From 940aaa0cbed168a2554d05222e11c0309d921e0d Mon Sep 17 00:00:00 2001 From: shihjeff Date: Wed, 21 Jul 2021 09:09:36 -0700 Subject: [PATCH] [201911] [Innovium] Update Cameo & Wistron Drivers (#7855) Fix #8068 Update Innovium configs on Cameo and Wistron platforms --- .../config_128x100G_Cameo-esc600-128q.yaml | 1 + .../plugins/eeprom.py | 2 +- .../plugins/psuutil.py | 25 +- .../plugins/sfputil.py | 181 +- .../pmon_daemon_control.json | 3 +- .../config_32x100G_Cameo-esc601-32q.yaml | 1 + .../config_32x200G_Cameo-esc601-32q.yaml | 1 + .../plugins/eeprom.py | 2 +- .../plugins/sfputil.py | 2 +- .../pmon_daemon_control.json | 3 +- .../plugins/eeprom.py | 2 +- .../plugins/sfputil.py | 2 +- .../pmon_daemon_control.json | 3 +- .../x86_64-cameo_escc601_32q-r0/default_sku | 1 + .../escc601-32q}/buffers.json.j2 | 15 +- .../buffers_defaults_def_lossy.j2 | 6 +- .../escc601-32q}/buffers_defaults_t1.j2 | 15 +- .../config_32x200G_Cameo-escc601-32q.yaml | 397 + .../escc601-32q/innovium.55610 | 62 + .../escc601-32q}/ivm.sai.config.yaml | 6 +- .../escc601-32q/ivm.sai.datapath.config.yaml | 9 + .../escc601-32q}/pg_profile_lookup.ini | 0 .../escc601-32q/port_config.ini | 33 + .../escc601-32q}/qos.json.j2 | 0 .../escc601-32q}/qos_defaults_def_lossy.j2 | 0 .../escc601-32q}/qos_defaults_t1.j2 | 0 .../escc601-32q}/sai.profile | 0 .../installer.conf | 3 + .../platform_reboot | 16 + .../plugins/eeprom.py | 12 + .../plugins/led_monitor_plugin.py | 84 + .../plugins/psuutil.py | 95 + .../plugins/sfputil.py | 166 + .../pmon_daemon_control.json | 3 + .../x86_64-cameo_escc601_32q-r0/sensors.conf | 3 + .../topo.conf | 0 .../plugins/eeprom.py | 2 +- .../plugins/psuutil.py | 22 +- .../plugins/sfputil.py | 45 +- .../pmon_daemon_control.json | 3 +- .../cameo/x86_64-fabric_1208i-r0/default_sku | 1 - .../fabric-1208i/config_32x400G_fab128.yaml | 417 - .../fabric-1208i/config_64x100G_fab128.yaml | 833 - .../fabric-1208i/innovium.77700_A | 59 - .../fabric-1208i/innovium.77700_B | 59 - .../fabric-1208i/ivm.sai.datapath.config.yaml | 9 - .../fabric-1208i/port_config.ini | 65 - .../config_64x100G_midstone200i.yaml | 1 + .../config_128x100G_midstone200i.yaml | 1 + .../config_32x400G_midstone200i.yaml | 1 + .../config_64x100G_nrz_midstone200i.yaml | 1 + .../config_64x100G_nrz_midstone200i.yaml | 1 + .../config_64x200G_midstone200i.yaml | 1 + .../config_32x400G_Delta-et-c032if.yaml | 1 + .../config_128x100G_Delta-et-c032if.yaml | 1 + .../config_32x100G_Delta-et-c032if.yaml | 1 + .../config_32x200G_Delta-et-c032if.yaml | 1 + .../config_32x400G_Delta-et-c032if.yaml | 1 + .../config_64x100G_Delta-et-c032if.yaml | 1 + .../config_64x200G_Delta-et-c032if.yaml | 1 + .../CSV/TL7_DAC_1M.csv | 342 + .../CSV/TL7_DAC_3M.csv | 342 + .../CSV/TL7_Optics.csv | 289 + .../config_32x400G_wistron_sw_to3200k.yaml | 12 +- .../Wistron_sw_to3200k/ivm.sai.config.yaml | 2 +- ...g_104x1025G_6x100G_wistron_sw_to3200k.yaml | 12 +- .../ivm.sai.config.yaml | 2 +- ...fig_24x400G_8x100G_wistron_sw_to3200k.yaml | 12 +- .../ivm.sai.config.yaml | 2 +- .../config_32x100G_wistron_sw_to3200k.yaml | 12 +- .../ivm.sai.config.yaml | 2 +- ...nfig_72x25G_6x400G_wistron_sw_to3200k.yaml | 12 +- .../ivm.sai.config.yaml | 2 +- .../libplatform.so | Bin 26640 -> 0 bytes platform/innovium/one-image.mk | 9 +- platform/innovium/platform-modules-cameo.mk | 6 + .../debian/cameo_platform_version.sh | 14 + .../debian/changelog | 6 + .../debian/compat | 1 + .../debian/control | 26 + .../sonic-platform-modules-cameo/debian/rules | 48 + .../sonic-platform-cameo-esc600-128q.install | 9 + .../sonic-platform-cameo-esc600-128q.postinst | 7 + .../sonic-platform-cameo-esc601-32q.install | 4 + .../sonic-platform-cameo-esc601-32q.postinst | 8 + .../sonic-platform-cameo-esc602-32q.install | 4 + .../sonic-platform-cameo-esc602-32q.postinst | 8 + .../sonic-platform-cameo-escc601-32q.install | 4 + .../sonic-platform-cameo-escc601-32q.postinst | 8 + .../sonic-platform-cameo-esqc610-56sq.install | 4 + ...sonic-platform-cameo-esqc610-56sq.postinst | 7 + .../credo_baldeagle/bin/credo_auto1357.sh | 28 +- .../credo_baldeagle/bin/credo_auto2468.sh | 28 +- .../credo_sdk_fw/BE.fw.2.15.04.bin | Bin 50324 -> 0 bytes .../credo_sdk_fw/BE2.fw.2.14.18.bin | Bin 47172 -> 0 bytes .../credo_sdk_fw/BE2.fw.2.15.04.bin | Bin 47624 -> 0 bytes .../credo_sdk_fw/BE2.fw.2.18.43.bin | Bin 0 -> 54308 bytes .../esc600-128q/credo_baldeagle/lib/Makefile | 11 + .../credo_baldeagle/lib/cameo_mdio.c | 404 + .../credo_baldeagle/lib/cameo_mdio.h | 12 + .../credo_baldeagle/lib/libcameo_mdio.so | Bin 17312 -> 0 bytes ...gleSdk_v2_12_00_20190715_cameo_gearbox.pyc | Bin 502922 -> 0 bytes .../python_wheel/BaldEagleSdk_v2_14_18.pyc | Bin 499630 -> 0 bytes .../python_wheel/BaldEagleSdk_v2_18.py | 14231 ++++++++++++++++ .../python_wheel/baldeagle_eagle_reg.py | 239 + .../python_wheel/baldeagle_eagle_reg.pyc | Bin 8360 -> 0 bytes .../python_wheel/baldeagle_phoenix_reg.py | 300 + .../python_wheel/baldeagle_phoenix_reg.pyc | Bin 9781 -> 0 bytes .../esc600-128q/modules/Makefile | 3 + .../esc600-128q/modules/pmbus.h | 4 +- .../modules/x86-64-cameo-esc600-128q-common.c | 382 + .../modules/x86-64-cameo-esc600-128q-common.h | 25 + .../modules/x86-64-cameo-esc600-128q-fan.c | 358 + .../modules/x86-64-cameo-esc600-128q-fan.h | 15 + .../modules/x86-64-cameo-esc600-128q-led.c | 518 + .../modules/x86-64-cameo-esc600-128q-led.h | 18 + .../modules/x86-64-cameo-esc600-128q-power.c | 1095 ++ .../modules/x86-64-cameo-esc600-128q-power.h | 148 + .../modules/x86-64-cameo-esc600-128q-sys.c | 2011 +++ .../modules/x86-64-cameo-esc600-128q-sys.h | 64 + .../x86-64-cameo-esc600-128q-thermal.c | 171 + .../x86-64-cameo-esc600-128q-thermal.h | 73 + .../modules/x86-64-cameo-esc600-128q.c | 4545 ----- .../modules/x86-64-cameo-esc600-128q.h | 1655 +- .../esc600-128q/platform_setup.py | 14 + .../esc600-128q/setup.py | 2 +- .../esc600-128q/sonic_platform/__init__.py | 1 + .../esc600-128q/sonic_platform/chassis.py | 335 + .../esc600-128q/sonic_platform/component.py | 104 + .../esc600-128q/sonic_platform/eeprom.py | 144 + .../esc600-128q/sonic_platform/fan.py | 158 + .../esc600-128q/sonic_platform/platDev.py | 363 + .../esc600-128q/sonic_platform/platform.py | 22 + .../esc600-128q/sonic_platform/psu.py | 193 + .../esc600-128q/sonic_platform/sfp.py | 1636 ++ .../esc600-128q/sonic_platform/thermal.py | 200 + .../templates/cameo_esc600_util.py.j2 | 1291 +- .../utils/cameo_esc600_platform.sh | 13 + .../esc600-128q/utils/cameo_esc600_sensors.py | 406 +- .../utils/esc600_128q_dynamic_hotswap.py | 102 +- .../esc600-128q/utils/esc600_128q_slot_power | 16 +- .../esc601-32q/setup.py | 14 + .../esc601-32q/sonic_platform/__init__.py | 1 + .../esc601-32q/sonic_platform/chassis.py | 330 + .../esc601-32q/sonic_platform/component.py | 103 + .../esc601-32q/sonic_platform/eeprom.py | 144 + .../esc601-32q/sonic_platform/fan.py | 165 + .../esc601-32q/sonic_platform/platDev.py | 364 + .../esc601-32q/sonic_platform/platform.py | 22 + .../esc601-32q/sonic_platform/psu.py | 221 + .../esc601-32q/sonic_platform/sfp.py | 1179 ++ .../esc601-32q/sonic_platform/thermal.py | 200 + .../modules/x86-64-cameo-esc602-32q-power.c | 30 +- .../modules/x86-64-cameo-esc602-32q-power.h | 4 +- .../modules/x86-64-cameo-esc602-32q-sys.c | 6 +- .../modules/x86-64-cameo-esc602-32q.h | 14 +- .../modules/x86-64-cameo-esc602-32q.txt | 38 - .../esc602-32q/setup.py | 14 + .../esc602-32q/sonic_platform/__init__.py | 1 + .../esc602-32q/sonic_platform/chassis.py | 330 + .../esc602-32q/sonic_platform/component.py | 103 + .../esc602-32q/sonic_platform/eeprom.py | 144 + .../esc602-32q/sonic_platform/fan.py | 158 + .../esc602-32q/sonic_platform/platDev.py | 359 + .../esc602-32q/sonic_platform/platform.py | 22 + .../esc602-32q/sonic_platform/psu.py | 193 + .../esc602-32q/sonic_platform/sfp.py | 1175 ++ .../esc602-32q/sonic_platform/thermal.py | 200 + .../escc601-32q/modules/Makefile | 5 + .../escc601-32q/modules/at24_smbus.c | 847 + .../escc601-32q/modules/nct7511.c | 765 + .../modules/x86-64-cameo-escc601-32q-common.c | 368 + .../modules/x86-64-cameo-escc601-32q-common.h | 25 + .../modules/x86-64-cameo-escc601-32q-fan.c | 365 + .../modules/x86-64-cameo-escc601-32q-fan.h | 12 + .../modules/x86-64-cameo-escc601-32q-led.c | 220 + .../modules/x86-64-cameo-escc601-32q-led.h | 12 + .../modules/x86-64-cameo-escc601-32q-power.c | 652 + .../modules/x86-64-cameo-escc601-32q-power.h | 38 + .../modules/x86-64-cameo-escc601-32q-qsfp.c | 584 + .../modules/x86-64-cameo-escc601-32q-qsfp.h | 187 + .../modules/x86-64-cameo-escc601-32q-sys.c | 789 + .../modules/x86-64-cameo-escc601-32q-sys.h | 23 + .../x86-64-cameo-escc601-32q-thermal.c | 271 + .../x86-64-cameo-escc601-32q-thermal.h | 45 + .../modules/x86-64-cameo-escc601-32q.h | 1044 ++ .../escc601-32q/modules/zrh2800k2.c | 684 + .../escc601-32q/scripts/sensors | 8 + .../service/escc601-platform-init.service | 14 + .../escc601-32q/setup.py | 14 + .../escc601-32q/sonic_platform/__init__.py | 1 + .../escc601-32q/sonic_platform/chassis.py | 330 + .../escc601-32q/sonic_platform/component.py | 103 + .../escc601-32q/sonic_platform/eeprom.py | 144 + .../escc601-32q/sonic_platform/fan.py | 158 + .../escc601-32q/sonic_platform/platDev.py | 359 + .../escc601-32q/sonic_platform/platform.py | 22 + .../escc601-32q/sonic_platform/psu.py | 193 + .../escc601-32q/sonic_platform/sfp.py | 1175 ++ .../escc601-32q/sonic_platform/thermal.py | 200 + .../templates/cameo_escc601_util.py.j2 | 737 + .../utils/cameo_escc601_platform.sh | 10 + .../utils/cameo_escc601_sensors.py | 318 + .../escc601-32q/utils/cameo_escc601_startup | 17 + .../escc601-32q/utils/halt | 18 + .../escc601-32q/utils/poweroff | 18 + .../escc601-32q/utils/shutdown | 18 + .../esqc610-56sq/modules/Makefile | 6 +- .../esqc610-56sq/modules/nct7511.mod.c | 52 - .../x86-64-cameo-esqc610-56sq-common.c | 376 + .../x86-64-cameo-esqc610-56sq-common.h | 25 + .../modules/x86-64-cameo-esqc610-56sq-fan.c | 339 + .../modules/x86-64-cameo-esqc610-56sq-fan.h | 12 + .../modules/x86-64-cameo-esqc610-56sq-led.c | 220 + .../modules/x86-64-cameo-esqc610-56sq-led.h | 12 + .../modules/x86-64-cameo-esqc610-56sq-power.c | 652 + .../modules/x86-64-cameo-esqc610-56sq-power.h | 38 + .../modules/x86-64-cameo-esqc610-56sq-qsfp.c | 478 + .../modules/x86-64-cameo-esqc610-56sq-qsfp.h | 75 + .../modules/x86-64-cameo-esqc610-56sq-sfp.c | 511 + .../modules/x86-64-cameo-esqc610-56sq-sfp.h | 218 + .../modules/x86-64-cameo-esqc610-56sq-sys.c | 789 + .../modules/x86-64-cameo-esqc610-56sq-sys.h | 23 + .../x86-64-cameo-esqc610-56sq-thermal.c | 286 + .../x86-64-cameo-esqc610-56sq-thermal.h | 50 + .../modules/x86-64-cameo-esqc610-56sq.h | 1620 +- .../esqc610-56sq/modules/zrh2800k2.mod.c | 54 - .../esqc610-56sq/setup.py | 14 + .../esqc610-56sq/sonic_platform/__init__.py | 1 + .../esqc610-56sq/sonic_platform/chassis.py | 330 + .../esqc610-56sq/sonic_platform/component.py | 103 + .../esqc610-56sq/sonic_platform/eeprom.py | 144 + .../esqc610-56sq/sonic_platform/fan.py | 158 + .../esqc610-56sq/sonic_platform/platDev.py | 381 + .../esqc610-56sq/sonic_platform/platform.py | 22 + .../esqc610-56sq/sonic_platform/psu.py | 193 + .../esqc610-56sq/sonic_platform/sfp.py | 1176 ++ .../esqc610-56sq/sonic_platform/thermal.py | 200 + .../templates/cameo_esqc610_util.py.j2 | 18 +- .../utils/cameo_esqc610_platform.sh | 9 + .../utils/cameo_esqc610_sensors.py | 349 +- .../debian/changelog | 5 + .../debian/compat | 1 + .../debian/control | 11 + .../debian/rules | 40 + .../sonic-platform-wistron-sw-to3200k.install | 5 + ...sonic-platform-wistron-sw-to3200k.postinst | 36 + .../sw-to3200k/service/to3200k-pld.service | 12 + .../sw-to3200k/utils/platform_pld | 4 + 249 files changed, 52432 insertions(+), 8179 deletions(-) create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/default_sku rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/buffers.json.j2 (93%) rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/buffers_defaults_def_lossy.j2 (87%) rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/buffers_defaults_t1.j2 (93%) create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/config_32x200G_Cameo-escc601-32q.yaml create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/innovium.55610 rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/ivm.sai.config.yaml (66%) mode change 100755 => 100644 create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/ivm.sai.datapath.config.yaml rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/pg_profile_lookup.ini (100%) create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/port_config.ini rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/qos.json.j2 (100%) rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/qos_defaults_def_lossy.j2 (100%) mode change 100755 => 100644 rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/qos_defaults_t1.j2 (100%) mode change 100755 => 100644 rename device/cameo/{x86_64-fabric_1208i-r0/fabric-1208i => x86_64-cameo_escc601_32q-r0/escc601-32q}/sai.profile (100%) create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/installer.conf create mode 100755 device/cameo/x86_64-cameo_escc601_32q-r0/platform_reboot create mode 100755 device/cameo/x86_64-cameo_escc601_32q-r0/plugins/eeprom.py create mode 100755 device/cameo/x86_64-cameo_escc601_32q-r0/plugins/led_monitor_plugin.py create mode 100755 device/cameo/x86_64-cameo_escc601_32q-r0/plugins/psuutil.py create mode 100755 device/cameo/x86_64-cameo_escc601_32q-r0/plugins/sfputil.py create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/pmon_daemon_control.json create mode 100644 device/cameo/x86_64-cameo_escc601_32q-r0/sensors.conf rename device/cameo/{x86_64-fabric_1208i-r0 => x86_64-cameo_escc601_32q-r0}/topo.conf (100%) delete mode 100644 device/cameo/x86_64-fabric_1208i-r0/default_sku delete mode 100644 device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_32x400G_fab128.yaml delete mode 100644 device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_64x100G_fab128.yaml delete mode 100644 device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_A delete mode 100644 device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_B delete mode 100644 device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/ivm.sai.datapath.config.yaml delete mode 100644 device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/port_config.ini create mode 100644 device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_1M.csv create mode 100644 device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_3M.csv create mode 100644 device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_Optics.csv delete mode 100644 device/wistron/x86_64-wistron_sw_to3200k-r0/libplatform.so create mode 100755 platform/innovium/sonic-platform-modules-cameo/debian/cameo_platform_version.sh create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/changelog create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/compat create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/control create mode 100755 platform/innovium/sonic-platform-modules-cameo/debian/rules create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.install create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.postinst create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.install create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.postinst create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.install create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.postinst create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.install create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.postinst create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.install create mode 100644 platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.postinst delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE.fw.2.15.04.bin delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.14.18.bin delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.15.04.bin create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.18.43.bin create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/Makefile create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.h delete mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/libcameo_mdio.so delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_12_00_20190715_cameo_gearbox.pyc delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_14_18.pyc create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_18.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_eagle_reg.py delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_eagle_reg.pyc create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_phoenix_reg.py delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_phoenix_reg.pyc create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.h delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.c create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/platform_setup.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/__init__.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/chassis.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/component.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/eeprom.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/fan.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platDev.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platform.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/psu.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/sfp.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/thermal.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_platform.sh create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/setup.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/__init__.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/chassis.py create mode 100644 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/component.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/eeprom.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/fan.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platDev.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platform.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/psu.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/sfp.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/thermal.py delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.txt create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/setup.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/__init__.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/chassis.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/component.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/eeprom.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/fan.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platDev.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platform.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/psu.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/sfp.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/thermal.py create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/Makefile create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/at24_smbus.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/nct7511.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/zrh2800k2.c create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/scripts/sensors create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/service/escc601-platform-init.service create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/setup.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/__init__.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/chassis.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/component.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/eeprom.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/fan.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platDev.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platform.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/psu.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/sfp.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/thermal.py create mode 100644 platform/innovium/sonic-platform-modules-cameo/escc601-32q/templates/cameo_escc601_util.py.j2 create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_platform.sh create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_sensors.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_startup create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/halt create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/poweroff create mode 100755 platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/shutdown delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/nct7511.mod.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.h create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.c create mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.h delete mode 100644 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/zrh2800k2.mod.c create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/setup.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/__init__.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/chassis.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/component.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/eeprom.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/fan.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platDev.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platform.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/psu.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/sfp.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/thermal.py create mode 100755 platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_platform.sh create mode 100644 platform/innovium/sonic-platform-modules-wistron/debian/changelog create mode 100644 platform/innovium/sonic-platform-modules-wistron/debian/compat create mode 100644 platform/innovium/sonic-platform-modules-wistron/debian/control create mode 100644 platform/innovium/sonic-platform-modules-wistron/debian/rules create mode 100644 platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.install create mode 100644 platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.postinst create mode 100755 platform/innovium/sonic-platform-modules-wistron/sw-to3200k/service/to3200k-pld.service create mode 100755 platform/innovium/sonic-platform-modules-wistron/sw-to3200k/utils/platform_pld diff --git a/device/cameo/x86_64-cameo_esc600_128q-r0/esc600-128q/config_128x100G_Cameo-esc600-128q.yaml b/device/cameo/x86_64-cameo_esc600_128q-r0/esc600-128q/config_128x100G_Cameo-esc600-128q.yaml index a887e1c982..0664c2172c 100644 --- a/device/cameo/x86_64-cameo_esc600_128q-r0/esc600-128q/config_128x100G_Cameo-esc600-128q.yaml +++ b/device/cameo/x86_64-cameo_esc600_128q-r0/esc600-128q/config_128x100G_Cameo-esc600-128q.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/eeprom.py b/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/eeprom.py index f0f19ba393..5b6ed4606b 100755 --- a/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/eeprom.py +++ b/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/eeprom.py @@ -2,7 +2,7 @@ try: from sonic_eeprom import eeprom_tlvinfo -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + "- required module not found") class board(eeprom_tlvinfo.TlvInfoDecoder): diff --git a/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/psuutil.py b/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/psuutil.py index 0d807ffd9f..16737add88 100755 --- a/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/psuutil.py +++ b/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/psuutil.py @@ -11,14 +11,11 @@ try: except ImportError as e: raise ImportError(str(e) + "- required module not found") -attr_path = '/sys/class/hwmon/hwmon2/device/' +attr_path = '/sys/class/hwmon/hwmon2/device/ESC600_POWER/' class PsuUtil(PsuBase): """Platform-specific PSUutil class""" - SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-10/10-0050", - "/sys/bus/i2c/devices/i2c-9/9-0050"] - def __init__(self): PsuBase.__init__(self) @@ -56,18 +53,16 @@ class PsuUtil(PsuBase): faulty """ status = 0 - attr_file = 'psu_status' - status_path = attr_path+'/ESC600_PSU/' + attr_file + attr_file = 'psu{}_good'.format(index) + status_path = attr_path + attr_file try: reg_file = open(status_path, 'r') except IOError as e: print( "Error: unable to open file: %s" % str(e)) return False - text_lines = reg_file.read() + text = reg_file.read() - search_str = "PSU {} is power good".format(index) - - if search_str in text_lines: + if int(text) == 1: status = 1 reg_file.close() @@ -82,18 +77,16 @@ class PsuUtil(PsuBase): :return: Boolean, True if PSU is plugged, False if not """ status = 0 - attr_file ='psu_present' - presence_path = attr_path+'ESC600_PSU/' + attr_file + attr_file ='psu{}_prnt'.format(index) + presence_path = attr_path + attr_file try: reg_file = open(presence_path, 'r') except IOError as e: print( "Error: unable to open file: %s" % str(e)) return False - text_lines = reg_file.read() + text = reg_file.read() - search_str = "PSU {} is present".format(index) - - if search_str in text_lines: + if int(text) == 1: status = 1 reg_file.close() diff --git a/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/sfputil.py b/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/sfputil.py index 92079cb69e..327ba748cc 100755 --- a/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/sfputil.py +++ b/device/cameo/x86_64-cameo_esc600_128q-r0/plugins/sfputil.py @@ -1,37 +1,41 @@ #!/usr/bin/env python try: - import os import time - from sonic_sfp.sfputilbase import SfpUtilBase -except ImportError, e: - raise ImportError (str(e) + "- required module not found") + import json + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PLATFORM_INSTALL_INFO_FILE = "/etc/sonic/platform_install.json" +PLATFORM_SFP_GROUPS = ['SFP-G11', 'SFP-G12', 'SFP-G21', 'SFP-G22', 'SFP-G31', 'SFP-G32', 'SFP-G41', 'SFP-G42', + 'SFP-G51', + 'SFP-G52', 'SFP-G61', 'SFP-G62', 'SFP-G71', 'SFP-G72', 'SFP-G81', 'SFP-G82'] +PLATFORM_CARD_LIST = ['PHY_CPLD_1', 'PHY_CPLD_2', 'PHY_CPLD_3', 'PHY_CPLD_4', 'PHY_CPLD_5', 'PHY_CPLD_6', 'PHY_CPLD_7', + 'PHY_CPLD_8'] -attr_path = '/sys/class/hwmon/hwmon2/device/' -qsfp_sysfile_path = '/sys/bus/i2c/devices/{}-0032/' -i2c_bus_base = 0 class SfpUtil(SfpUtilBase): """Platform specific SfpUtill class""" _port_start = 0 _port_end = 127 - _port_in_block = 128 _port_to_eeprom_mapping = {} _global_port_pres_dict = {} - _port_position_mapping = [] + _port_status_mapping = [] def __init__(self): - self.create_port_position_mapping() - eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom" + eeprom_path = "{}/eeprom" + eeprom_path_list, status_path_list = self.get_sfp_path() + self._port_end = len(status_path_list) - 1 + self._port_status_mapping = status_path_list for x in range(self._port_start, self._port_end + 1): - port_eeprom_path = eeprom_path.format(self._port_position_mapping[x][2]) + port_eeprom_path = eeprom_path.format(eeprom_path_list[x]) self._port_to_eeprom_mapping[x] = port_eeprom_path - - self.init_global_port_presence() + self.init_global_port_presence() SfpUtilBase.__init__(self) - def get_attr_value(self,attr_path): + def get_attr_value(self, attr_path): retval = 'ERR' try: with open(attr_path, 'r') as fd: @@ -39,93 +43,41 @@ class SfpUtil(SfpUtilBase): except Exception as error: print("Unable to open ", attr_path, " file !") return retval - retval = retval.rstrip('\r\n') fd.close() return retval - def bmc_is_exist(self): - value = '' - bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESC600_SYS/bmc_present' - if os.path.exists(bmc_filePath): - value = self.get_attr_value(bmc_filePath) - if value.find('not') < 0: - return True - else: - return False - else: - return False - - def get_inserted_slots(self): - """ return list of inserted slots """ - path = attr_path+'ESC600_Module/module_insert' - try: - reg_file = open(path, 'r') - except IOError as e: - print( "Error: unable to open file: %s" % str(e)) - return False - - text_lines = reg_file.readlines() - reg_file.close() - - slots = [] - for line in text_lines: - if "is present" in line: - slots.append(int(filter(str.isdigit, line))) - - return slots - - def create_port_position_mapping(self): - inserted_slots = [] - ports_in_slots = [0]*8 - # record inserted slots - inserted_slots = self.get_inserted_slots() - - # record the numbers of port on each slot - for slot in inserted_slots: - path = qsfp_sysfile_path.format(slot+i2c_bus_base) + 'portnum' - ports_in_slots[slot-1] = int(self.get_attr_value(path)) - - # mapping - nport = 0 - if self.bmc_is_exist(): - PATH_71_BUS_BASE = 9 - else: - PATH_71_BUS_BASE = 33 - - sfp_bus = PATH_71_BUS_BASE - for i in range(0,8): - for x in range(0,ports_in_slots[i]): - self._port_position_mapping.append((i, x+1, sfp_bus+x)) - nport = nport + 1 - - if ports_in_slots[i] == 4: - sfp_bus = sfp_bus + 8 - elif ports_in_slots[i] == 16: - sfp_bus = sfp_bus + 16 - - self._port_end = nport-1 - - + def get_sfp_path(self): + eeprom_path_list=[] + status_path_list=[] + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for sfp_group_name in PLATFORM_SFP_GROUPS: + sfp_group = install_info[2][sfp_group_name] + for i in range(0,sfp_group['number']): + eeprom_path_list.append(sfp_group['paths'][i]) + for card_name in PLATFORM_CARD_LIST: + card = install_info[1][card_name] + if card['portnum'] == 0: + continue + for i in range(1,card['portnum']+1): + present_file = card['hwmon_path']+'/device/'+'QSFP_present_{}'.format(i) + lp_file = card['hwmon_path']+'/device/'+'QSFP_low_power_{}'.format(i) + reset_file = card['hwmon_path']+'/device/'+'QSFP_reset_{}'.format(i) + status_path_list.append([present_file,lp_file,reset_file]) + return eeprom_path_list, status_path_list def reset(self, port_num): # Check for invalid port_num if port_num < self._port_start or port_num > self._port_end: return False - - pos = self._port_position_mapping[port_num] - path = qsfp_sysfile_path.format(pos[0]+i2c_bus_base+1)+'QSFP_reset_{}'.format(pos[1]) + pos = self._port_status_mapping[port_num] + path = pos[2] try: reg_file = open(path, 'w') except IOError as e: - print( "Error: unable to open file: %s" % str(e)) + print("Error: unable to open file: %s" % str(e)) return False - - #toggle reset - #reg_file.seek(0) - reg_file.write(str(port_num+1)) - #time.sleep(1) - #reg_file.seek(0) - #reg_file.write('0') + reg_file.write(str(port_num + 1)) reg_file.close() return True @@ -133,86 +85,71 @@ class SfpUtil(SfpUtilBase): # Check for invalid port_num if port_num < self.port_start or port_num > self.port_end: return False - - pos = self._port_position_mapping[port_num] - path = qsfp_sysfile_path.format(pos[0]+i2c_bus_base+1)+'QSFP_low_power_{}'.format(pos[1]) - + pos = self._port_status_mapping[port_num] + path = pos[1] try: reg_file = open(path, 'w') except IOError as e: - print( "Error: unable to open file: %s" % str(e)) + print("Error: unable to open file: %s" % str(e)) return False - # the gpio pin is ACTIVE_HIGH if lpmode is True: val = "1" else: val = "0" - # write value to gpio reg_file.seek(0) reg_file.write(val) reg_file.close() - return True def get_low_power_mode(self, port_num): # Check for invalid port_num if port_num < self._port_start or port_num > self._port_end: return False - - pos = self._port_position_mapping[port_num] - path = qsfp_sysfile_path.format(pos[0]+i2c_bus_base+1)+'QSFP_low_power_{}'.format(pos[1]) - + pos = self._port_status_mapping[port_num] + path = pos[1] res = self.get_attr_value(path) if res == 'ERR': return False - if int(res) == 1: return True - return False - + def get_presence(self, port_num): # Check for invalid port_num if port_num < self._port_start or port_num > self._port_end: return False - - pos = self._port_position_mapping[port_num] - path = qsfp_sysfile_path.format(pos[0]+i2c_bus_base+1)+'QSFP_present_{}'.format(pos[1]) + pos = self._port_status_mapping[port_num] + path = pos[0] res = self.get_attr_value(path) if res == 'ERR': return False - if int(res) == 1: return True - return False def init_global_port_presence(self): for port_num in range(self.port_start, (self.port_end + 1)): presence = self.get_presence(port_num) - if(presence): + if (presence): self._global_port_pres_dict[port_num] = '1' else: - self._global_port_pres_dict[port_num] = '0' - + self._global_port_pres_dict[port_num] = '0' + def get_transceiver_change_event(self, timeout=0): port_dict = {} while True: for port_num in range(self.port_start, (self.port_end + 1)): presence = self.get_presence(port_num) - if(presence and self._global_port_pres_dict[port_num] == '0'): + if (presence and self._global_port_pres_dict[port_num] == '0'): self._global_port_pres_dict[port_num] = '1' port_dict[port_num] = '1' - elif(not presence and - self._global_port_pres_dict[port_num] == '1'): + elif (not presence and self._global_port_pres_dict[port_num] == '1'): self._global_port_pres_dict[port_num] = '0' port_dict[port_num] = '0' - - if(len(port_dict) > 0): + if (len(port_dict) > 0): return True, port_dict - time.sleep(1) @property @@ -225,8 +162,8 @@ class SfpUtil(SfpUtilBase): @property def qsfp_ports(self): - return range(0, self._port_in_block + 1) + return range(0, self._port_end + 1) - @property + @property def port_to_eeprom_mapping(self): - return self._port_to_eeprom_mapping + return self._port_to_eeprom_mapping diff --git a/device/cameo/x86_64-cameo_esc600_128q-r0/pmon_daemon_control.json b/device/cameo/x86_64-cameo_esc600_128q-r0/pmon_daemon_control.json index 44871c057e..94592fa8ce 100644 --- a/device/cameo/x86_64-cameo_esc600_128q-r0/pmon_daemon_control.json +++ b/device/cameo/x86_64-cameo_esc600_128q-r0/pmon_daemon_control.json @@ -1,4 +1,3 @@ { - "skip_ledd": true, - "skip_thermalctld": true + "skip_ledd": true } diff --git a/device/cameo/x86_64-cameo_esc601_32q-r0/esc601-32q/config_32x100G_Cameo-esc601-32q.yaml b/device/cameo/x86_64-cameo_esc601_32q-r0/esc601-32q/config_32x100G_Cameo-esc601-32q.yaml index 6ecbfb1a30..ec613635d1 100644 --- a/device/cameo/x86_64-cameo_esc601_32q-r0/esc601-32q/config_32x100G_Cameo-esc601-32q.yaml +++ b/device/cameo/x86_64-cameo_esc601_32q-r0/esc601-32q/config_32x100G_Cameo-esc601-32q.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/cameo/x86_64-cameo_esc601_32q-r0/escc600-32q/config_32x200G_Cameo-esc601-32q.yaml b/device/cameo/x86_64-cameo_esc601_32q-r0/escc600-32q/config_32x200G_Cameo-esc601-32q.yaml index 5b676f2d18..53b8ce036f 100644 --- a/device/cameo/x86_64-cameo_esc601_32q-r0/escc600-32q/config_32x200G_Cameo-esc601-32q.yaml +++ b/device/cameo/x86_64-cameo_esc601_32q-r0/escc600-32q/config_32x200G_Cameo-esc601-32q.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/eeprom.py b/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/eeprom.py index f0f19ba393..5b6ed4606b 100644 --- a/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/eeprom.py +++ b/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/eeprom.py @@ -2,7 +2,7 @@ try: from sonic_eeprom import eeprom_tlvinfo -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + "- required module not found") class board(eeprom_tlvinfo.TlvInfoDecoder): diff --git a/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/sfputil.py b/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/sfputil.py index da280f79e7..8fd0f8f911 100644 --- a/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/sfputil.py +++ b/device/cameo/x86_64-cameo_esc601_32q-r0/plugins/sfputil.py @@ -4,7 +4,7 @@ try: import time import json from sonic_sfp.sfputilbase import SfpUtilBase -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + "- required module not found") attr_path = '/sys/class/hwmon/hwmon2/device/' diff --git a/device/cameo/x86_64-cameo_esc601_32q-r0/pmon_daemon_control.json b/device/cameo/x86_64-cameo_esc601_32q-r0/pmon_daemon_control.json index 44871c057e..94592fa8ce 100644 --- a/device/cameo/x86_64-cameo_esc601_32q-r0/pmon_daemon_control.json +++ b/device/cameo/x86_64-cameo_esc601_32q-r0/pmon_daemon_control.json @@ -1,4 +1,3 @@ { - "skip_ledd": true, - "skip_thermalctld": true + "skip_ledd": true } diff --git a/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/eeprom.py b/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/eeprom.py index f0f19ba393..5b6ed4606b 100755 --- a/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/eeprom.py +++ b/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/eeprom.py @@ -2,7 +2,7 @@ try: from sonic_eeprom import eeprom_tlvinfo -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + "- required module not found") class board(eeprom_tlvinfo.TlvInfoDecoder): diff --git a/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/sfputil.py b/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/sfputil.py index 4719155efc..bad935f6ea 100755 --- a/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/sfputil.py +++ b/device/cameo/x86_64-cameo_esc602_32q-r0/plugins/sfputil.py @@ -4,7 +4,7 @@ try: import time import json from sonic_sfp.sfputilbase import SfpUtilBase -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + "- required module not found") attr_path = '/sys/class/hwmon/hwmon2/device/' diff --git a/device/cameo/x86_64-cameo_esc602_32q-r0/pmon_daemon_control.json b/device/cameo/x86_64-cameo_esc602_32q-r0/pmon_daemon_control.json index 44871c057e..94592fa8ce 100644 --- a/device/cameo/x86_64-cameo_esc602_32q-r0/pmon_daemon_control.json +++ b/device/cameo/x86_64-cameo_esc602_32q-r0/pmon_daemon_control.json @@ -1,4 +1,3 @@ { - "skip_ledd": true, - "skip_thermalctld": true + "skip_ledd": true } diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/default_sku b/device/cameo/x86_64-cameo_escc601_32q-r0/default_sku new file mode 100644 index 0000000000..96da15b889 --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/default_sku @@ -0,0 +1 @@ +escc601-32q t1 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers.json.j2 b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers.json.j2 similarity index 93% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers.json.j2 rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers.json.j2 index 93dac6b199..380e5d6a4d 100644 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers.json.j2 +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers.json.j2 @@ -76,16 +76,13 @@ }, "BUFFER_POOL": { "ingress_lossless_pool": { - "size": "47218432", + "size": "23201280", "type": "ingress", - "mode": "dynamic", - "xoff": "17708800" + "xoff": "7104000" }, "lossy_pool": { - "size": "18874368", - "type": "egress", - "mode": "dynamic", - "xoff": "0" + "size": "27601920", + "type": "egress" } }, "BUFFER_PROFILE": { @@ -99,12 +96,12 @@ "egress_lossless_profile": { "pool":"[BUFFER_POOL|ingress_lossless_pool]", "size":"0", - "static_th":"9497600" + "static_th":"23001600" }, "ingress_lossy_profile": { "pool":"[BUFFER_POOL|lossy_pool]", "size":"0", - "static_th":"9497600" + "static_th":"23001600" }, "egress_lossy_profile": { "pool":"[BUFFER_POOL|lossy_pool]", diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers_defaults_def_lossy.j2 b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers_defaults_def_lossy.j2 similarity index 87% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers_defaults_def_lossy.j2 rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers_defaults_def_lossy.j2 index 1a31812c26..82cfd1b96d 100644 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers_defaults_def_lossy.j2 +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers_defaults_def_lossy.j2 @@ -7,17 +7,15 @@ { "BUFFER_POOL": { "lossy_pool": { - "size": "56985600", + "size": "46003200", "type": "egress", - "mode": "dynamic", - "xoff": "0" } }, "BUFFER_PROFILE": { "ingress_lossy_profile": { "pool":"[BUFFER_POOL|lossy_pool]", "size":"0", - "static_th":"9497600" + "static_th":"23001600" }, "egress_lossy_profile": { "pool":"[BUFFER_POOL|lossy_pool]", diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers_defaults_t1.j2 b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers_defaults_t1.j2 similarity index 93% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers_defaults_t1.j2 rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers_defaults_t1.j2 index 93dac6b199..380e5d6a4d 100644 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/buffers_defaults_t1.j2 +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/buffers_defaults_t1.j2 @@ -76,16 +76,13 @@ }, "BUFFER_POOL": { "ingress_lossless_pool": { - "size": "47218432", + "size": "23201280", "type": "ingress", - "mode": "dynamic", - "xoff": "17708800" + "xoff": "7104000" }, "lossy_pool": { - "size": "18874368", - "type": "egress", - "mode": "dynamic", - "xoff": "0" + "size": "27601920", + "type": "egress" } }, "BUFFER_PROFILE": { @@ -99,12 +96,12 @@ "egress_lossless_profile": { "pool":"[BUFFER_POOL|ingress_lossless_pool]", "size":"0", - "static_th":"9497600" + "static_th":"23001600" }, "ingress_lossy_profile": { "pool":"[BUFFER_POOL|lossy_pool]", "size":"0", - "static_th":"9497600" + "static_th":"23001600" }, "egress_lossy_profile": { "pool":"[BUFFER_POOL|lossy_pool]", diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/config_32x200G_Cameo-escc601-32q.yaml b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/config_32x200G_Cameo-escc601-32q.yaml new file mode 100644 index 0000000000..5bf5c0dd2f --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/config_32x200G_Cameo-escc601-32q.yaml @@ -0,0 +1,397 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.55610" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + skip_pll_check: "false" + ilpm_enable: "1" + forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" + mac_clk: "1340" + sys_clk: "2000" + ifc_clk: "1000" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 47" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + queues: "42, 43, 44, 45, 46" + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "121" + lanes: "0:4" + serdes_group: "15" + speed: "200G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "125" + lanes: "4:4" + serdes_group: "15" + speed: "200G" + sysport: "125" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:4" + serdes_group: "14" + speed: "200G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "117" + lanes: "4:4" + serdes_group: "14" + speed: "200G" + sysport: "117" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:4" + serdes_group: "13" + speed: "200G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "109" + lanes: "4:4" + serdes_group: "13" + speed: "200G" + sysport: "109" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:4" + serdes_group: "12" + speed: "200G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "101" + lanes: "4:4" + serdes_group: "12" + speed: "200G" + sysport: "101" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:4" + serdes_group: "11" + speed: "200G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "93" + lanes: "4:4" + serdes_group: "11" + speed: "200G" + sysport: "93" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:4" + serdes_group: "10" + speed: "200G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "85" + lanes: "4:4" + serdes_group: "10" + speed: "200G" + sysport: "85" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:4" + serdes_group: "9" + speed: "200G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "77" + lanes: "4:4" + serdes_group: "9" + speed: "200G" + sysport: "77" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:4" + serdes_group: "8" + speed: "200G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "69" + lanes: "4:4" + serdes_group: "8" + speed: "200G" + sysport: "69" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:4" + serdes_group: "7" + speed: "200G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "61" + lanes: "4:4" + serdes_group: "7" + speed: "200G" + sysport: "61" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:4" + serdes_group: "6" + speed: "200G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "53" + lanes: "4:4" + serdes_group: "6" + speed: "200G" + sysport: "53" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:4" + serdes_group: "5" + speed: "200G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "45" + lanes: "4:4" + serdes_group: "5" + speed: "200G" + sysport: "45" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:4" + serdes_group: "4" + speed: "200G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "37" + lanes: "4:4" + serdes_group: "4" + speed: "200G" + sysport: "37" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:4" + serdes_group: "3" + speed: "200G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "29" + lanes: "4:4" + serdes_group: "3" + speed: "200G" + sysport: "29" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:4" + serdes_group: "2" + speed: "200G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "21" + lanes: "4:4" + serdes_group: "2" + speed: "200G" + sysport: "21" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:4" + serdes_group: "1" + speed: "200G" + sysport: "9" + type: "eth" + - fec: "KPFEC" + id: "13" + lanes: "4:4" + serdes_group: "1" + speed: "200G" + sysport: "13" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:4" + serdes_group: "0" + speed: "200G" + sysport: "1" + type: "eth" + - fec: "KPFEC" + id: "5" + lanes: "4:4" + serdes_group: "0" + speed: "200G" + sysport: "5" + type: "eth" +# Aux ports to be enabled later +# - id: "33" +# fec: "NONE" +# lanes: "0:1" +# serdes_group: "16" +# speed: "10G" +# sysport: "33" +# type: "mgmt 0" +# - id: "34" +# fec: "NONE" +# lanes: "1:1" +# serdes_group: "16" +# speed: "10G" +# sysport: "34" +# type: "mgmt 1" + isg: + - id: "0" + tx_polarity: "00001010" + rx_polarity: "01001001" + lane_swap: "46750132" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "1" + tx_polarity: "00011111" + rx_polarity: "01101001" + lane_swap: "46752130" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "2" + tx_polarity: "00101000" + rx_polarity: "11110111" + lane_swap: "57462301" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "3" + tx_polarity: "00111101" + rx_polarity: "00101101" + lane_swap: "67542301" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "4" + tx_polarity: "01110110" + rx_polarity: "01111101" + lane_swap: "76543021" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "5" + tx_polarity: "00100100" + rx_polarity: "01101010" + lane_swap: "76542103" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "6" + tx_polarity: "11000011" + rx_polarity: "11110101" + lane_swap: "45672013" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "7" + tx_polarity: "10011101" + rx_polarity: "11111010" + lane_swap: "74562103" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "8" + tx_polarity: "01001000" + rx_polarity: "00100011" + lane_swap: "54672301" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "9" + tx_polarity: "11111111" + rx_polarity: "01110111" + lane_swap: "46750321" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "10" + tx_polarity: "10011110" + rx_polarity: "10110000" + lane_swap: "67542310" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "11" + tx_polarity: "01010010" + rx_polarity: "10101011" + lane_swap: "65741302" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "12" + tx_polarity: "11010110" + rx_polarity: "01101001" + lane_swap: "45760321" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "13" + tx_polarity: "01110111" + rx_polarity: "00101000" + lane_swap: "45670123" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "14" + tx_polarity: "11110110" + rx_polarity: "10111100" + lane_swap: "67542013" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + - id: "15" + tx_polarity: "01011011" + rx_polarity: "01101000" + lane_swap: "64572103" + pre1: "-3, -3, -3, -3, -3, -3, -3, -3" + main: "20, 20, 20, 20, 20, 20, 20, 20" + + diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/innovium.55610 b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/innovium.55610 new file mode 100644 index 0000000000..b3b7fab24f --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/innovium.55610 @@ -0,0 +1,62 @@ +sku: innovium.55610 + +device_id: 0x1b59 + +# Hardware constraint information +hardware: + num_ibs: 2 + ib_active: 0, 1 + + ports_per_ib: 64, 64 + recirc_port_num: 64, 64 + cpu_port_num: 65 + cpu_port_ib: 0 + mgmt_port_num: 65, 66 + mgmt_port_ibs: 1, 1 + + pics_per_ib: 9, 9 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 0 + + isg [0-7]: + ib: 0 + pic_id: [0-7] + + isg 8: + ib: 1 + pic_id: 7 + + isg 9: + ib: 1 + pic_id: 6 + + isg 10: + ib: 1 + pic_id: 5 + + isg 11: + ib: 1 + pic_id: 4 + + isg 12: + ib: 1 + pic_id: 3 + + isg 13: + ib: 1 + pic_id: 2 + + isg 14: + ib: 1 + pic_id: 1 + + isg 15: + ib: 1 + pic_id: 0 + + isg 16: + mode: 0:2 + ib: 1 + pic_id: 8 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/ivm.sai.config.yaml b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/ivm.sai.config.yaml old mode 100755 new mode 100644 similarity index 66% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/ivm.sai.config.yaml rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/ivm.sai.config.yaml index dc8e200ec1..f1901be9a6 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/ivm.sai.config.yaml +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/ivm.sai.config.yaml @@ -1,8 +1,8 @@ -IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_64x100G_fab128.yaml" -IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_32x200G_Cameo-escc601-32q.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.55610" IFCS_INNO_CLI_PORT : "9999" IFCS_TARGET : "device" INNOVIUM_DIR : "/innovium" PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" IVM_SAI_DATAPATH_CONFIG_FILE: "/usr/share/sonic/hwsku/ivm.sai.datapath.config.yaml" -IVM_SAI_PARAM_A0008: "32" +IVM_SAI_PARAM_A0008: "64" diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/ivm.sai.datapath.config.yaml b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/ivm.sai.datapath.config.yaml new file mode 100644 index 0000000000..ef4bc6d129 --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/ivm.sai.datapath.config.yaml @@ -0,0 +1,9 @@ +ISAI_PARAM_P0_0_LS : "9216 9216" +ISAI_PARAM_P0_1_LS : "2850 2650" +ISAI_PARAM_P0_1_ALS : "290 90" +ISAI_PARAM_P1_0_LS : "3072 3072" +ISAI_PARAM_P1_0_LL : "6144 6144" +ISAI_PARAM_P1_1_LS : "2210 2010" +ISAI_PARAM_P1_1_LL : "1330 1330" +ISAI_PARAM_P1_1_ALS : "290 90" +ISAI_PARAM_P1_1_ALL : "50 50" diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/pg_profile_lookup.ini b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/pg_profile_lookup.ini similarity index 100% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/pg_profile_lookup.ini rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/pg_profile_lookup.ini diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/port_config.ini b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/port_config.ini new file mode 100644 index 0000000000..371c04c263 --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/port_config.ini @@ -0,0 +1,33 @@ +# name lanes speed index mtu fec +Ethernet0 121,122,123,124 200000 0 9126 rs +Ethernet4 125,126,127,128 200000 1 9126 rs +Ethernet8 113,114,115,116 200000 2 9126 rs +Ethernet12 117,118,119,120 200000 3 9126 rs +Ethernet16 105,106,107,108 200000 4 9126 rs +Ethernet20 109,110,111,112 200000 5 9126 rs +Ethernet24 97,98,99,100 200000 6 9126 rs +Ethernet28 101,102,103,104 200000 7 9126 rs +Ethernet32 89,90,91,92 200000 8 9126 rs +Ethernet36 93,94,95,96 200000 9 9126 rs +Ethernet40 81,82,83,84 200000 10 9126 rs +Ethernet44 85,86,87,88 200000 11 9126 rs +Ethernet48 73,74,75,76 200000 12 9126 rs +Ethernet52 77,78,79,80 200000 13 9126 rs +Ethernet56 65,66,67,68 200000 14 9126 rs +Ethernet60 69,70,71,72 200000 15 9126 rs +Ethernet64 57,58,59,60 200000 16 9126 rs +Ethernet68 61,62,63,64 200000 17 9126 rs +Ethernet72 49,50,51,52 200000 18 9126 rs +Ethernet76 53,54,55,56 200000 19 9126 rs +Ethernet80 41,42,43,44 200000 20 9126 rs +Ethernet84 45,46,47,48 200000 21 9126 rs +Ethernet88 33,34,35,36 200000 22 9126 rs +Ethernet92 37,38,39,40 200000 23 9126 rs +Ethernet96 25,26,27,28 200000 24 9126 rs +Ethernet100 29,30,31,32 200000 25 9126 rs +Ethernet104 17,18,19,20 200000 26 9126 rs +Ethernet108 21,22,23,24 200000 27 9126 rs +Ethernet112 9,10,11,12 200000 28 9126 rs +Ethernet116 13,14,15,16 200000 29 9126 rs +Ethernet120 1,2,3,4 200000 30 9126 rs +Ethernet124 5,6,7,8 200000 31 9126 rs diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/qos.json.j2 b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/qos.json.j2 similarity index 100% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/qos.json.j2 rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/qos.json.j2 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/qos_defaults_def_lossy.j2 b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/qos_defaults_def_lossy.j2 old mode 100755 new mode 100644 similarity index 100% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/qos_defaults_def_lossy.j2 rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/qos_defaults_def_lossy.j2 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/qos_defaults_t1.j2 b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/qos_defaults_t1.j2 old mode 100755 new mode 100644 similarity index 100% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/qos_defaults_t1.j2 rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/qos_defaults_t1.j2 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/sai.profile b/device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/sai.profile similarity index 100% rename from device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/sai.profile rename to device/cameo/x86_64-cameo_escc601_32q-r0/escc601-32q/sai.profile diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/installer.conf b/device/cameo/x86_64-cameo_escc601_32q-r0/installer.conf new file mode 100644 index 0000000000..925a32fc0c --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/platform_reboot b/device/cameo/x86_64-cameo_escc601_32q-r0/platform_reboot new file mode 100755 index 0000000000..46ee9f04ac --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/platform_reboot @@ -0,0 +1,16 @@ +#!/bin/sh + +mr_reboot() { + + sudo rmmod x86-64-cameo-escc601-32q + sudo i2cset -y 0 0x30 0xa1 0 + +} + +if [ $# -eq 0 ] || [ $@ = "-f" ] || [ $@ = "--force" ] || [ $@ = "reboot" ]; then + mr_reboot +elif [ $@ = "-p" ] ; then + sudo halt +else + echo "unsupported option" +fi diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/eeprom.py b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/eeprom.py new file mode 100755 index 0000000000..5b6ed4606b --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/eeprom.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/led_monitor_plugin.py b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/led_monitor_plugin.py new file mode 100755 index 0000000000..27db265a45 --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/led_monitor_plugin.py @@ -0,0 +1,84 @@ +"""SONiC LED plugin to control LED on/off/blinking when link-up/link-down/flowing-traffic +""" +def platform_configure_led(isg, lane, link_status, detailed_speed, activity_status): + """ Configure LED to turn on/off/blink based on link-up/link-down/activity-status + Args: + isg, lane, link_status, detailed_speed, activity_status + Returns: + cmd + Raises: + none + """ + base_cmd = 'i2cset -f -y 0 0x38' + isg_to_bitset_map = { + 'ISG0':'0', + 'ISG1':'1', + 'ISG2':'2', + 'ISG3':'3', + 'ISG4':'4', + 'ISG5':'5', + 'ISG6':'6', + 'ISG7':'7', + 'ISG8':'8', + 'ISG9':'9', + 'ISG10':'a', + 'ISG11':'b', + 'ISG12':'c', + 'ISG13':'d', + 'ISG14':'e', + 'ISG15':'f' + } + detailed_speed_to_bitset_map = { + '400G/50G':'0', + '200G/50G':'1', + '200G/25G':'2', + '100G/50G':'3', + '50G/50G':'4', + '100G/25G':'5', + '50G/25G':'6', + '25G/25G':'7', + '40G/10G':'8', + '10G/10G':'9' + } + + try: + if link_status == 'D': + arg = '0x' + isg_to_bitset_map[isg] + str(lane) + cmd = base_cmd + ' ' + arg + ' 0x00' + elif link_status == 'U': + arg1 = '0x' + isg_to_bitset_map[isg] + str(lane) + arg2 = '0x' + str(1+(2*activity_status)) + detailed_speed_to_bitset_map[detailed_speed] + cmd = base_cmd + ' ' + arg1 + ' ' + arg2 + + return cmd + + except Exception: + print('Error when processing command: {}'.format(cmd)) + raise + +def platform_configure_switch_led_control_from_TL5_to_CPU(): + """ Configure switch LED stream from TL5 to CPU through i2c + Args: + none + Returns: + cmd + Raises: + none + """ + cmd = 'i2cset -f -y 0 0x30 0xa0 0xf' + return cmd + +def main(): + """ Main function. + Args: + none + Returns: + none + Raises: + none + """ + return + + +if __name__ == '__main__': + main() diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/psuutil.py b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/psuutil.py new file mode 100755 index 0000000000..39566d208b --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/psuutil.py @@ -0,0 +1,95 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +attr_path = '/sys/class/hwmon/hwmon2/device/ESCC601_POWER/' + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, path): + + retval = 'ERR' + if (not os.path.isfile(path)): + return retval + + try: + with open(path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu{}_good'.format(index) + status_path = attr_path + attr_file + try: + reg_file = open(status_path, 'r') + except IOError as e: + print( "Error: unable to open file: %s" % str(e)) + return False + text = reg_file.read() + + if int(text) == 1: + status = 1 + + reg_file.close() + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + attr_file ='psu{}_prnt'.format(index) + presence_path = attr_path + attr_file + try: + reg_file = open(presence_path, 'r') + except IOError as e: + print( "Error: unable to open file: %s" % str(e)) + return False + text = reg_file.read() + + if int(text) == 1: + status = 1 + + reg_file.close() + + return status + diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/sfputil.py b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/sfputil.py new file mode 100755 index 0000000000..899b127960 --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/plugins/sfputil.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python + +try: + import time + import json + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +attr_path = '/sys/class/hwmon/hwmon2/device/' +PLATFORM_INSTALL_INFO_FILE="/etc/sonic/platform_install.json" +PLATFORM_SFP_GROUPS = ['SFP-G01','SFP-G02','SFP-G03','SFP-G04'] + +QSFP_RESET_FILE = 'ESCC601_QSFP/qsfp{}_reset' +QSFP_LOWPOWER_FILE = 'ESCC601_QSFP/qsfp{}_low_power' +QSFP_PRESENT_FILE = 'ESCC601_QSFP/qsfp{}_present' + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 31 + _port_in_block =32 + _port_to_eeprom_mapping = {} + _global_port_pres_dict = {} + + def __init__(self): + eeprom_path = "{}/eeprom" + path_list = self.get_sfp_path() + for x in range(self._port_start, self._port_end + 1): + port_eeprom_path = eeprom_path.format(path_list[x]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + + self.init_global_port_presence() + SfpUtilBase.__init__(self) + + def get_sfp_path(self): + map = [] + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for sfp_group_name in PLATFORM_SFP_GROUPS: + sfp_group = install_info[2][sfp_group_name] + map = map + sfp_group['paths'] + return map + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = attr_path+QSFP_RESET_FILE.format(port_num+1) + try: + reg_file = open(path, 'w') + except IOError as e: + print( "Error: unable to open file: %s" % str(e)) + return False + + reg_file.seek(0) + reg_file.write('1') + + reg_file.close() + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + path = attr_path+QSFP_LOWPOWER_FILE.format(port_num+1) + try: + reg_file = open(path, 'w') + except IOError as e: + print( "Error: unable to open file: %s" % str(e)) + return False + + # the gpio pin is ACTIVE_HIGH + if lpmode is True: + val = "1" + else: + val = "0" + + # write value to gpio + reg_file.seek(0) + reg_file.write(val) + reg_file.close() + + return True + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = attr_path+QSFP_LOWPOWER_FILE.format(port_num+1) + try: + reg_file = open(path, 'r') + except IOError as e: + print( "Error: unable to open file: %s" % str(e)) + return False + + text = reg_file.read() + reg_file.close() + if int(text) == 1: + return True + + return False + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = attr_path+QSFP_PRESENT_FILE.format(port_num+1) + try: + reg_file = open(path, 'r') + except IOError as e: + print( "Error: unable to open file: %s" % str(e)) + return False + text = reg_file.read() + reg_file.close() + if int(text) == 1: + return True + + return False + + def init_global_port_presence(self): + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + while True: + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, port_dict + + time.sleep(1) + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self._port_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/pmon_daemon_control.json b/device/cameo/x86_64-cameo_escc601_32q-r0/pmon_daemon_control.json new file mode 100644 index 0000000000..94592fa8ce --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/cameo/x86_64-cameo_escc601_32q-r0/sensors.conf b/device/cameo/x86_64-cameo_escc601_32q-r0/sensors.conf new file mode 100644 index 0000000000..b28b04f643 --- /dev/null +++ b/device/cameo/x86_64-cameo_escc601_32q-r0/sensors.conf @@ -0,0 +1,3 @@ + + + diff --git a/device/cameo/x86_64-fabric_1208i-r0/topo.conf b/device/cameo/x86_64-cameo_escc601_32q-r0/topo.conf similarity index 100% rename from device/cameo/x86_64-fabric_1208i-r0/topo.conf rename to device/cameo/x86_64-cameo_escc601_32q-r0/topo.conf diff --git a/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/eeprom.py b/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/eeprom.py index f0f19ba393..5b6ed4606b 100755 --- a/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/eeprom.py +++ b/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/eeprom.py @@ -2,7 +2,7 @@ try: from sonic_eeprom import eeprom_tlvinfo -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + "- required module not found") class board(eeprom_tlvinfo.TlvInfoDecoder): diff --git a/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/psuutil.py b/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/psuutil.py index ce9e9acbf6..f0b135d4a4 100755 --- a/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/psuutil.py +++ b/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/psuutil.py @@ -11,7 +11,7 @@ try: except ImportError as e: raise ImportError(str(e) + "- required module not found") -attr_path = '/sys/class/hwmon/hwmon2/device/' +attr_path = '/sys/class/hwmon/hwmon2/device/ESQC610_POWER/' class PsuUtil(PsuBase): """Platform-specific PSUutil class""" @@ -53,18 +53,16 @@ class PsuUtil(PsuBase): faulty """ status = 0 - attr_file = 'psu_status' - status_path = attr_path+'/ESQC610_PSU/' + attr_file + attr_file = 'psu{}_good'.format(index) + status_path = attr_path + attr_file try: reg_file = open(status_path, 'r') except IOError as e: print( "Error: unable to open file: %s" % str(e)) return False - text_lines = reg_file.read() + text = reg_file.read() - search_str = "PSU {} is power Good".format(index) - - if search_str in text_lines: + if int(text) == 1: status = 1 reg_file.close() @@ -79,18 +77,16 @@ class PsuUtil(PsuBase): :return: Boolean, True if PSU is plugged, False if not """ status = 0 - attr_file ='psu_present' - presence_path = attr_path+'ESQC610_PSU/' + attr_file + attr_file ='psu{}_prnt'.format(index) + presence_path = attr_path + attr_file try: reg_file = open(presence_path, 'r') except IOError as e: print( "Error: unable to open file: %s" % str(e)) return False - text_lines = reg_file.read() + text = reg_file.read() - search_str = "PSU {} is present".format(index) - - if search_str in text_lines: + if int(text) == 1: status = 1 reg_file.close() diff --git a/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/sfputil.py b/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/sfputil.py index e4d19b318f..0ac1f5c870 100755 --- a/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/sfputil.py +++ b/device/cameo/x86_64-cameo_esqc610_56sq-r0/plugins/sfputil.py @@ -4,13 +4,19 @@ try: import time import json from sonic_sfp.sfputilbase import SfpUtilBase -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + "- required module not found") attr_path = '/sys/class/hwmon/hwmon2/device/' PLATFORM_INSTALL_INFO_FILE="/etc/sonic/platform_install.json" PLATFORM_SFP_GROUPS = ['SFP-G01','SFP-G02','SFP-G03','SFP-G04','SFP-G05', 'SFP-G06', 'SFP-G07'] +QSFP_RESET_FILE = 'ESQC610_QSFP/qsfp{}_reset' +QSFP_LOWPOWER_FILE = 'ESQC610_QSFP/qsfp{}_low_power' +QSFP_PRESENT_FILE = 'ESQC610_QSFP/qsfp{}_present' + +SFP_PRESENT_FILE = 'ESQC610_SFP/sfp{}_present' + class SfpUtil(SfpUtilBase): """Platform specific SfpUtill class""" @@ -45,28 +51,25 @@ class SfpUtil(SfpUtilBase): if port_num < self._qsfp_port_start or port_num > self._port_end: return False - path = attr_path+'ESQC610_QSFP/QSFP_reset' + path = attr_path+QSFP_RESET_FILE.format(port_num-self._qsfp_port_start+1) try: reg_file = open(path, 'w') except IOError as e: print( "Error: unable to open file: %s" % str(e)) return False + + reg_file.seek(0) + reg_file.write('1') - #toggle reset - #reg_file.seek(0) - reg_file.write(str(port_num-self._qsfp_port_start+1)) - #time.sleep(1) - #reg_file.seek(0) - #reg_file.write('0') reg_file.close() return True def set_low_power_mode(self, port_num, lpmode): # Check for invalid port_num - if port_num < self._qsfp_port_start or port_num > self.port_end: + if port_num < self._qsfp_port_start or port_num > self._port_end: return False - path = attr_path+'ESQC610_QSFP/QSFP_low_power_'+str(port_num-self._qsfp_port_start+1) + path = attr_path+QSFP_LOWPOWER_FILE.format(port_num-self._qsfp_port_start+1) try: reg_file = open(path, 'w') except IOError as e: @@ -91,16 +94,16 @@ class SfpUtil(SfpUtilBase): if port_num < self._qsfp_port_start or port_num > self._port_end: return False - path = attr_path+'ESQC610_QSFP/QSFP_low_power_'+str(port_num-self._qsfp_port_start+1) + path = attr_path+QSFP_LOWPOWER_FILE.format(port_num-self._qsfp_port_start+1) try: reg_file = open(path, 'r') except IOError as e: print( "Error: unable to open file: %s" % str(e)) return False - text_lines = reg_file.readline() + text = reg_file.read() reg_file.close() - if text_lines.find('OFF') < 0: + if int(text) == 1: return True return False @@ -111,26 +114,24 @@ class SfpUtil(SfpUtilBase): return False if port_num >= self._qsfp_port_start: - path = attr_path+'ESQC610_QSFP/QSFP_present' - line = port_num - self._qsfp_port_start + path = attr_path+QSFP_PRESENT_FILE.format(port_num-self._qsfp_port_start+1) else: - path = attr_path+'ESQC610_SFP/SFP_present' - line = port_num + path = attr_path+SFP_PRESENT_FILE.format(port_num+1) try: reg_file = open(path, 'r') except IOError as e: print( "Error: unable to open file: %s" % str(e)) return False - text_lines = reg_file.readlines() + text = reg_file.read() reg_file.close() - if text_lines[line].find('not') < 0: + if int(text) == 1: return True return False def init_global_port_presence(self): - for port_num in range(self.port_start, (self.port_end + 1)): + for port_num in range(self._port_start, (self._port_end + 1)): presence = self.get_presence(port_num) if(presence): self._global_port_pres_dict[port_num] = '1' @@ -140,7 +141,7 @@ class SfpUtil(SfpUtilBase): def get_transceiver_change_event(self, timeout=0): port_dict = {} while True: - for port_num in range(self.port_start, (self.port_end + 1)): + for port_num in range(self._port_start, (self._port_end + 1)): presence = self.get_presence(port_num) if(presence and self._global_port_pres_dict[port_num] == '0'): self._global_port_pres_dict[port_num] = '1' @@ -165,7 +166,7 @@ class SfpUtil(SfpUtilBase): @property def qsfp_ports(self): - return range(self._qsfp_port_start, self._port_in_block + 1) + return range(self._qsfp_port_start, self._port_end + 1) @property def port_to_eeprom_mapping(self): diff --git a/device/cameo/x86_64-cameo_esqc610_56sq-r0/pmon_daemon_control.json b/device/cameo/x86_64-cameo_esqc610_56sq-r0/pmon_daemon_control.json index 44871c057e..94592fa8ce 100644 --- a/device/cameo/x86_64-cameo_esqc610_56sq-r0/pmon_daemon_control.json +++ b/device/cameo/x86_64-cameo_esqc610_56sq-r0/pmon_daemon_control.json @@ -1,4 +1,3 @@ { - "skip_ledd": true, - "skip_thermalctld": true + "skip_ledd": true } diff --git a/device/cameo/x86_64-fabric_1208i-r0/default_sku b/device/cameo/x86_64-fabric_1208i-r0/default_sku deleted file mode 100644 index d361cdfd59..0000000000 --- a/device/cameo/x86_64-fabric_1208i-r0/default_sku +++ /dev/null @@ -1 +0,0 @@ -fabric-1208i t1 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_32x400G_fab128.yaml b/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_32x400G_fab128.yaml deleted file mode 100644 index 66bd195e7f..0000000000 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_32x400G_fab128.yaml +++ /dev/null @@ -1,417 +0,0 @@ -ifcs: - options: - log_level: "off" -nodes: -- node_id: "0" - options: - sku: "configs/sku/innovium.77700_A" - netdev: - - auto_create: "no" - multi_interface: "yes" - buffer_management_mode: "api_driven" - max_lossless_tc: "2" - skip_pll_check: "false" - mbist_on_init: "true" - ilpm_enable: "1" - forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" - txring: - - txring_id: "0" - desc_count: "1024" - prio: "1" - netdev: "true" - - txring_id: "1" - desc_count: "1024" - prio: "1" - netdev: "true" - - txring_id: "2" - desc_count: "1024" - prio: "1" - netdev: "true" - - txring_id: "3" - desc_count: "1024" - prio: "1" - netdev: "true" - rxring: - - rxring_id: "0" - desc_count: "1024" - prio: "1" - netdev: "true" - queues: "0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39" - - rxring_id: "1" - desc_count: "1024" - prio: "1" - netdev: "true" - queues: "1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40" - - rxring_id: "2" - desc_count: "1024" - prio: "1" - netdev: "true" - queues: "2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 47" - - rxring_id: "3" - desc_count: "1024" - prio: "1" - queues: "42, 43, 44, 45, 46" - sys_clk: "1720" - ifc_clk: "1200" - mac_clk: "1340" - devports: - - id: "0" - sysport: "1000" - type: "cpu" - - fec: "KPFEC" - id: "1" - lanes: "0:8" - serdes_group: "4" - speed: "400G" - sysport: "1" - type: "eth" - - fec: "KPFEC" - id: "9" - lanes: "0:8" - serdes_group: "5" - speed: "400G" - sysport: "9" - type: "eth" - - fec: "KPFEC" - id: "17" - lanes: "0:8" - serdes_group: "6" - speed: "400G" - sysport: "17" - type: "eth" - - fec: "KPFEC" - id: "25" - lanes: "0:8" - serdes_group: "7" - speed: "400G" - sysport: "25" - type: "eth" - - fec: "KPFEC" - id: "33" - lanes: "0:8" - serdes_group: "0" - speed: "400G" - sysport: "33" - type: "eth" - - fec: "KPFEC" - id: "41" - lanes: "0:8" - serdes_group: "1" - speed: "400G" - sysport: "41" - type: "eth" - - fec: "KPFEC" - id: "49" - lanes: "0:8" - serdes_group: "2" - speed: "400G" - sysport: "49" - type: "eth" - - fec: "KPFEC" - id: "57" - lanes: "0:8" - serdes_group: "3" - speed: "400G" - sysport: "57" - type: "eth" - - fec: "KPFEC" - id: "65" - lanes: "0:8" - serdes_group: "28" - speed: "400G" - sysport: "65" - type: "eth" - - fec: "KPFEC" - id: "73" - lanes: "0:8" - serdes_group: "29" - speed: "400G" - sysport: "73" - type: "eth" - - fec: "KPFEC" - id: "81" - lanes: "0:8" - serdes_group: "30" - speed: "400G" - sysport: "81" - type: "eth" - - fec: "KPFEC" - id: "89" - lanes: "0:8" - serdes_group: "31" - speed: "400G" - sysport: "89" - type: "eth" - - fec: "KPFEC" - id: "97" - lanes: "0:8" - serdes_group: "24" - speed: "400G" - sysport: "97" - type: "eth" - - fec: "KPFEC" - id: "105" - lanes: "0:8" - serdes_group: "25" - speed: "400G" - sysport: "105" - type: "eth" - - fec: "KPFEC" - id: "113" - lanes: "0:8" - serdes_group: "26" - speed: "400G" - sysport: "113" - type: "eth" - - fec: "KPFEC" - id: "121" - lanes: "0:8" - serdes_group: "27" - speed: "400G" - sysport: "121" - type: "eth" - - fec: "KPFEC" - id: "129" - lanes: "0:8" - serdes_group: "20" - speed: "400G" - sysport: "129" - type: "eth" - - fec: "KPFEC" - id: "137" - lanes: "0:8" - serdes_group: "21" - speed: "400G" - sysport: "137" - type: "eth" - - fec: "KPFEC" - id: "145" - lanes: "0:8" - serdes_group: "22" - speed: "400G" - sysport: "145" - type: "eth" - - fec: "KPFEC" - id: "153" - lanes: "0:8" - serdes_group: "23" - speed: "400G" - sysport: "153" - type: "eth" - - fec: "KPFEC" - id: "161" - lanes: "0:8" - serdes_group: "16" - speed: "400G" - sysport: "161" - type: "eth" - - fec: "KPFEC" - id: "169" - lanes: "0:8" - serdes_group: "17" - speed: "400G" - sysport: "169" - type: "eth" - - fec: "KPFEC" - id: "177" - lanes: "0:8" - serdes_group: "18" - speed: "400G" - sysport: "177" - type: "eth" - - fec: "KPFEC" - id: "185" - lanes: "0:8" - serdes_group: "19" - speed: "400G" - sysport: "185" - type: "eth" - - fec: "KPFEC" - id: "193" - lanes: "0:8" - serdes_group: "12" - speed: "400G" - sysport: "193" - type: "eth" - - fec: "KPFEC" - id: "201" - lanes: "0:8" - serdes_group: "13" - speed: "400G" - sysport: "201" - type: "eth" - - fec: "KPFEC" - id: "209" - lanes: "0:8" - serdes_group: "14" - speed: "400G" - sysport: "209" - type: "eth" - - fec: "KPFEC" - id: "217" - lanes: "0:8" - serdes_group: "15" - speed: "400G" - sysport: "217" - type: "eth" - - fec: "KPFEC" - id: "225" - lanes: "0:8" - serdes_group: "8" - speed: "400G" - sysport: "225" - type: "eth" - - fec: "KPFEC" - id: "233" - lanes: "0:8" - serdes_group: "9" - speed: "400G" - sysport: "233" - type: "eth" - - fec: "KPFEC" - id: "241" - lanes: "0:8" - serdes_group: "10" - speed: "400G" - sysport: "241" - type: "eth" - - fec: "KPFEC" - id: "249" - lanes: "0:8" - serdes_group: "11" - speed: "400G" - sysport: "249" - type: "eth" - isg: - - id: "0" - tx_polarity: "01011011" - rx_polarity: "11001111" - lane_swap: "01235467" - - id: "1" - tx_polarity: "01011011" - rx_polarity: "01001111" - lane_swap: "01234567" - - id: "2" - tx_polarity: "10110100" - rx_polarity: "10001110" - lane_swap: "73215460" - - id: "3" - tx_polarity: "11111110" - rx_polarity: "10011111" - lane_swap: "71234560" - - id: "4" - tx_polarity: "01001011" - rx_polarity: "11011010" - lane_swap: "01235467" - - id: "5" - tx_polarity: "01001011" - rx_polarity: "01001111" - lane_swap: "01234567" - - id: "6" - tx_polarity: "11110100" - rx_polarity: "10010110" - lane_swap: "73215460" - - id: "7" - tx_polarity: "11111101" - rx_polarity: "11110011" - lane_swap: "53164720" - - id: "8" - tx_polarity: "00101001" - rx_polarity: "01101001" - lane_swap: "01234567" - - id: "9" - tx_polarity: "00101001" - rx_polarity: "01101001" - lane_swap: "01234567" - - id: "10" - tx_polarity: "10010110" - rx_polarity: "10110100" - lane_swap: "73215460" - - id: "11" - tx_polarity: "10000100" - rx_polarity: "00010100" - lane_swap: "71635420" - - id: "12" - tx_polarity: "00101001" - rx_polarity: "10001001" - lane_swap: "01234567" - - id: "13" - tx_polarity: "01101001" - rx_polarity: "00001011" - lane_swap: "01235467" - - id: "14" - tx_polarity: "10000110" - rx_polarity: "10000010" - lane_swap: "73215460" - - id: "15" - tx_polarity: "10000100" - rx_polarity: "10010100" - lane_swap: "73615420" - - id: "16" - tx_polarity: "00101001" - rx_polarity: "00001011" - lane_swap: "01234567" - - id: "17" - tx_polarity: "00101001" - rx_polarity: "00001011" - lane_swap: "01235467" - - id: "18" - tx_polarity: "00010110" - rx_polarity: "10010110" - lane_swap: "73215460" - - id: "19" - tx_polarity: "11101110" - rx_polarity: "10100100" - lane_swap: "73615420" - - id: "20" - tx_polarity: "01001101" - rx_polarity: "11101011" - lane_swap: "01234567" - - id: "21" - tx_polarity: "11011011" - rx_polarity: "10001011" - lane_swap: "01234567" - - id: "22" - tx_polarity: "11110100" - rx_polarity: "10001111" - lane_swap: "73215460" - - id: "23" - tx_polarity: "11110110" - rx_polarity: "01011100" - lane_swap: "73615420" - - id: "24" - tx_polarity: "01011011" - rx_polarity: "01101101" - lane_swap: "01234567" - - id: "25" - tx_polarity: "01001011" - rx_polarity: "01101101" - lane_swap: "01234567" - - id: "26" - tx_polarity: "11110100" - rx_polarity: "10111100" - lane_swap: "73215460" - - id: "27" - tx_polarity: "10111100" - rx_polarity: "00010100" - lane_swap: "73615420" - - id: "28" - tx_polarity: "01001011" - rx_polarity: "01010101" - lane_swap: "01235467" - - id: "29" - tx_polarity: "01011011" - rx_polarity: "11001010" - lane_swap: "01234567" - - id: "30" - tx_polarity: "11110100" - rx_polarity: "00010111" - lane_swap: "73215460" - - id: "31" - tx_polarity: "11110100" - rx_polarity: "00110111" - lane_swap: "73615420" - - id: "32" - tx_polarity: "00000000" - rx_polarity: "00000000" - lane_swap: "01234567" diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_64x100G_fab128.yaml b/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_64x100G_fab128.yaml deleted file mode 100644 index efb8fc73aa..0000000000 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/config_64x100G_fab128.yaml +++ /dev/null @@ -1,833 +0,0 @@ -ifcs: - options: - log_level: "fatal" -nodes: -- node_id: "0" - options: - sku: "configs/sku/innovium.77700_B" - netdev: - - auto_create: "no" - multi_interface: "yes" - buffer_management_mode: "api_driven" - max_lossless_tc: "2" - skip_pll_check: "false" - mbist_on_init: "true" - ilpm_enable: "1" - forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" - txring: - - txring_id: "0" - desc_count: "1024" - prio: "1" - netdev: "true" - - txring_id: "1" - desc_count: "1024" - prio: "1" - netdev: "true" - - txring_id: "2" - desc_count: "1024" - prio: "1" - netdev: "true" - - txring_id: "3" - desc_count: "1024" - prio: "1" - netdev: "true" - rxring: - - rxring_id: "0" - desc_count: "1024" - prio: "1" - netdev: "true" - queues: "0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39" - - rxring_id: "1" - desc_count: "1024" - prio: "1" - netdev: "true" - queues: "1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40" - - rxring_id: "2" - desc_count: "1024" - prio: "1" - netdev: "true" - queues: "2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 47" - - rxring_id: "3" - desc_count: "1024" - prio: "1" - queues: "42, 43, 44, 45, 46" - sys_clk: "1720" - ifc_clk: "1200" - mac_clk: "1340" - devports: - - id: "0" - sysport: "1000" - type: "cpu" - - fec: "KRFEC" - id: "1" - lanes: "0:4" - serdes_group: "4" - speed: "100G" - sysport: "1" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "5" - lanes: "4:4" - serdes_group: "4" - speed: "100G" - sysport: "5" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "9" - lanes: "0:4" - serdes_group: "5" - speed: "100G" - sysport: "9" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "13" - lanes: "4:4" - serdes_group: "5" - speed: "100G" - sysport: "13" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "17" - lanes: "0:4" - serdes_group: "6" - speed: "100G" - sysport: "17" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "21" - lanes: "4:4" - serdes_group: "6" - speed: "100G" - sysport: "21" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "25" - lanes: "0:4" - serdes_group: "7" - speed: "100G" - sysport: "25" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "29" - lanes: "4:4" - serdes_group: "7" - speed: "100G" - sysport: "29" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "33" - lanes: "0:4" - serdes_group: "0" - speed: "100G" - sysport: "33" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "37" - lanes: "4:4" - serdes_group: "0" - speed: "100G" - sysport: "37" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "41" - lanes: "0:4" - serdes_group: "1" - speed: "100G" - sysport: "41" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "45" - lanes: "4:4" - serdes_group: "1" - speed: "100G" - sysport: "45" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "49" - lanes: "0:4" - serdes_group: "2" - speed: "100G" - sysport: "49" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "53" - lanes: "4:4" - serdes_group: "2" - speed: "100G" - sysport: "53" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "57" - lanes: "0:4" - serdes_group: "3" - speed: "100G" - sysport: "57" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "61" - lanes: "4:4" - serdes_group: "3" - speed: "100G" - sysport: "61" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "65" - lanes: "0:4" - serdes_group: "28" - speed: "100G" - sysport: "65" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "69" - lanes: "4:4" - serdes_group: "28" - speed: "100G" - sysport: "69" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "73" - lanes: "0:4" - serdes_group: "29" - speed: "100G" - sysport: "73" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "77" - lanes: "4:4" - serdes_group: "29" - speed: "100G" - sysport: "77" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "81" - lanes: "0:4" - serdes_group: "30" - speed: "100G" - sysport: "81" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "85" - lanes: "4:4" - serdes_group: "30" - speed: "100G" - sysport: "85" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "89" - lanes: "0:4" - serdes_group: "31" - speed: "100G" - sysport: "89" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "93" - lanes: "4:4" - serdes_group: "31" - speed: "100G" - sysport: "93" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "97" - lanes: "0:4" - serdes_group: "24" - speed: "100G" - sysport: "97" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "101" - lanes: "4:4" - serdes_group: "24" - speed: "100G" - sysport: "101" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "105" - lanes: "0:4" - serdes_group: "25" - speed: "100G" - sysport: "105" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "109" - lanes: "4:4" - serdes_group: "25" - speed: "100G" - sysport: "109" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "113" - lanes: "0:4" - serdes_group: "26" - speed: "100G" - sysport: "113" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "117" - lanes: "4:4" - serdes_group: "26" - speed: "100G" - sysport: "117" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "121" - lanes: "0:4" - serdes_group: "27" - speed: "100G" - sysport: "121" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "125" - lanes: "4:4" - serdes_group: "27" - speed: "100G" - sysport: "125" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "129" - lanes: "0:4" - serdes_group: "20" - speed: "100G" - sysport: "129" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "133" - lanes: "4:4" - serdes_group: "20" - speed: "100G" - sysport: "133" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "137" - lanes: "0:4" - serdes_group: "21" - speed: "100G" - sysport: "137" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "141" - lanes: "4:4" - serdes_group: "21" - speed: "100G" - sysport: "141" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "145" - lanes: "0:4" - serdes_group: "22" - speed: "100G" - sysport: "145" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "149" - lanes: "4:4" - serdes_group: "22" - speed: "100G" - sysport: "149" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "153" - lanes: "0:4" - serdes_group: "23" - speed: "100G" - sysport: "153" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "157" - lanes: "4:4" - serdes_group: "23" - speed: "100G" - sysport: "157" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "161" - lanes: "0:4" - serdes_group: "16" - speed: "100G" - sysport: "161" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "165" - lanes: "4:4" - serdes_group: "16" - speed: "100G" - sysport: "165" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "169" - lanes: "0:4" - serdes_group: "17" - speed: "100G" - sysport: "169" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "173" - lanes: "4:4" - serdes_group: "17" - speed: "100G" - sysport: "173" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "177" - lanes: "0:4" - serdes_group: "18" - speed: "100G" - sysport: "177" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "181" - lanes: "4:4" - serdes_group: "18" - speed: "100G" - sysport: "181" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "185" - lanes: "0:4" - serdes_group: "19" - speed: "100G" - sysport: "185" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "189" - lanes: "4:4" - serdes_group: "19" - speed: "100G" - sysport: "189" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "193" - lanes: "0:4" - serdes_group: "12" - speed: "100G" - sysport: "193" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "197" - lanes: "4:4" - serdes_group: "12" - speed: "100G" - sysport: "197" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "201" - lanes: "0:4" - serdes_group: "13" - speed: "100G" - sysport: "201" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "205" - lanes: "4:4" - serdes_group: "13" - speed: "100G" - sysport: "205" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "209" - lanes: "0:4" - serdes_group: "14" - speed: "100G" - sysport: "209" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "213" - lanes: "4:4" - serdes_group: "14" - speed: "100G" - sysport: "213" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "217" - lanes: "0:4" - serdes_group: "15" - speed: "100G" - sysport: "217" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "221" - lanes: "4:4" - serdes_group: "15" - speed: "100G" - sysport: "221" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "225" - lanes: "0:4" - serdes_group: "8" - speed: "100G" - sysport: "225" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "229" - lanes: "4:4" - serdes_group: "8" - speed: "100G" - sysport: "229" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "233" - lanes: "0:4" - serdes_group: "9" - speed: "100G" - sysport: "233" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "237" - lanes: "4:4" - serdes_group: "9" - speed: "100G" - sysport: "237" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "241" - lanes: "0:4" - serdes_group: "10" - speed: "100G" - sysport: "241" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "245" - lanes: "4:4" - serdes_group: "10" - speed: "100G" - sysport: "245" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "249" - lanes: "0:4" - serdes_group: "11" - speed: "100G" - sysport: "249" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - - fec: "KRFEC" - id: "253" - lanes: "4:4" - serdes_group: "11" - speed: "100G" - sysport: "253" - type: "eth" - link_training: "true" - bp_tech_ability: "100GBASE_KR4,100GBASE_CR4,100GBASE_KR2_CR2" - auto_neg: "true" - isg: - - id: "0" - tx_polarity: "01011011" - rx_polarity: "11001111" - lane_swap: "01234567" - - id: "1" - tx_polarity: "01011011" - rx_polarity: "01001111" - lane_swap: "01234567" - - id: "2" - tx_polarity: "01101001" - rx_polarity: "00001111" - lane_swap: "73215460" - - id: "3" - tx_polarity: "01111111" - rx_polarity: "10011111" - lane_swap: "71234560" - - id: "4" - tx_polarity: "01000111" - rx_polarity: "11010110" - lane_swap: "01235467" - - id: "5" - tx_polarity: "01001011" - rx_polarity: "01001111" - lane_swap: "01234567" - - id: "6" - tx_polarity: "01111001" - rx_polarity: "01001011" - lane_swap: "73215460" - - id: "7" - tx_polarity: "11101111" - rx_polarity: "01110111" - lane_swap: "72614035" - - id: "8" - tx_polarity: "00101001" - rx_polarity: "01101001" - lane_swap: "01234567" - - id: "9" - tx_polarity: "00101001" - rx_polarity: "01101001" - lane_swap: "01234567" - - id: "10" - tx_polarity: "01001011" - rx_polarity: "01101001" - lane_swap: "73215460" - - id: "11" - tx_polarity: "00001001" - rx_polarity: "00011000" - lane_swap: "71635420" - - id: "12" - tx_polarity: "00101001" - rx_polarity: "10001001" - lane_swap: "01234567" - - id: "13" - tx_polarity: "01100101" - rx_polarity: "00000111" - lane_swap: "01235467" - - id: "14" - tx_polarity: "00001011" - rx_polarity: "00000011" - lane_swap: "73215460" - - id: "15" - tx_polarity: "00001001" - rx_polarity: "01001001" - lane_swap: "73615420" - - id: "16" - tx_polarity: "00101001" - rx_polarity: "00001011" - lane_swap: "01234567" - - id: "17" - tx_polarity: "00100101" - rx_polarity: "00000111" - lane_swap: "01235467" - - id: "18" - tx_polarity: "01001010" - rx_polarity: "01001011" - lane_swap: "73215460" - - id: "19" - tx_polarity: "00111111" - rx_polarity: "00001011" - lane_swap: "73615420" - - id: "20" - tx_polarity: "01001101" - rx_polarity: "11101011" - lane_swap: "01234567" - - id: "21" - tx_polarity: "11011011" - rx_polarity: "10001011" - lane_swap: "01234567" - - id: "22" - tx_polarity: "01111001" - rx_polarity: "10001111" - lane_swap: "73215460" - - id: "23" - tx_polarity: "01111011" - rx_polarity: "01011100" - lane_swap: "73615420" - - id: "24" - tx_polarity: "01011011" - rx_polarity: "01101101" - lane_swap: "01234567" - - id: "25" - tx_polarity: "01001011" - rx_polarity: "01101101" - lane_swap: "01234567" - - id: "26" - tx_polarity: "01111001" - rx_polarity: "01101101" - lane_swap: "73215460" - - id: "27" - tx_polarity: "01001111" - rx_polarity: "01001000" - lane_swap: "73615420" - - id: "28" - tx_polarity: "01000111" - rx_polarity: "01011001" - lane_swap: "01235467" - - id: "29" - tx_polarity: "01011011" - rx_polarity: "11001010" - lane_swap: "01234567" - - id: "30" - tx_polarity: "01111001" - rx_polarity: "11001010" - lane_swap: "73215460" - - id: "31" - tx_polarity: "01011011" - rx_polarity: "11101010" - lane_swap: "73615420" - - id: "32" - tx_polarity: "00000000" - rx_polarity: "00000000" - lane_swap: "01234567" diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_A b/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_A deleted file mode 100644 index 84aa419836..0000000000 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_A +++ /dev/null @@ -1,59 +0,0 @@ -sku: innovium.77700_A - -device_id: 0x1b58 - -# Hardware constraint information -hardware: - num_ibs: 6 - - ports_per_ib: 32, 32, 32, 32, 20, 20 - recirc_port_num: 32, 32, 32, 32, 32, 32 - cpu_port_num: 33 - cpu_port_ib: 0 - mgmt_port_num: 33 - mgmt_port_ibs: 1,2 - - pics_per_ib: 6, 7, 6, 5, 5, 5 - pic_ports_per_pic: 8 - max_serdes_speed: 50 - - num_shared_pics: 2 - - isg [0-4]: - ib: 0 - pic_id: [0-4] - - isg [5-9]: - ib: 5 - pic_id: [0-4] - - isg [10-14]: - ib: 1 - pic_id: [0-4] - - isg [16-20]: - ib: 3 - pic_id: [0-4] - - isg [21-25]: - ib: 4 - pic_id: [0-4] - - isg [26-30]: - ib: 2 - pic_id: [0-4] - - isg 15: - mode: 8:0 - ib: 1 - pic_id: 5 - - isg 31: - mode: 8:0 - ib: 0 - pic_id: 5 - - isg 32: - mode: 1:1 - ib: 1, 2 - pic_id: 6 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_B b/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_B deleted file mode 100644 index 27297b3139..0000000000 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/innovium.77700_B +++ /dev/null @@ -1,59 +0,0 @@ -sku: innovium.77700_B - -device_id: 0x1b58 - -# Hardware constraint information -hardware: - num_ibs: 6 - - ports_per_ib: 32, 32, 32, 32, 20, 20 - recirc_port_num: 32, 32, 32, 32, 32, 32 - cpu_port_num: 33 - cpu_port_ib: 0 - mgmt_port_num: 33 - mgmt_port_ibs: 1,2 - - pics_per_ib: 6, 7, 7, 6, 5, 5 - pic_ports_per_pic: 8 - max_serdes_speed: 50 - - num_shared_pics: 2 - - isg [0-4]: - ib: 0 - pic_id: [0-4] - - isg [5-9]: - ib: 5 - pic_id: [0-4] - - isg [10-14]: - ib: 1 - pic_id: [0-4] - - isg [16-20]: - ib: 3 - pic_id: [0-4] - - isg [21-25]: - ib: 4 - pic_id: [0-4] - - isg [26-30]: - ib: 2 - pic_id: [0-4] - - isg 15: - mode: 4:4 - ib: 1, 3 - pic_id: 5 - - isg 31: - mode: 4:4 - ib: 0, 2 - pic_id: 5 - - isg 32: - mode: 1:1 - ib: 1, 2 - pic_id: 6 diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/ivm.sai.datapath.config.yaml b/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/ivm.sai.datapath.config.yaml deleted file mode 100644 index 891b0b3e28..0000000000 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/ivm.sai.datapath.config.yaml +++ /dev/null @@ -1,9 +0,0 @@ -ISAI_PARAM_P0_0_LS : "4608 4608 4608 4608 2880 2880" -ISAI_PARAM_P0_1_LS : "2226 1946 1946 1890 1218 1218" -ISAI_PARAM_P0_1_ALS : "434 154 154 98 98 98" -ISAI_PARAM_P1_0_LS : "1536 1536 1536 1536 960 960" -ISAI_PARAM_P1_0_LL : "3072 3072 3072 3072 1920 1920" -ISAI_PARAM_P1_1_LS : "1778 1498 1498 1442 938 938" -ISAI_PARAM_P1_1_LL : "2478 2478 2478 2478 2478 2478" -ISAI_PARAM_P1_1_ALS : "434 154 154 98 98 98" -ISAI_PARAM_P1_1_ALL : "126 126 126 126 126 126" diff --git a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/port_config.ini b/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/port_config.ini deleted file mode 100644 index 112be08612..0000000000 --- a/device/cameo/x86_64-fabric_1208i-r0/fabric-1208i/port_config.ini +++ /dev/null @@ -1,65 +0,0 @@ -# name lanes alias speed index mtu fec -Ethernet0 33,34,35,36 C1 100000 0 9126 rs -Ethernet4 37,38,39,40 C2 100000 1 9126 rs -Ethernet8 41,42,43,44 C3 100000 2 9126 rs -Ethernet12 45,46,47,48 C4 100000 3 9126 rs -Ethernet16 49,50,51,52 C5 100000 4 9126 rs -Ethernet20 53,54,55,56 C6 100000 5 9126 rs -Ethernet24 57,58,59,60 C7 100000 6 9126 rs -Ethernet28 61,62,63,64 C8 100000 7 9126 rs -Ethernet32 1,2,3,4 C9 100000 8 9126 rs -Ethernet36 5,6,7,8 C10 100000 9 9126 rs -Ethernet40 9,10,11,12 C11 100000 10 9126 rs -Ethernet44 13,14,15,16 C12 100000 11 9126 rs -Ethernet48 17,18,19,20 C13 100000 12 9126 rs -Ethernet52 21,22,23,24 C14 100000 13 9126 rs -Ethernet56 25,26,27,28 C15 100000 14 9126 rs -Ethernet60 29,30,31,32 C16 100000 15 9126 rs -Ethernet64 225,226,227,228 C17 100000 16 9126 rs -Ethernet68 229,230,231,232 C18 100000 17 9126 rs -Ethernet72 233,234,235,236 C19 100000 18 9126 rs -Ethernet76 237,238,239,240 C20 100000 19 9126 rs -Ethernet80 241,242,243,244 C21 100000 20 9126 rs -Ethernet84 245,246,247,248 C22 100000 21 9126 rs -Ethernet88 249,250,251,252 C23 100000 22 9126 rs -Ethernet92 253,254,255,256 C24 100000 23 9126 rs -Ethernet96 193,194,195,196 C25 100000 24 9126 rs -Ethernet100 197,198,199,200 C26 100000 25 9126 rs -Ethernet104 201,202,203,204 C27 100000 26 9126 rs -Ethernet108 205,206,207,208 C28 100000 27 9126 rs -Ethernet112 209,210,211,212 C29 100000 28 9126 rs -Ethernet116 213,214,215,216 C30 100000 29 9126 rs -Ethernet120 217,218,219,220 C31 100000 30 9126 rs -Ethernet124 221,222,223,224 C32 100000 31 9126 rs -Ethernet128 161,162,163,164 C33 100000 32 9126 rs -Ethernet132 165,166,167,168 C34 100000 33 9126 rs -Ethernet136 169,170,171,172 C35 100000 34 9126 rs -Ethernet140 173,174,175,176 C36 100000 35 9126 rs -Ethernet144 177,178,179,180 C37 100000 36 9126 rs -Ethernet148 181,182,183,184 C38 100000 37 9126 rs -Ethernet152 185,186,187,188 C39 100000 38 9126 rs -Ethernet156 189,190,191,192 C40 100000 39 9126 rs -Ethernet160 129,130,131,132 C41 100000 40 9126 rs -Ethernet164 133,134,135,136 C42 100000 41 9126 rs -Ethernet168 137,138,139,140 C43 100000 42 9126 rs -Ethernet172 141,142,143,144 C44 100000 43 9126 rs -Ethernet176 145,146,147,148 C45 100000 44 9126 rs -Ethernet180 149,150,151,152 C46 100000 45 9126 rs -Ethernet184 153,154,155,156 C47 100000 46 9126 rs -Ethernet188 157,158,159,160 C48 100000 47 9126 rs -Ethernet192 97,98,99,100 C49 100000 48 9126 rs -Ethernet196 101,102,103,104 C50 100000 49 9126 rs -Ethernet200 105,106,107,108 C51 100000 50 9126 rs -Ethernet204 109,110,111,112 C52 100000 51 9126 rs -Ethernet208 113,114,115,116 C53 100000 52 9126 rs -Ethernet212 117,118,119,120 C54 100000 53 9126 rs -Ethernet216 121,122,123,124 C55 100000 54 9126 rs -Ethernet220 125,126,127,128 C56 100000 55 9126 rs -Ethernet224 65,66,67,68 C57 100000 56 9126 rs -Ethernet228 69,70,71,72 C58 100000 57 9126 rs -Ethernet232 73,74,75,76 C59 100000 58 9126 rs -Ethernet236 77,78,79,80 C60 100000 59 9126 rs -Ethernet240 81,82,83,84 C61 100000 60 9126 rs -Ethernet244 85,86,87,88 C62 100000 61 9126 rs -Ethernet248 89,90,91,92 C63 100000 62 9126 rs -Ethernet252 93,94,95,96 C64 100000 63 9126 rs diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/config_64x100G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/config_64x100G_midstone200i.yaml index e55efe3c88..74baab51f0 100755 --- a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/config_64x100G_midstone200i.yaml +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/config_64x100G_midstone200i.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/config_128x100G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/config_128x100G_midstone200i.yaml index b4b1c4fe84..ea31f498bd 100644 --- a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/config_128x100G_midstone200i.yaml +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/config_128x100G_midstone200i.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/config_32x400G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/config_32x400G_midstone200i.yaml index 2028451c75..f59530d3a8 100644 --- a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/config_32x400G_midstone200i.yaml +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/config_32x400G_midstone200i.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_A" netdev: - auto_create: "no" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/config_64x100G_nrz_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/config_64x100G_nrz_midstone200i.yaml index 7c75d19cfa..9788885f46 100644 --- a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/config_64x100G_nrz_midstone200i.yaml +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/config_64x100G_nrz_midstone200i.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/config_64x100G_nrz_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/config_64x100G_nrz_midstone200i.yaml index 8fb6a114a4..798a71c9a7 100644 --- a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/config_64x100G_nrz_midstone200i.yaml +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/config_64x100G_nrz_midstone200i.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/config_64x200G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/config_64x200G_midstone200i.yaml index 850a0f565e..9e67f7cf60 100644 --- a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/config_64x200G_midstone200i.yaml +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/config_64x200G_midstone200i.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/config_32x400G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/config_32x400G_Delta-et-c032if.yaml index 76cf0dc36b..424b4a83ce 100755 --- a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/config_32x400G_Delta-et-c032if.yaml +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/config_32x400G_Delta-et-c032if.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_A" netdev: - auto_create: "no" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/config_128x100G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/config_128x100G_Delta-et-c032if.yaml index 61e01852e1..16a237eb60 100755 --- a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/config_128x100G_Delta-et-c032if.yaml +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/config_128x100G_Delta-et-c032if.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/config_32x100G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/config_32x100G_Delta-et-c032if.yaml index d6319406d1..09719ec15c 100755 --- a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/config_32x100G_Delta-et-c032if.yaml +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/config_32x100G_Delta-et-c032if.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/config_32x200G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/config_32x200G_Delta-et-c032if.yaml index 44920a242b..bdd09d1f3f 100755 --- a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/config_32x200G_Delta-et-c032if.yaml +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/config_32x200G_Delta-et-c032if.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/config_32x400G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/config_32x400G_Delta-et-c032if.yaml index 76cf0dc36b..424b4a83ce 100755 --- a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/config_32x400G_Delta-et-c032if.yaml +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/config_32x400G_Delta-et-c032if.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_A" netdev: - auto_create: "no" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/config_64x100G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/config_64x100G_Delta-et-c032if.yaml index 28f4f6dd9f..b27f39ce11 100755 --- a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/config_64x100G_Delta-et-c032if.yaml +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/config_64x100G_Delta-et-c032if.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/config_64x200G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/config_64x200G_Delta-et-c032if.yaml index cbf750c1c1..498155cf37 100755 --- a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/config_64x200G_Delta-et-c032if.yaml +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/config_64x200G_Delta-et-c032if.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_1M.csv b/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_1M.csv new file mode 100644 index 0000000000..b9f4e750a8 --- /dev/null +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_1M.csv @@ -0,0 +1,342 @@ +VERSION,CABLE TYPE,VENDOR,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +1.2,DAC_1M,GENERIC,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,SPEED,ENCODING,,,,,,,,,SPEED,ENCODING,,,,,,,,,,,,,SPEED,ENCODING,,,,,,,SPEED,ENCODING,,,,,,,SPEED,ENCODING,,,,,,,,,, +,,,50G/400G,PAM4,,,,,,,,,25G/100G,NRZ,,,,,,,,,,,,,10G/40G,NRZ,,,,,,,LT 50G/400G ,PAM4,,,,,,,ANLT 25G/100G ,NRZ,,,,,,,,,, +index,Front Port,lane,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,RX_EQ_COARSE_TUNE_EFFORT_50G,RX_EQ_FINE_TUNE_EFFORT_50G,RX_GAINSHAPE1,RX_GAINSHAPE2,LINK_TRAINING,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,RX_GAINSHAPE1,RX_GAINSHAPE2,RX_AGC_TARGET,RX_EYE_DISQUALIFY_THRESHOLD_25G,RX_EQ_COARSE_TUNE_EFFORT_25G,RX_EQ_FINE_TUNE_EFFORT_25G,SD_RESET_THRESHOLD,SD_RESET_25G,LINK_TRAINING,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,RX_GAINSHAPE1,RX_GAINSHAPE2,LINK_TRAINING,RX_GAINSHAPE1,RX_GAINSHAPE2,RX_EQ_COARSE_TUNE_EFFORT_50G,RX_EQ_FINE_TUNE_EFFORT_50G,RX_CTLE_LF,RX_CTLE_HF,RX_CTLE_BW,LINK_TRAINING,RX_GAINSHAPE1,RX_GAINSHAPE2,RX_AGC_TARGET,RX_EYE_DISQUALIFY_THRESHOLD_25G,RX_EQ_COARSE_TUNE_EFFORT_25G,RX_EQ_FINE_TUNE_EFFORT_25G,SD_RESET_25G,SD_RESET_THRESHOLD_25G,LINK_TRAINING,AN,AN_ABILITY,FEC +0,0,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +1,0,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +2,0,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +3,0,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +4,0,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +5,0,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +6,0,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +7,0,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +8,1,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +9,1,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +10,1,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +11,1,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +12,1,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +13,1,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +14,1,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +15,1,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +16,2,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +17,2,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +18,2,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +19,2,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +20,2,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +21,2,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +22,2,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +23,2,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +24,3,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +25,3,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +26,3,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +27,3,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +28,3,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +29,3,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +30,3,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +31,3,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +32,4,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +33,4,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +34,4,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +35,4,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +36,4,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +37,4,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +38,4,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +39,4,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +40,5,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +41,5,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +42,5,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +43,5,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +44,5,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +45,5,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +46,5,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +47,5,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +48,6,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +49,6,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +50,6,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +51,6,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +52,6,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +53,6,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +54,6,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +55,6,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +56,7,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +57,7,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +58,7,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +59,7,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +60,7,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +61,7,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +62,7,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +63,7,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +64,8,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +65,8,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +66,8,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +67,8,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +68,8,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +69,8,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +70,8,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +71,8,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +72,9,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +73,9,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +74,9,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +75,9,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +76,9,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +77,9,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +78,9,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +79,9,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +80,10,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +81,10,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +82,10,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +83,10,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +84,10,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +85,10,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +86,10,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +87,10,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +88,11,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +89,11,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +90,11,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +91,11,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +92,11,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +93,11,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +94,11,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +95,11,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +96,12,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +97,12,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +98,12,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +99,12,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +100,12,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +101,12,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +102,12,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +103,12,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +104,13,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +105,13,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +106,13,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +107,13,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +108,13,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +109,13,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +110,13,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +111,13,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +112,14,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +113,14,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +114,14,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +115,14,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +116,14,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +117,14,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +118,14,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +119,14,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +120,15,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +121,15,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +122,15,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +123,15,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +124,15,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +125,15,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +126,15,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +127,15,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +128,16,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +129,16,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +130,16,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +131,16,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +132,16,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +133,16,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +134,16,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +135,16,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +136,17,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +137,17,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +138,17,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +139,17,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +140,17,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +141,17,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +142,17,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +143,17,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +144,18,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +145,18,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +146,18,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +147,18,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +148,18,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +149,18,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +150,18,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +151,18,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +152,19,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +153,19,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +154,19,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +155,19,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +156,19,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +157,19,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +158,19,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +159,19,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +160,20,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +161,20,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +162,20,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +163,20,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +164,20,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +165,20,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +166,20,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +167,20,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +168,21,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +169,21,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +170,21,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +171,21,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +172,21,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +173,21,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +174,21,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +175,21,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +176,22,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +177,22,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +178,22,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +179,22,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +180,22,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +181,22,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +182,22,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +183,22,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +184,23,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +185,23,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +186,23,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +187,23,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +188,23,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +189,23,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +190,23,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +191,23,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +192,24,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +193,24,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +194,24,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +195,24,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +196,24,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +197,24,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +198,24,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +199,24,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +200,25,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +201,25,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +202,25,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +203,25,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +204,25,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +205,25,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +206,25,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +207,25,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +208,26,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +209,26,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +210,26,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +211,26,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +212,26,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +213,26,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +214,26,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +215,26,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +216,27,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +217,27,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +218,27,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +219,27,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +220,27,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +221,27,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +222,27,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +223,27,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +224,28,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +225,28,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +226,28,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +227,28,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +228,28,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +229,28,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +230,28,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +231,28,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +232,29,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +233,29,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +234,29,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +235,29,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +236,29,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +237,29,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +238,29,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +239,29,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +240,30,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +241,30,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +242,30,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +243,30,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +244,30,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +245,30,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +246,30,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +247,30,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +248,31,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +249,31,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +250,31,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +251,31,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +252,31,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +253,31,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +254,31,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +255,31,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,0,1,130,100,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_3M.csv b/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_3M.csv new file mode 100644 index 0000000000..b6bbd017e4 --- /dev/null +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_DAC_3M.csv @@ -0,0 +1,342 @@ +VERSION,CABLE TYPE,VENDOR,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +1.2,DAC_3M,GENERIC,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,SPEED,ENCODING,,,,,,,,,SPEED,ENCODING,,,,,,,,,,,,,SPEED,ENCODING,,,,,,,SPEED,ENCODING,,,,,,,SPEED,ENCODING,,,,,,,,,, +,,,50G/400G,PAM4,,,,,,,,,25G/100G,NRZ,,,,,,,,,,,,,10G/40G,NRZ,,,,,,,LT 50G/400G,PAM4,,,,,,,ANLT 25G/100G,NRZ,,,,,,,,,, +index,Front Port,lane,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,RX_EQ_COARSE_TUNE_EFFORT_50G,RX_EQ_FINE_TUNE_EFFORT_50G,RX_GAINSHAPE1,RX_GAINSHAPE2,LINK_TRAINING,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,RX_GAINSHAPE1,RX_GAINSHAPE2,RX_AGC_TARGET,RX_EYE_DISQUALIFY_THRESHOLD_25G,RX_EQ_COARSE_TUNE_EFFORT_25G,RX_EQ_FINE_TUNE_EFFORT_25G,SD_RESET_THRESHOLD,SD_RESET_25G,LINK_TRAINING,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,RX_GAINSHAPE1,RX_GAINSHAPE2,LINK_TRAINING,RX_GAINSHAPE1,RX_GAINSHAPE2,RX_EQ_COARSE_TUNE_EFFORT_50G,RX_EQ_FINE_TUNE_EFFORT_50G,RX_CTLE_LF,RX_CTLE_HF,RX_CTLE_BW,LINK_TRAINING,RX_GAINSHAPE1,RX_GAINSHAPE2,RX_AGC_TARGET,RX_EYE_DISQUALIFY_THRESHOLD_25G,RX_EQ_COARSE_TUNE_EFFORT_25G,RX_EQ_FINE_TUNE_EFFORT_25G,SD_RESET_25G,SD_RESET_THRESHOLD_25G,LINK_TRAINING,AN,AN_ABILITY,FEC +0,0,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +1,0,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +2,0,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +3,0,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +4,0,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +5,0,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +6,0,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +7,0,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +8,1,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +9,1,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +10,1,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +11,1,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +12,1,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +13,1,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +14,1,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +15,1,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +16,2,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +17,2,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +18,2,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +19,2,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +20,2,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +21,2,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +22,2,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +23,2,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +24,3,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +25,3,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +26,3,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +27,3,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +28,3,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +29,3,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +30,3,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +31,3,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +32,4,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +33,4,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +34,4,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +35,4,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +36,4,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +37,4,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +38,4,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +39,4,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +40,5,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +41,5,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +42,5,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +43,5,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +44,5,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +45,5,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +46,5,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +47,5,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +48,6,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +49,6,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +50,6,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +51,6,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +52,6,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +53,6,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +54,6,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +55,6,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +56,7,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +57,7,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +58,7,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +59,7,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +60,7,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +61,7,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +62,7,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +63,7,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +64,8,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +65,8,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +66,8,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +67,8,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +68,8,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +69,8,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +70,8,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +71,8,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +72,9,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +73,9,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +74,9,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +75,9,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +76,9,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +77,9,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +78,9,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +79,9,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +80,10,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +81,10,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +82,10,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +83,10,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +84,10,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +85,10,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +86,10,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +87,10,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +88,11,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +89,11,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +90,11,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +91,11,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +92,11,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +93,11,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +94,11,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +95,11,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +96,12,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +97,12,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +98,12,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +99,12,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +100,12,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +101,12,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +102,12,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +103,12,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +104,13,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +105,13,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +106,13,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +107,13,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +108,13,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +109,13,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +110,13,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +111,13,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +112,14,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +113,14,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +114,14,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +115,14,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +116,14,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +117,14,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +118,14,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +119,14,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +120,15,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +121,15,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +122,15,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +123,15,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +124,15,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +125,15,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +126,15,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +127,15,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +128,16,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +129,16,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +130,16,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +131,16,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +132,16,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +133,16,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +134,16,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +135,16,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +136,17,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +137,17,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +138,17,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +139,17,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +140,17,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +141,17,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +142,17,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +143,17,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +144,18,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +145,18,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +146,18,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +147,18,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +148,18,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +149,18,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +150,18,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +151,18,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +152,19,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +153,19,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +154,19,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +155,19,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +156,19,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +157,19,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +158,19,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +159,19,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +160,20,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +161,20,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +162,20,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +163,20,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +164,20,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +165,20,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +166,20,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +167,20,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +168,21,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +169,21,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +170,21,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +171,21,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +172,21,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +173,21,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +174,21,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +175,21,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +176,22,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +177,22,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +178,22,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +179,22,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +180,22,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +181,22,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +182,22,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +183,22,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +184,23,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +185,23,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +186,23,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +187,23,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +188,23,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +189,23,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +190,23,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +191,23,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +192,24,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +193,24,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +194,24,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +195,24,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +196,24,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +197,24,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +198,24,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +199,24,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +200,25,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +201,25,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +202,25,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +203,25,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +204,25,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +205,25,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +206,25,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +207,25,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +208,26,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +209,26,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +210,26,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +211,26,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +212,26,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +213,26,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +214,26,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +215,26,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +216,27,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +217,27,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +218,27,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +219,27,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +220,27,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +221,27,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +222,27,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +223,27,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +224,28,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +225,28,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +226,28,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +227,28,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +228,28,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +229,28,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +230,28,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +231,28,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +232,29,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +233,29,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +234,29,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +235,29,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +236,29,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +237,29,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +238,29,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +239,29,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +240,30,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +241,30,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +242,30,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +243,30,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +244,30,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +245,30,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +246,30,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +247,30,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +248,31,0,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +249,31,1,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +250,31,2,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +251,31,3,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +252,31,4,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +253,31,5,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +254,31,6,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +255,31,7,0,0,0,0,0,Medium,HIGH,0,2,0,0,0,0,0,0,2,2,130,150,Low,Low,5,TRUE,0,3,2,-2,0,4,0,1,0,0,2,Medium,High,0,10,10,1,0,1,130,100,Low,Low,0,NA,1,1,100GBASE-KR4,NONE +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_Optics.csv b/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_Optics.csv new file mode 100644 index 0000000000..758ee73173 --- /dev/null +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/CSV/TL7_Optics.csv @@ -0,0 +1,289 @@ +VERSION,CABLE TYPE,VENDOR,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +1.2,OPTICS,GENERIC,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,SPEED,ENCODING,,,,,,,,,,SPEED,ENCODING,,,,,,,,,,,,,,SPEED,ENCODING,,,,,, +,,,50G/400G,PAM4,,,,,,,,,,25G/100G,NRZ,,,,,,,,,,,,,,10G/40G,NRZ,,,,,, +index,Front Port,lane,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,Optical Module CTLE,RX_EQ_COARSE_TUNE_EFFORT_50G,RX_EQ_FINE_TUNE_EFFORT_50G,RX_GAINSHAPE1,RX_GAINSHAPE2,LINK_TRAINING,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,Optical Module CTLE,RX_GAINSHAPE1,RX_GAINSHAPE2,RX_AGC_TARGET,RX_EYE_DISQUALIFY_THRESHOLD_25G,RX_EQ_COARSE_TUNE_EFFORT_25G,RX_EQ_FINE_TUNE_EFFORT_25G,SD_RESET_THRESHOLD,SD_RESET_25G,LINK_TRAINING,TX_EQ_ATTN,TX_EQ_PRE1,TX_EQ_PRE2,TX_EQ_PRE3,TX_EQ_POST,RX_GAINSHAPE1,RX_GAINSHAPE2,LINK_TRAINING +0,0,0,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,4,3,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +1,0,1,0,4,-1,0,2,6,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +2,0,2,0,4,0,0,0,6,Medium,High,0,2,0,0,4,0,0,4,3,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +3,0,3,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,4,3,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +4,0,4,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +5,0,5,0,4,0,0,4,5.5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +6,0,6,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +7,0,7,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,High,High,NA,FALSE,0,0,0,0,0,0,0,0,0 +8,1,0,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +9,1,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +10,1,2,0,4,0,0,0,6,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +11,1,3,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +12,1,4,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,-1,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +13,1,5,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +14,1,6,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,6,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +15,1,7,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +16,2,0,0,4,0,0,0,6,Medium,High,0,2,0,0,2,0,0,4,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +17,2,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +18,2,2,0,4,0,0,0,6,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +19,2,3,0,4,0,0,0,6,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +20,2,4,0,4,0,0,4,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +21,2,5,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +22,2,6,0,4,0,0,4,5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +23,2,7,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +24,3,0,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +25,3,1,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +26,3,2,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +27,3,3,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +28,3,4,0,4,-1,0,0,5.5,Medium,High,0,2,0,0,4,0,0,4,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +29,3,5,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +30,3,6,0,2,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +31,3,7,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +32,4,0,0,4,0,0,2,4,Medium,High,0,2,0,0,4,0,1,2,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +33,4,1,0,2,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +34,4,2,0,4,0,0,2,4,Medium,High,0,2,0,0,2,0,0,2,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +35,4,3,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +36,4,4,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +37,4,5,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +38,4,6,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +39,4,7,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +40,5,0,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +41,5,1,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +42,5,2,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +43,5,3,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +44,5,4,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +45,5,5,0,2,0,0,4,4,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +46,5,6,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +47,5,7,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +48,6,0,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +49,6,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +50,6,2,0,4,0,0,2,4,Medium,High,0,2,0,0,4,-1,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +51,6,3,0,4,0,0,0,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +52,6,4,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +53,6,5,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +54,6,6,0,2,0,0,2,5.5,Medium,High,0,2,0,0,2,0,1,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +55,6,7,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +56,7,0,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +57,7,1,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +58,7,2,0,4,-1,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +59,7,3,0,4,0,0,2,4,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +60,7,4,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +61,7,5,0,4,0,0,0,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +62,7,6,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +63,7,7,0,4,0,0,4,4,Medium,High,0,2,0,1,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +64,8,0,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +65,8,1,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +66,8,2,0,4,0,0,2,6,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +67,8,3,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +68,8,4,0,4,0,0,4,6,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +69,8,5,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +70,8,6,0,2,0,0,4,6,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +71,8,7,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,2,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +72,9,0,0,4,0,0,4,5.5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +73,9,1,0,4,0,0,0,6.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +74,9,2,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +75,9,3,0,4,0,0,0,6.5,Medium,High,0,2,0,0,4,0,0,4,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +76,9,4,0,4,0,0,4,6,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +77,9,5,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +78,9,6,0,4,0,0,2,6,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +79,9,7,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +80,10,0,0,4,0,0,4,4,Medium,High,0,2,0,0,4,0,0,4,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +81,10,1,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +82,10,2,0,4,0,0,4,4,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +83,10,3,0,4,0,0,2,6,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +84,10,4,0,4,-1,0,4,6,Medium,High,0,2,0,0,4,0,0,4,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +85,10,5,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +86,10,6,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +87,10,7,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +88,11,0,0,4,0,0,0,6.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +89,11,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +90,11,2,0,4,0,0,0,6,Medium,High,0,2,0,0,4,0,1,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +91,11,3,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +92,11,4,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +93,11,5,0,4,0,0,2,7,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +94,11,6,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +95,11,7,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +96,12,0,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +97,12,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +98,12,2,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +99,12,3,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +100,12,4,0,4,0,0,2,6,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +101,12,5,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +102,12,6,0,4,0,0,4,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +103,12,7,0,4,0,0,0,5.5,Medium,High,0,2,0,1,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +104,13,0,0,2,0,0,4,4.5,Medium,High,0,2,0,0,4,-1,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +105,13,1,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +106,13,2,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +107,13,3,0,2,0,0,2,4.5,Medium,High,0,2,0,1,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +108,13,4,0,4,0,0,2,6,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +109,13,5,0,4,0,0,4,4,Medium,High,0,2,0,0,4,0,1,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +110,13,6,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +111,13,7,0,4,-1,0,0,5,Medium,High,0,2,0,0,4,-1,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +112,14,0,0,4,0,0,0,5,Medium,High,0,2,0,0,2,0,0,2,2,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +113,14,1,0,4,0,0,2,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +114,14,2,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,1,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +115,14,3,0,4,0,0,0,5,Medium,High,0,2,0,1,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +116,14,4,0,4,0,0,4,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +117,14,5,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +118,14,6,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +119,14,7,0,4,0,0,0,5,Medium,High,0,2,0,1,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +120,15,0,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +121,15,1,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +122,15,2,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +123,15,3,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +124,15,4,0,4,-1,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +125,15,5,0,4,0,0,0,5,Medium,High,0,2,0,0,4,-1,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +126,15,6,0,4,0,0,0,4.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +127,15,7,0,4,0,0,0,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +128,16,0,0,2,0,0,2,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +129,16,1,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +130,16,2,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,1,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +131,16,3,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +132,16,4,0,4,0,0,0,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +133,16,5,0,2,0,0,2,5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +134,16,6,0,4,0,0,0,6.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +135,16,7,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,1,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +136,17,0,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +137,17,1,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +138,17,2,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +139,17,3,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +140,17,4,1,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +141,17,5,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +142,17,6,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +143,17,7,0,4,0,0,2,5,Medium,High,0,2,0,1,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +144,18,0,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +145,18,1,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +146,18,2,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +147,18,3,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +148,18,4,0,2,0,0,0,7,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +149,18,5,0,2,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +150,18,6,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +151,18,7,0,4,0,0,4,4,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +152,19,0,0,2,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +153,19,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +154,19,2,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +155,19,3,0,4,0,0,-2,6,Medium,High,0,2,0,0,4,-1,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +156,19,4,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +157,19,5,0,4,0,0,0,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +158,19,6,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +159,19,7,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +160,20,0,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +161,20,1,0,2,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +162,20,2,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +163,20,3,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +164,20,4,0,2,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +165,20,5,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +166,20,6,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +167,20,7,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +168,21,0,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +169,21,1,0,4,-1,0,0,6,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +170,21,2,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +171,21,3,0,4,0,0,0,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +172,21,4,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +173,21,5,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +174,21,6,0,2,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +175,21,7,0,4,0,0,2,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +176,22,0,0,4,0,0,4,5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +177,22,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +178,22,2,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,4,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +179,22,3,0,4,-1,0,4,5.5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +180,22,4,0,4,0,0,4,4.5,Medium,High,0,2,0,0,2,-1,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +181,22,5,0,4,0,0,4,4.5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +182,22,6,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +183,22,7,0,4,0,0,4,5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +184,23,0,0,2,0,0,2,6,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +185,23,1,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +186,23,2,0,4,0,0,2,6,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +187,23,3,0,4,0,0,0,6,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +188,23,4,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +189,23,5,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +190,23,6,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +191,23,7,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,2,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +192,24,0,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +193,24,1,0,2,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +194,24,2,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +195,24,3,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +196,24,4,0,4,0,0,4,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +197,24,5,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +198,24,6,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +199,24,7,0,4,0,0,2,4,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +200,25,0,0,4,0,0,0,5.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +201,25,1,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +202,25,2,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +203,25,3,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +204,25,4,0,4,0,0,0,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +205,25,5,0,4,0,0,0,5,Medium,High,0,2,0,1,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +206,25,6,0,4,0,0,2,5,Medium,High,0,2,0,0,4,-1,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +207,25,7,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,0,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +208,26,0,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,-1,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +209,26,1,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +210,26,2,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +211,26,3,0,4,0,0,2,4.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +212,26,4,0,2,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +213,26,5,0,4,0,0,0,5.5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +214,26,6,0,4,0,0,4,3.5,Medium,High,0,2,0,0,2,-1,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +215,26,7,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +216,27,0,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +217,27,1,0,4,0,0,2,6,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +218,27,2,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +219,27,3,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,2,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +220,27,4,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +221,27,5,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +222,27,6,0,2,0,0,0,6,Medium,High,0,2,0,0,4,0,0,2,5,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +223,27,7,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +224,28,0,0,4,0,0,0,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +225,28,1,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +226,28,2,0,4,0,0,0,4.5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +227,28,3,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +228,28,4,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +229,28,5,0,2,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +230,28,6,0,2,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +231,28,7,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,0,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +232,29,0,0,4,0,0,4,4,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +233,29,1,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +234,29,2,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +235,29,3,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +236,29,4,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +237,29,5,0,4,0,0,4,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +238,29,6,0,4,0,0,2,5,Medium,High,0,2,0,0,2,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +239,29,7,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +240,30,0,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,3,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +241,30,1,0,4,0,0,2,5.5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +242,30,2,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +243,30,3,0,2,0,0,2,6,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +244,30,4,0,4,0,0,2,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +245,30,5,0,4,0,0,4,5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +246,30,6,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +247,30,7,0,4,0,0,4,5,Medium,High,0,2,0,0,2,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +248,31,0,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +249,31,1,0,4,0,-1,2,5.5,Medium,High,0,2,0,0,4,0,1,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +250,31,2,0,4,0,0,2,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +251,31,3,0,4,0,0,4,4.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +252,31,4,0,4,-1,0,4,5.5,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +253,31,5,0,4,0,0,4,6,Medium,High,0,2,0,0,4,0,0,4,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +254,31,6,0,4,0,0,2,5,Medium,High,0,2,0,0,4,-1,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +255,31,7,0,4,0,0,2,5.5,Medium,High,0,2,0,0,4,0,0,2,4,0,0,100,100,LOW,LOW,NA,FALSE,0,0,0,0,0,0,0,0,0 +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/config_32x400G_wistron_sw_to3200k.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/config_32x400G_wistron_sw_to3200k.yaml index 34b1437fa3..23445c6ded 100644 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/config_32x400G_wistron_sw_to3200k.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/config_32x400G_wistron_sw_to3200k.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_A" netdev: - auto_create: "no" @@ -13,9 +14,14 @@ nodes: ilpm_enable: "1" forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" ecn_stats_enable: "1" - led_cfg_sck_rate: "0x4" - led_refresh_precliff_timer: "0xa" - led_refresh_cliff_timer: "0xc350" + pcie_attn: "10, 0, 0, 0" + pcie_post: "10, 18, 18, 18" + pcie_pre1: "0, 0, 0, 0" + led_cfg_sck_rate: "0x5" + led_refresh_precliff_timer: "0x18eec2" + led_refresh_cliff_timer: "0x15e" + led_cfg_pic_stream_mode: "1" + led_refresh_tmr_ctl_enable: "1" txring: - txring_id: "0" desc_count: "1024" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/ivm.sai.config.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/ivm.sai.config.yaml index d306017f5f..0c1644ab7d 100755 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/ivm.sai.config.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k/ivm.sai.config.yaml @@ -4,6 +4,6 @@ IFCS_INNO_CLI_PORT : "9999" IFCS_TARGET : "device" INNOVIUM_DIR : "/innovium" PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" -PLATFORM_LIBRARY: "/usr/share/sonic/platform/libplatform.so" +PLATFORM_LIBRARY: "/usr/share/sonic/platform/lib_ivm_serdes_pltfm.so" IVM_SAI_DATAPATH_CONFIG_FILE: "/usr/share/sonic/hwsku/ivm.sai.datapath.config.yaml" IVM_SAI_PARAM_A0008: "32" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/config_104x1025G_6x100G_wistron_sw_to3200k.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/config_104x1025G_6x100G_wistron_sw_to3200k.yaml index 41dea285a6..2e019733c4 100644 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/config_104x1025G_6x100G_wistron_sw_to3200k.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/config_104x1025G_6x100G_wistron_sw_to3200k.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" @@ -13,9 +14,14 @@ nodes: ilpm_enable: "1" forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" ecn_stats_enable: "1" - led_cfg_sck_rate: "0x4" - led_refresh_precliff_timer: "0xa" - led_refresh_cliff_timer: "0xc350" + pcie_attn: "10, 0, 0, 0" + pcie_post: "10, 18, 18, 18" + pcie_pre1: "0, 0, 0, 0" + led_cfg_sck_rate: "0x5" + led_refresh_precliff_timer: "0x18eec2" + led_refresh_cliff_timer: "0x15e" + led_cfg_pic_stream_mode: "1" + led_refresh_tmr_ctl_enable: "1" txring: - txring_id: "0" desc_count: "1024" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/ivm.sai.config.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/ivm.sai.config.yaml index 441aec9fba..5e5d2fe668 100755 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/ivm.sai.config.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_104x1025_6x100/ivm.sai.config.yaml @@ -4,6 +4,6 @@ IFCS_INNO_CLI_PORT : "9999" IFCS_TARGET : "device" INNOVIUM_DIR : "/innovium" PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" -PLATFORM_LIBRARY: "/usr/share/sonic/platform/libplatform.so" +PLATFORM_LIBRARY: "/usr/share/sonic/platform/lib_ivm_serdes_pltfm.so" IVM_SAI_DATAPATH_CONFIG_FILE: "/usr/share/sonic/hwsku/ivm.sai.datapath.config.yaml" IVM_SAI_PARAM_A0008: "32" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/config_24x400G_8x100G_wistron_sw_to3200k.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/config_24x400G_8x100G_wistron_sw_to3200k.yaml index b81b3c6912..76171942ee 100644 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/config_24x400G_8x100G_wistron_sw_to3200k.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/config_24x400G_8x100G_wistron_sw_to3200k.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_A" netdev: - auto_create: "no" @@ -13,9 +14,14 @@ nodes: ilpm_enable: "1" forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" ecn_stats_enable: "1" - led_cfg_sck_rate: "0x4" - led_refresh_precliff_timer: "0xa" - led_refresh_cliff_timer: "0xc350" + pcie_attn: "10, 0, 0, 0" + pcie_post: "10, 18, 18, 18" + pcie_pre1: "0, 0, 0, 0" + led_cfg_sck_rate: "0x5" + led_refresh_precliff_timer: "0x18eec2" + led_refresh_cliff_timer: "0x15e" + led_cfg_pic_stream_mode: "1" + led_refresh_tmr_ctl_enable: "1" txring: - txring_id: "0" desc_count: "1024" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/ivm.sai.config.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/ivm.sai.config.yaml index 8ba5cfd54d..8014caa1da 100755 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/ivm.sai.config.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_24x400_8x100/ivm.sai.config.yaml @@ -4,6 +4,6 @@ IFCS_INNO_CLI_PORT : "9999" IFCS_TARGET : "device" INNOVIUM_DIR : "/innovium" PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" -PLATFORM_LIBRARY: "/usr/share/sonic/platform/libplatform.so" +PLATFORM_LIBRARY: "/usr/share/sonic/platform/lib_ivm_serdes_pltfm.so" IVM_SAI_DATAPATH_CONFIG_FILE: "/usr/share/sonic/hwsku/ivm.sai.datapath.config.yaml" IVM_SAI_PARAM_A0008: "32" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/config_32x100G_wistron_sw_to3200k.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/config_32x100G_wistron_sw_to3200k.yaml index 65111d3480..a6f5d00d8b 100644 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/config_32x100G_wistron_sw_to3200k.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/config_32x100G_wistron_sw_to3200k.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_B" netdev: - auto_create: "no" @@ -12,9 +13,14 @@ nodes: max_lossless_tc: "2" ilpm_enable: "1" forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" - led_cfg_sck_rate: "0x4" - led_refresh_precliff_timer: "0xa" - led_refresh_cliff_timer: "0xc350" + pcie_attn: "10, 0, 0, 0" + pcie_post: "10, 18, 18, 18" + pcie_pre1: "0, 0, 0, 0" + led_cfg_sck_rate: "0x5" + led_refresh_precliff_timer: "0x18eec2" + led_refresh_cliff_timer: "0x15e" + led_cfg_pic_stream_mode: "1" + led_refresh_tmr_ctl_enable: "1" txring: - txring_id: "0" desc_count: "1024" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/ivm.sai.config.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/ivm.sai.config.yaml index 47931e341c..8ae2b9683d 100755 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/ivm.sai.config.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_32x100/ivm.sai.config.yaml @@ -4,6 +4,6 @@ IFCS_INNO_CLI_PORT : "9999" IFCS_TARGET : "device" INNOVIUM_DIR : "/innovium" PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" -PLATFORM_LIBRARY: "/usr/share/sonic/platform/libplatform.so" +PLATFORM_LIBRARY: "/usr/share/sonic/platform/lib_ivm_serdes_pltfm.so" IVM_SAI_DATAPATH_CONFIG_FILE: "/usr/share/sonic/hwsku/ivm.sai.datapath.config.yaml" IVM_SAI_PARAM_A0008: "32" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/config_72x25G_6x400G_wistron_sw_to3200k.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/config_72x25G_6x400G_wistron_sw_to3200k.yaml index f01ef1f495..5eb611aa7d 100644 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/config_72x25G_6x400G_wistron_sw_to3200k.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/config_72x25G_6x400G_wistron_sw_to3200k.yaml @@ -4,6 +4,7 @@ ifcs: nodes: - node_id: "0" options: + sd_low_power_mode_global_default: "true" sku: "configs/sku/innovium.77700_A" netdev: - auto_create: "no" @@ -13,9 +14,14 @@ nodes: ilpm_enable: "1" forward_profile: "IFCS_FORWARD_PROFILE_ID_PROFILE_E" ecn_stats_enable: "1" - led_cfg_sck_rate: "0x4" - led_refresh_precliff_timer: "0xa" - led_refresh_cliff_timer: "0xc350" + pcie_attn: "10, 0, 0, 0" + pcie_post: "10, 18, 18, 18" + pcie_pre1: "0, 0, 0, 0" + led_cfg_sck_rate: "0x5" + led_refresh_precliff_timer: "0x18eec2" + led_refresh_cliff_timer: "0x15e" + led_cfg_pic_stream_mode: "1" + led_refresh_tmr_ctl_enable: "1" txring: - txring_id: "0" desc_count: "1024" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/ivm.sai.config.yaml b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/ivm.sai.config.yaml index c7943895f8..01fe64ec7b 100755 --- a/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/ivm.sai.config.yaml +++ b/device/wistron/x86_64-wistron_sw_to3200k-r0/Wistron_sw_to3200k_72x25_6x400/ivm.sai.config.yaml @@ -4,6 +4,6 @@ IFCS_INNO_CLI_PORT : "9999" IFCS_TARGET : "device" INNOVIUM_DIR : "/innovium" PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" -PLATFORM_LIBRARY: "/usr/share/sonic/platform/libplatform.so" +PLATFORM_LIBRARY: "/usr/share/sonic/platform/lib_ivm_serdes_pltfm.so" IVM_SAI_DATAPATH_CONFIG_FILE: "/usr/share/sonic/hwsku/ivm.sai.datapath.config.yaml" IVM_SAI_PARAM_A0008: "32" diff --git a/device/wistron/x86_64-wistron_sw_to3200k-r0/libplatform.so b/device/wistron/x86_64-wistron_sw_to3200k-r0/libplatform.so deleted file mode 100644 index 1ca41771ff2dd58339f90189c280eb1b1e5e6ffa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26640 zcmdU23wTu3oj;R@gy#eW&7zjeBZ3b?2*x504TLL$5{N*Qx~0P;nLKnd6XpS-Uun}$ zf*Ge-V_RMN*p;rf#kRXkcPnezj~cWZw6u*aZmDbAh-haF-3CE-+R|o!|MR$W?__2O zDf_K^b>^J&JO9`DpXWVia`=?K?v5Orjj1P>-Nq=@KS3ZBGNXT+j3B6BOV~JkU(2rH zwE4-b5wXox0#YGk8V5+nW%$HoeymF1D%_jP$yo1iM5y?3kR-l>^#U(guknZqdu35n zSRlw)9zyyYmHDaRTuG-wqNS($tzbRH2kzp@5#c%kGZiYnyTM0xj`k^(gd3&4OnxaM z2jEemEDkT*G~nd6HS25GwvP_o|HNHuw=|r0EZF&_gZ+2Dmj7$wqkN(xG2`(0Dzn`= z#l|89dCc}uUZIWhX5jN7eAv`qoLHs5db(r#;dc(b`MFQjUh{hN_T#^b&UpBtU!K^$ z<(h3vD>r_5+5xMUWkIFqtDHNzW^EO z=+9@s!x`|$GT`KA4WHC!dst}|f!6zO4;SBg6GvH;wHGEQ^HvpuQ zPwjSgDlyUzWuSkB;}h8rWk=a0c~`;@h3qQUezztO5m5KNoK0jODi-N2SBr2nr!Qjr z%V!Bde$N9=^iNd?pkKE4t0cZd;)^By-ytOWTQmXGO57pkr`oe$((je@i)DxX4#&r{ zedDD78Tb%RWkqaXv9wcmR0=Lv4;`^f}JDHWvwSd73{C!aH|3H%bYW9#IpWqIAKswMqB-E zk!E>L+uE%~j7@Tpo|F zj%#k+Wk>X{P83yZ zoR8)T=>neCOt{g;ku%?ftGSREN=>+Vy|BcDo9D|46HdC-<1pdM*OXUn!p;8KV#4K; zhKt%}!c|pKMw1Dj%qhiJs|lZC!rM%^-GsNB@Tn%e%Y>W#++)J8Fwr~0rwbg>`~`Pt z%+c8!%#THp=?MRz;CVqbT)qlf!^NxdZJ$|z7^RyiGd?hkr+6u)sp{hWJY7aG2JpC@EsVd?XJpB%(sS4tyJbjYV)MVotPrpWKs)~3aPydwCR0VOy(=St+Tpu6$ z^YE~vJO2O-aCEQu2Lv^a>l2R1TaIvI%Fdjv&%=?&R|`kJyLEVg`~~`5g5GbUKa$9G zM4odTdFOVAt>5uVBE*@eKg*ea8hm%FBl6<#N#bu`aVz*(Xr3dy;v2|@%E(*6Nu+<3 zhS35h#+vZ8^~L-`5ZcZ@Ph1Tp_L&_pnW}O{D+pQeIv97aG;T%>`0oP@S;PHX< zeP%n+$L~U%bT~eJx(DgV?$1U-U6Gm&N2I$AS$%qf$Q*rojECL&zC#s=eV?ZyeX$$4 zlk}cLR7D0lozQ3}NpN(R`#uZ_pnaUsh#qr}!fZS_)xhp5EpR*Ca)dy1{NxE|wy5nv|aYxzW zZo4n5;~xLR7#z0?({|EvKf^+p9Cr?)KIo2PuyK@*%XepWT*L3j;J6A*5=qBBUM3v( z?-2DtcU)g$)Q&sm%j&oVkaW>w+&Ij(Nyj~~NI32@5M^?lCMSmpmtb;u);c*%Pniqs zoev5E%Z!m}f_Uh^hlgouy5JOX)X_bu6M|_?(D`wVMW$iMPd8D--oH2}E~1IzIV@?C zPAn-EPFw-w{y#WTN0Beui4{*}apDv2jlqe#u}(}n@l1(uVgjN}PNZc@c=umU0 zW5F`{612&utZj0{f+dvFNJE+0;~&l?JM)=z%arjav~08O{ouctF1&_X-)bzlla70S zfpFZj5S7+((~10p=C~tgFW|WT*Rncp5%@3KaTD?8l62goHwnk>fvB{OdmXFl51iw= z-o1e1{`Qwy9hW#W2FLw$oY`@WHwwp9!4#9@z9%P*iR3feSbC`gFF1H(nJVRPg{hsr zp$6*zp&O%mN3;g-1wVBhIf+++en@)`98$5D1SGXE9Xq1r1IHPc^y}7@4QdQ%U=4g z|C*N`-e>Xa4FhIoH(BIL3sZ%I zZ$~VPgC8-~?ldZ&Xj+Hni^AoMR{2^}?H@^*7i(q7FQ1EFCyy zU*J0zm}Ym6cAEYCZ_O)~5fiO>v9}i$mT|H7$I}-#_}xy^?W-7Ak`CN^op4|^OiJs( zuM;^OIOT)nz>O$)a>Lf2L^YG*4Ip=aNb`y zhu|H08!V*~cZkg-Y#d?IFgFw$|Itw5@1v0>t^3JbVcmAH8`jx7{uxBV!agF0g$4BW zm&|e=scGjsd>ovgWjy(Tjn5YF4I8{O3*A=)9mv?=Y*nVni`ajh0Ak`m=K)~@dz=vTp+h(=l-rNd{51W3ZsR{19<g~Uye7LQYp@750-(hSj1{V>Ul>iZ$LpX36%M#ww?nJ2IX`vZ`p z6`hzUhfUgoJqMN($t~D(*d0AUFRqrH<+p`iC4~^(E=4bbHmsG@s2#77Hi5(?Nv0%8 zsQ%++Ns?8PWbikJ6lAivU6Jr6Q4A{KfG0pF9I%lnL@C!vA-7P$BPfL^<(;BS|3#%d zKU+BPF2lYA%wusM$rg@yLz2u-lJHWlOOm`GN%E5tSz7B4n)|5wI7?}7D{pgz%cJ+n!zF0AY zM)aYs{%FlmG?c(ZjrMyt9OsDE3^=;0u>6K0ksnjD&KE}TlZ9b>=Na1ejiTou z>;AWRd_Ns`P2%kYU@<_;kTLB>jrWg_B7+y&7&1}@rNAuZm03b?0_}U>OgIi=O8_MY zCHu2@?PW2XxmZNvpe2XM4|nlh{ioY`@Ms$aeR?lg=v0G7Bsnm_ks^iVFoBr0D2P#= z%Q34@e_imMpa5cc86440p@T-#cQj>q(WvBYjEWnTw4VfiH@>}{@p(PIKvZXXwXspxZ}uxI2=2f z=de8o@!TJ_{wND4uCzb+Do7)}rZ=t6U;>Ed;vi zyezzXXgG9JG&B^gIv1^>9k4*CJ)BmujT57lgN z^Wa7RHfz2h=lM4emKhA_3v6)C;4FiIQ(Qh+XaJmo_2AGjH#CPf{Pok^35gFWCp`9s za>CG6j402uPtG6I6yZ3-TP+4*9|%FGeG*jXxwxqY)f$89t3=g;<3~LfPS}Fe@#X)k za3Uv|GdQD9KY`bKHaHcL$rLF-gbtc}9NnEgs8H*1U=D;LV;^NyfQl-F_a8b}Cl2(F zL)0gXjDBRmILBU7rF~_dMy)@hABgG)x~s=aRTzWX;0<&~(JJz}vPa1ZsS_02%oJ~O ztxuCV(W(Rdc$E(pYa>Hq_}>U>A#8~-kVqk==xSlMpU{Z@4CdHpSg2U3;jUb7@Sgv* zs+oK6(>#pa&&Z-WBCm+jQgzcX@-Lv2qnZ66_lEsoZ$$rgRR4B3G1cDj*B}fhih@(Z ziOKek_rMi@91v*lgJGZz58NKn_seu|>@v>&WK@5WYVI1Uxk*%W*M<|h!8wCBM)Qki zVQA5hp`GMUmC@2#|9$~)l! zn`8WQ1U+}wzNPo9{UiFZv-YX_zO(j1eV_e43|}iAxEAiT!RlE2SHr_9<6V2<*%i7-Cgav~Sic(Xw; zn-dJ#K!C*#vRp>iIAqa)HiW5Eato3j2Fa<{sc)aKOn&{;4JLvY-KrPes#na!+YP3F z1{1H>`1mVmG`F&2?$mp~&x;8;pXUnBVemlWAQBL|7pGPN_?iH^4B!hK;6K#tlm1gAS^cK!Qnj^i9|Dh>_0()(vu~3A}*YC3O@;e;Sn9J5Z~?e-PsCZJhDwi zs#T;=MVN@t5(73HF0FuMunM@#fUh^fygWvZ-JC4Oa=SgLYBzofV+vm0hYLnuzc^jWMH4i8ec@+OB;y}9!Q(Ft!p zAmZGcP98VBSuK*vn=3_f3k)XbmWgDMOwJKW<;`i7>|SxWNO`jofbizu;kceVk$w-y zBLhZx)B%VngyEMf!7K`#B%qQR1n>Qv2oe#!U%d@nfyn^N0}N5e@fr}-`=eE-qM?}a z^Q-gtIhN%YSVu6Jm(0YtZ##+^r7H)_T^GfC<_0tKqiwupT!ixP++yJ;w_lY0?W-*O zTP~J=(RwpKA0?wTc%3?l->Z$rf##jaw?3j_S!s*Fi+qS3v!Jg;q#!W@(e}F-fo??K za6}(6|G8Ju{GZ_m+jFdqvM)+*uph`bX@V?Bv-tH8;m8%CuPU9dLpgCW=DSI zXws3?;xCeYE6(b9J%sgs{91%w5YH{skJ}%7tQ_KMmWF55dlijTDr^OtMp&4Wp z?r(>*@XHm+K`e9U!jG)8DyGFF6w@ShX%&C?0*Yy|3dJ;!U0TJrWmHTn2kbau@ip?e zvKP}UO-`!{GWjyy@STaakF6Y&6-%ETixu%{SYOgSV(*-QSZ1S^W;BWq?w$OPLZXlI zHT!6X_)+!6WfxFPi*7Uq{(^8x6|cysI9p@**I$pN8Z!I6VoX*nc;nJqv3^WeeBhhNsZdUz!3Y`vp1h*I5JZ51b(wHE9)gY||sr>m&{9(*sG%Omvd3%bf@PZd5F9i#|x_=bp zDC-dr(Z0I;tzftp##UfWs1M0sjm8h~`7kkJ5kCaK+Yh$$_2B?*i0V|9lyfqjs35VB zwhnOMl!X9q|2H4yFWhN`KoxHm0~MD<)k}R@Rf$sNT@qCv%dV=E8v6k48vo@EJo_SE z!0=aFsMy#fbHzs4GCg5`@MbIe7{1ErYcc*hJLqMt_~UBU7-({} zB2R>6%-`m$3wqp6PlFL{N=9pU66)UWtaAq0I^RxK<*siIwJ=9>W0TBjKn`eJjdj6B z9&_(1MWzsCE37k|I4?QnTQ?xk9B0Keemk5$fEua^AVb8UXB z#}#bw`CC>H{aUZrw}WgiD_NYXAGR!jF?UosS8u#WyT|Q!76-D*SAUG2qQlP?h64VD zaIxRLFyQkx*DX{wEDY>i5cDlBD=mG%$#a}2alJcGB1$WZlj4^R_-px0UYW%_F0b1e zXmz{mS$XLiR#v`-Ekc;aFQfKvQY80T9o-z@4DM=mvkldo*H*4v$5yYbbS|pmL0NTq z6|1b-w0T3-(oz+nmnb~edKtC;q(ZL0xn4+1m1op5HEI5r{wWoaqTfVsx=BEr&#yJ` zx?0>^+eo|DdePvT>$PTYYbYohUkTHLO>VyzHy@;<$E^zut~$3yLbc|A=Jf?N#ZUqU zt6x;Ju6OUCI}S8-Q-5=9DCkC$4>T?Q* zhX_v~$tydIl~0uqw=p~*_!U>C{w4gecGDUtQbu0SN*9!t7W2AV7}yn9SQ`o~Y%Z%? zh+;L@xdRJ}0}FAPgWuP(D8=si=$M-52k6u&ZEMpmCwW4oD4TmZwYFKCoR=;t(sjmnJlb-`OX>D~o{5&E`9YcsQ_*uT*o4Eep7Zqy)*3r~X0-o{yM70xw# zaJ)yM`W!_17ZRIk!d3og!t>z23P-^7p=0FtA?Gc8UciSAZRwnLH$K+-v5s$a^GWL1 zmW`fnMoFdr(XnHAFKoY^F%7TjM^}C6i}aki-F9{EvUPAZ?I8~w9v*H&`0BIp1;Trd z4-X$e_zXh&f$iXl;bGc2rc*Gwf9Wy&jI9*mO9-nG(lbp2%=Yn(%+^+DyL!^Nf*$0} z1&(uX)(RcO%cd0GF{S8E`^23E?d z(;$lHQ~&+@pA8S!A~f=Iwo*3F?*Kf2e13P2!C#W6_@6}nSsYkxvhc4r_+K7aUG1!6N~THT97^-hn!3i^f2tk- zAq)Jr4BwaGWwIi!l;L$UyhVn0$nYK+(oO(9J7l;=hL6ec>oPnj!xv>JxER|Y=2Mka z%UMgBuWKbz$uGPzviU-rQnc8n$5?Rl6l2tGsclkwrZ!9UPE|_PMr|?=AF4BIPgJ*s z_}KB8f)Dix>L=6|$!u~FwJT~P)A7L%=-3tbP}`e|53UMf_{}2I@WC&>_#Jy|Dl3<2 z^KoO}_1euPOG?VMveHH6rMHwV*5+??*J}<}P~Zy|-+Db*vOc-6P~B^2Cd`HPs-Ic$ zT%&(k@jRm+TJe0Q+OrkEjH!NL#m6z#pR9NRQ~l10kGy}4@^j(cUfKSv^b?JHDy{g) zd)b7X$*il=Oex~Is7-ahqd7MhHC;-RXUda{R-nc`b5<^DS&esA{BoA4(##N#=ThrP z)BkeOV$$`?T(l~6Z9#a}{E zRTGqQqRmGEIeoJgzf$2LD^B+$a{5nO@g)lHmUt=S5B*6Er$21PKdSKGN}L8fJlhq1 zM&oHd5F)lm;qO`TFDv}_5|MCKT`rgIyk^O@5)5+=N z^drZC&vAU@IPhiQH2b8ESO3K6N8Z1Ah~p#22U@$*y_u=^cn)x!bXcEvfooQXr>0x8KfbYy8|B(#zPXeE9Hbln% z%*#7+{m`314y*GA1Hn*3LrER(6uq-@qjTNbO`CBsYw|W$XRrm^6+Ublfui2$Z1nhQ zT^?tB(B}_0U7v3t*85bSAS&v%Br=Mpup>ZQ+G%<$LfuM za5baHB9#ax9+mi^Xq!8 zki3IeTmx*)QWp-3dyU0a!&VC6`jo4I`TfIIx|EBO#eKn65+RCT7|ibgHs5k=z9877 zlHVpQ)0WGP(@Ew=3h`;~R;HVitz7bcWGg7IJ+^|p64GAk%rDg05PGLB9x_R1D`D?vh4tsH8U3?5SUXgBqS{as`@LN&PM_I7NuTh3D*W`vc8B zuO;C`p5N_p5rd4urL2UzswC)cL!94hUE=rg+nP(%^5st2!12@WyT2@Vy%zYb)? zN_rrL+vI9#u7e#uNXJ(RS1H8fE@*}Wxt10Tt!XBOF+lX5Lht`r?(j#wPpfdQ#8rUl z#q!Ym4DL$vDSq|dt-@`R8q*bj)IO6;;$Kz}uSkl&T1He@BpFGs4Ijm?-bX5c5sBhg z`)Mjv`)45G56Lh;4kTzVOYy7seHE^f#L9j}r@|WK)83d$t9=0#YLY+IehIUBL?}=3 ztNjBN4oO0#KehZ`$-hd{seJ|&w#xz&Kkd(?^0xsa61D%R_CHmq_BBDmAF|c_1duTE zt9=U<7N$5{zTWVCC6e>W6n^y{t-`0MftVh}ub>V@%=*>+^eRl(iDDUe`vj+P8KY9C4cdnvurf6DKQU$vuOg4b-n+HX3#L1;{Aen$UMa!#i38~ak#f`6|FjBmxK z!od`NwSTow@(&oCBBG_F&mc{*RQc8WQv2P4aQ-PPgJw;#_mQUZm!{x~e?bZ^-N|_< zi_)s^m`M*v{SMgyX`ZRXN0qxs5>vLaT|zua+$U1URmI6nrC-rbMI;^nF{hwN-N;Mj F{~wL=Fn9m} diff --git a/platform/innovium/one-image.mk b/platform/innovium/one-image.mk index bf857404fb..0019b46a98 100755 --- a/platform/innovium/one-image.mk +++ b/platform/innovium/one-image.mk @@ -7,8 +7,13 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CEL_MIDSTONE_200I_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELTA_ETC032IF_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELTA_EVSA32Q56_PLATFORM_MODULE) -$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CAMEO_ESC601_32Q_PLATFORM_MODULE) $(CAMEO_ESC600_128Q_PLATFORM_MODULE) $(CAMEO_ESQC610_56SQ_PLATFORM_MODULE) $(CAMEO_ESC602_32Q_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CAMEO_ESC601_32Q_PLATFORM_MODULE) $(CAMEO_ESC600_128Q_PLATFORM_MODULE) $(CAMEO_ESQC610_56SQ_PLATFORM_MODULE) $(CAMEO_ESC602_32Q_PLATFORM_MODULE) $(CAMEO_ESCC601_32Q_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(WISTRON_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_INSTALLS += $(INVM_DRV) -$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/innovium/platform-modules-cameo.mk b/platform/innovium/platform-modules-cameo.mk index 8e1ddffd5c..d253925f8e 100755 --- a/platform/innovium/platform-modules-cameo.mk +++ b/platform/innovium/platform-modules-cameo.mk @@ -3,6 +3,7 @@ CAMEO_ESC601_32Q_PLATFORM_MODULE_VERSION = 1.0.0 CAMEO_ESC600_128Q_PLATFORM_MODULE_VERSION = 1.0.0 CAMEO_ESQC610_56SQ_PLATFORM_MODULE_VERSION = 1.0.0 CAMEO_ESC602_32Q_PLATFORM_MODULE_VERSION = 1.0.0 +CAMEO_ESCC601_32Q_PLATFORM_MODULE_VERSION = 1.0.0 export CAMEO_ESC601_32Q_PLATFORM_MODULE_VERSION export CAMEO_ESC600_128Q_PLATFORM_MODULE_VERSION @@ -27,4 +28,9 @@ CAMEO_ESC602_32Q_PLATFORM_MODULE = sonic-platform-cameo-esc602-32q_$(CAMEO_ESC60 $(CAMEO_ESC602_32Q_PLATFORM_MODULE)_PLATFORM = x86_64-cameo_esc602_32q-r0 $(eval $(call add_extra_package,$(CAMEO_ESC601_32Q_PLATFORM_MODULE),$(CAMEO_ESC602_32Q_PLATFORM_MODULE))) +CAMEO_ESCC601_32Q_PLATFORM_MODULE = sonic-platform-cameo-escc601-32q_$(CAMEO_ESCC601_32Q_PLATFORM_MODULE_VERSION)_amd64.deb +$(CAMEO_ESCC601_32Q_PLATFORM_MODULE)_PLATFORM = x86_64-cameo_escc601_32q-r0 +$(eval $(call add_extra_package,$(CAMEO_ESC601_32Q_PLATFORM_MODULE),$(CAMEO_ESCC601_32Q_PLATFORM_MODULE))) + + SONIC_STRETCH_DEBS +=$(CAMEO_ESC601_32Q_PLATFORM_MODULE) diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/cameo_platform_version.sh b/platform/innovium/sonic-platform-modules-cameo/debian/cameo_platform_version.sh new file mode 100755 index 0000000000..33b3163164 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/cameo_platform_version.sh @@ -0,0 +1,14 @@ +#! /bin/sh +# driver version + +PLATFORM=$1 +PLATFORM_PATH=$2 + +export PLATFORM_DRIVER_VER='"0.3.16"' + +echo "PLATFORM_DRIVER_VER = $PLATFORM_DRIVER_VER" + +util_name=$(echo $PLATFORM | cut -d "-" -f 1) + +j2 $PLATFORM_PATH/templates/cameo_${util_name}_util.py.j2 -o $PLATFORM_PATH/utils/cameo_${util_name}_util.py +chmod 775 $PLATFORM_PATH/utils/cameo_${util_name}_util.py diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/changelog b/platform/innovium/sonic-platform-modules-cameo/debian/changelog new file mode 100644 index 0000000000..28a015dcbf --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/changelog @@ -0,0 +1,6 @@ +sonic-cameo-platform-modules (1.0.0) unstable; urgency=low + + * Add support for ESC601 series + + -- developer Mon, 29 Jul 2019 11:00:00 +0800 + diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/compat b/platform/innovium/sonic-platform-modules-cameo/debian/compat new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/control b/platform/innovium/sonic-platform-modules-cameo/debian/control new file mode 100644 index 0000000000..0afdc036d6 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/control @@ -0,0 +1,26 @@ +Source: sonic-cameo-platform-modules +Section: main +Priority: extra +Maintainer: yuchun_hsueh@cameo.com.tw +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-cameo-esc601-32q +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-cameo-esc600-128q +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-cameo-esqc610-56sq +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-cameo-esc602-32q +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-cameo-escc601-32q +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/rules b/platform/innovium/sonic-platform-modules-cameo/debian/rules new file mode 100755 index 0000000000..e1073e0e2b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/rules @@ -0,0 +1,48 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-cameo +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= esc601-32q esc600-128q esqc610-56sq esc602-32q escc601-32q +MODULE_DIR := modules + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + if [ -f "$${mod}/setup.py" ]; then \ + rm -rdf build; \ + $(PYTHON) $${mod}/setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + fi;\ + if [ $${mod} = "esc600-128q" ]; then \ + make -C $(MOD_SRC_DIR)/$${mod}/credo_baldeagle/lib; \ + if [ -f "$${mod}/platform_setup.py" ]; then \ + rm -rdf build; \ + $(PYTHON) $${mod}/platform_setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + fi;\ + fi; \ + debian/cameo_platform_version.sh $${mod} $(MOD_SRC_DIR)/$${mod}; \ + done) + + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.install b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.install new file mode 100644 index 0000000000..f4e7b10327 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.install @@ -0,0 +1,9 @@ +esc600-128q/utils/* usr/local/bin +esc600-128q/service/*.service lib/systemd/system +esc600-128q/scripts/sensors usr/bin +esc600-128q/scripts/slotcheck etc/update-motd.d +esc600-128q/credo_baldeagle/bin/* usr/local/bin +esc600-128q/credo_baldeagle/lib/*.so lib/credo_sdk +esc600-128q/credo_baldeagle/credo_sdk_fw/* lib/credo_sdk +esc600-128q/modules/esc600_128q-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cameo_esc600_128q-r0 +esc600-128q/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cameo_esc600_128q-r0 diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.postinst b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.postinst new file mode 100644 index 0000000000..22d013174c --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc600-128q.postinst @@ -0,0 +1,7 @@ +depmod -a +pip install --upgrade --target=/usr/local/lib/python2.7/dist-packages /usr/share/sonic/device/x86_64-cameo_esc600_128q-r0/esc600_128q-1.0-py2-none-any.whl +systemctl enable esc600-platform-init.service +systemctl start esc600-platform-init.service +systemctl enable phy_module_init.service +systemctl start phy_module_init.service +/usr/local/bin/cameo_esc600_platform.sh \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.install b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.install new file mode 100644 index 0000000000..b2f1e5baac --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.install @@ -0,0 +1,4 @@ +esc601-32q/scripts/* usr/bin +esc601-32q/utils/* usr/local/bin +esc601-32q/service/*.service lib/systemd/system +esc601-32q/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cameo_esc601_32q-r0 \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.postinst b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.postinst new file mode 100644 index 0000000000..f303da1df1 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc601-32q.postinst @@ -0,0 +1,8 @@ +#!/bin/sh + +depmod -a +systemctl enable esc601-platform-init.service +systemctl start esc601-platform-init.service + + +/usr/local/bin/cameo_esc601_platform.sh diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.install b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.install new file mode 100644 index 0000000000..c887ac4492 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.install @@ -0,0 +1,4 @@ +esc602-32q/scripts/* usr/bin +esc602-32q/utils/* usr/local/bin +esc602-32q/service/*.service lib/systemd/system +esc602-32q/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cameo_esc602_32q-r0 \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.postinst b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.postinst new file mode 100644 index 0000000000..4297297b3f --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esc602-32q.postinst @@ -0,0 +1,8 @@ +#!/bin/sh + +depmod -a +systemctl enable esc602-platform-init.service +systemctl start esc602-platform-init.service + + +/usr/local/bin/cameo_esc602_platform.sh \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.install b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.install new file mode 100644 index 0000000000..1dd5c813b2 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.install @@ -0,0 +1,4 @@ +escc601-32q/scripts/* usr/bin +escc601-32q/utils/* usr/local/bin +escc601-32q/service/*.service lib/systemd/system +escc601-32q/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cameo_escc601_32q-r0 \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.postinst b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.postinst new file mode 100644 index 0000000000..e5649efa9f --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-escc601-32q.postinst @@ -0,0 +1,8 @@ +#!/bin/sh + +depmod -a +systemctl enable escc601-platform-init.service +systemctl start escc601-platform-init.service + + +/usr/local/bin/cameo_escc601_platform.sh \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.install b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.install new file mode 100644 index 0000000000..035555664a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.install @@ -0,0 +1,4 @@ +esqc610-56sq/scripts/* usr/bin +esqc610-56sq/utils/* usr/local/bin +esqc610-56sq/service/* lib/systemd/system +esqc610-56sq/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cameo_esqc610_56sq-r0 \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.postinst b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.postinst new file mode 100644 index 0000000000..fb8a753aea --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/debian/sonic-platform-cameo-esqc610-56sq.postinst @@ -0,0 +1,7 @@ +#!/bin/sh + +depmod -a + +systemctl enable esqc610-platform-init.service +systemctl start esqc610-platform-init.service +/usr/local/bin/cameo_esqc610_platform.sh \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto1357.sh b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto1357.sh index bbf8bdc59d..f5c176a844 100755 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto1357.sh +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto1357.sh @@ -1,13 +1,12 @@ -BALDEAGLESDK_100G_EXE="/usr/local/bin/BaldEagleSdk_v2_12_00_20190715_cameo_gearbox.py" -BALDEAGLESDK_400G_EXE="/usr/local/bin/BaldEagleSdk_v2_14_18.py" +BALDEAGLESDK_EXE="/usr/local/bin/BaldEagleSdk_v2_18.py" -EXE1=$BALDEAGLESDK_100G_EXE -EXE3=$BALDEAGLESDK_100G_EXE -EXE5=$BALDEAGLESDK_100G_EXE -EXE7=$BALDEAGLESDK_100G_EXE +EXE1=$BALDEAGLESDK_EXE +EXE3=$BALDEAGLESDK_EXE +EXE5=$BALDEAGLESDK_EXE +EXE7=$BALDEAGLESDK_EXE # credo_auto1357.sh x x x x -# x: type of PHY module, 1 = 100G, 2 = 400G, 0 = don't init +# x: type of PHY module, 1 = init, 0 = don't init if [ $# -ne 4 ]; then echo "invalid parameter" exit 1 @@ -15,25 +14,12 @@ fi for var in $1 $2 $3 $4 do - if [ $var -lt 0 ] || [ $var -gt 2 ]; then + if [ $var -lt 0 ] || [ $var -gt 1 ]; then echo "invalid parameter" exit 1 fi done -if [ $1 -eq 2 ]; then - EXE1=$BALDEAGLESDK_400G_EXE -fi -if [ $2 -eq 2 ]; then - EXE3=$BALDEAGLESDK_400G_EXE -fi -if [ $3 -eq 2 ]; then - EXE5=$BALDEAGLESDK_400G_EXE -fi -if [ $4 -eq 2 ]; then - EXE7=$BALDEAGLESDK_400G_EXE -fi - d1=$(date +"%s") #long action here if [ $1 -ne 0 ]; then diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto2468.sh b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto2468.sh index b0463064ce..1d340e0973 100755 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto2468.sh +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/bin/credo_auto2468.sh @@ -1,13 +1,12 @@ -BALDEAGLESDK_100G_EXE="/usr/local/bin/BaldEagleSdk_v2_12_00_20190715_cameo_gearbox.py" -BALDEAGLESDK_400G_EXE="/usr/local/bin/BaldEagleSdk_v2_14_18.py" +BALDEAGLESDK_EXE="/usr/local/bin/BaldEagleSdk_v2_18.py" -EXE2=$BALDEAGLESDK_100G_EXE -EXE4=$BALDEAGLESDK_100G_EXE -EXE6=$BALDEAGLESDK_100G_EXE -EXE8=$BALDEAGLESDK_100G_EXE +EXE2=$BALDEAGLESDK_EXE +EXE4=$BALDEAGLESDK_EXE +EXE6=$BALDEAGLESDK_EXE +EXE8=$BALDEAGLESDK_EXE # credo_auto2468.sh x x x x -# x: type of PHY module, 1 = 100G, 2 = 400G, 0 = don't init +# x: type of PHY module, 1 = init, 0 = don't init if [ $# -ne 4 ]; then echo "invalid parameter" exit 1 @@ -15,25 +14,12 @@ fi for var in $1 $2 $3 $4 do - if [ $var -lt 0 ] || [ $var -gt 2 ]; then + if [ $var -lt 0 ] || [ $var -gt 1 ]; then echo "invalid parameter" exit 1 fi done -if [ $1 -eq 2 ]; then - EXE2=$BALDEAGLESDK_400G_EXE -fi -if [ $2 -eq 2 ]; then - EXE4=$BALDEAGLESDK_400G_EXE -fi -if [ $3 -eq 2 ]; then - EXE6=$BALDEAGLESDK_400G_EXE -fi -if [ $4 -eq 2 ]; then - EXE8=$BALDEAGLESDK_400G_EXE -fi - d1=$(date +"%s") #long action here if [ $1 -ne 0 ]; then diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE.fw.2.15.04.bin b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE.fw.2.15.04.bin deleted file mode 100644 index 95dfd609192fa817af6d40498bc0de692daf25c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50324 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 diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.14.18.bin b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.14.18.bin deleted file mode 100644 index f1dffbf5f2d2f17402459181de90fea920ae2b98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47172 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 U%fBrg!(3SRrH!PfM;VuY1B}R|j{pDw diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.15.04.bin b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.15.04.bin deleted file mode 100644 index ac21b40645ccc56c75e5976416cd4c69c569fdb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47624 zcmeFaeSDPFng4(8c@7C=z=#7<85A{D)~0IPXkCqfEv*zOrJA<3Mgo);Yg5Y#T2=xK zk=E#@Zq(QvNR$MJ2VK^+HrmjPpwz7`rQKBXZKK|SM5&@iMMcHT_x(BdJrI!Y?)Ue4 z?LWVllh@?j_j$a|^>nUtorlTgKKguwfsZio5e7cOz(*MP2m>Es;3Eutgn^GR@DT<+ z!oWuu_y`04f5(8id+*1d{n6*Ibc`uCX2Sp>pTMsF_pdRDq)H$6P-epBxc~fbdQMNs z%}%s9rpt+^x*WHq%bAwxa$>bzPR;5rr=h;fX=&(kwlsD**`_XMSGvm?Xw6J9=AX73 zlddvOrfqY{o|OZ!bgeO)m*#R^PO_-I+Qj)%E>YTQ;}Y?7m9yWy>BNXzU24+RCPv!1 z4RcJSBWO(AnD^3IV^YgaQBR;u-w}dI2@lf4VwU`L_t-|WmyYQwn`JcS-vXiD_X^8}vnCcdFNQ283q zQ~mg4+d>m1{wKr_v@Hx~)3r_)>7VoKNfG~g>%u|mEUEz4Ur@TA_K&2!(YnwXAniQT z@^y})zUxVQlX{Nx+j+%rzlQkzUYzqR`L5{+RKDG|&~d4^mpqsFbdsA{GIEx>!C0@*9_(;|W`pT=VW>61fdxaDW@HvC_#Ji%P<9fgtuD<8Fz)v^fr zk>|t+=>^HG^L;rT=E-U7WR(q>Q8x;{kQuQ{@5aPFrVw~XWLk2$zF?`~4I+E+ zLt;c`j?Mc`@mAv;XHq&_E4g&i_d4`r%p~;4qVx)HG9B|6kZgVc^4ve`z z(*$2!e>iVf7%U2Zb9+e6}G z_<5YycEnu+9gxAl*fwbwI77(H{i0F-rWz^^{aE;Io@^H7>$-ItxJN(IXpXv0N>{Bg z;O~0+w-{MkL?4!^KJ-vy=0>kC)cNn3oyK@$SZI-@*<#bRb)~H*sCVJ6VX^tsQE`j& zbwk&);Pp>IxvX6VQrnQpOfw~p{=vbg>*f6zS3c;@2}|Lj zA2ANrWF8W3zP2=vJMi{h@K>IvFEmXe-*OFm} z!G0*(B6!l-6u2u}bjLHMwr!^gwC&90d|4PVw$>5Pw;$&D;cvrlj>q%CUkHywaD1}z zXT+-&t88C@_u$6HyW-N%YD@YV+5~$74S7CBrw`u&{?BfD#tbyQW8OI2)`%yF_vOpP zHaum_ZIhAHQPzIA*5?B|Hr6*<{khCd`8Z6O#M)UVEA;*B{9>LRBSYwKFx##?{i&Zv{1JwbqO=L`7#8?~O z@JI2b^hfwn)g3ZL*2YNJ*4efs&(K~tSOuO>>o`;V8N6C`H~qr&ZCwS<;2(H4BK*NO zMSj1}RG4{CafMm6j+j%;H;R;PXJb z*HnP>6V{-kJp7t6bXGy?YE!{{sw7=~+|3>9P9H%(q!&YU_xLqcz_i#r+P=~R+_?$O z+e!!nnmb`z#51WoyQ0~Ga-JJ{7gYv2&a||$HVC##X6rg@H@+&|VasP2i|=z6CJf_r z#?mK@j#z0Dv=b0-)AlfQ%YE=$u}z<1P9jda6?qRmDZG)_(YxZ&wdXU3GwAJ-?nJ5S z8C~Y{PWb2a5uF|Wxo{4if93P+bCMX&mS`0{Rh-$*GKo ztH8fX9)RI}ubx6{JBWUIR~yK~uMhK6V4Y}@u3BwnMl^u7`_Tz+i^t%-$CTIOtw59J zrLy&~8Kz}A7@HR}PsVq2JaKd9~c#ipBl*KWLm=j+V>;d$Z4TWEigF;?gCOx$T38#Cvo&_$Vr zdOx^(W5th6SD>;9et6pBH#1gsTm5JIbX*Pn%;Rg0XpSD}@$gktD;#;e9{7gJc{Y9F zGLIgXZ$hGjF`8q&s(Ho>q6c^%r8>ZUT6DoqVtyMMY72}4_X}vd*c+DvQ&qp@GGvnf zf=mwhw5#`EDZE*sFTc_mB^qxUf8oq-yvw;9S#kQ>lK4r=CXyD)EVlIJJvp(l+PvUa z53Ek#YxbtMnJw_B)8&+wAwT2j?n=spEUcX$+_|X2?9rW8q zzUkT@*Gi82K3yXnRigPwG#fiR!}z-UY0p+^e^~Qd=UHHKp~-EGjV?HS-0MftnHHyo zxg7d`K=l|C2wNOM58(iuU_+U>C;Ouk$bQJwLZ=y-M zZD&TP^L_bn`d3ncL4VewM<~;pLjO+m=(Tl;7mC)Kf(9JbnDlMtTI_(7n@SpYMbh+y zN*B2+6Gr1%d#ee%sZ#O94!8Zxh;&N-6o0Pg*WYojwQCAm=h6=P8yk1m)(5N}ADOw9 zhD_*pjGIwxD%ofS9pDsw5aBsLmmMZ}$hSlJiI1Y=jGi~{q$9c9y}jF8jN*h_V8!+@ zu1~j53CHBQN&J8v@m!{D;sM5`WxYGkj8G=Q^L)|Bqe0Vk7MApwzWzLqLCEb!V8?w1v@4^!!YZe;jjir0BNtw%*zQlLm#wN;U zjj4Oglx>_X+?JX4KblzkgUmC$dRM#aOGDHh!*Ae^H3tvU-r4zddPXxY5F*D;y3LG~PVG3=oCE*-3E42%EkS5hgq`s_bnZD;?krsm^PL|o0WCr1 zqX+qZK-zMT=H}D=wIKxIp`z@9HAeFJqPXLgw_W2?E>q=^YrKVOXa&z zT^pW(*7Pyj`Tp~aA%A90@E4wYHeQM>V3+ZHcZRVek;QIi%*gD>oJ-v7R2{s_xB)H4 z-Fbz1VfUP`ab}{UU-FAEs9yHkFa8~%J#W%)dGNQXXPWzg53 z@h8!r{(Qk~l-^|i|0J{uxOFv#u_}~G8N+;|Lb~($J*N-)yl^dj58(^^`VgOCm2?zz zAJH+z`mw|5d&~u*JJDZ*p4PvUUT(_u3>_Q9*VI#vJT$v2lVP{j%IXD&-cyNyJ1>cD zb-vZU%Fd}G(zW6pWX1PAI#oxcd2;;sf<^L`TH(Z{lfijcS71yW`t_*~p8q-00{##C zpF7`wR`TWfpCfmZHno1SGl#HH_4Kz|y-}RmL_ZgsUSE&o=e*H1%*}}3)4$2))4b87 zH|3c7iC-qfht}m*B?A4x1&!l^hjMQJwO%<-*Bk0H4)MGD=lS(z#S2zHP~RtQImXut z>27E-cL*)YWQ*WeEb(=Zm3{he^*1H@fG$ZuL2l{!45e{_R|jxCJ(Dm5n_)U|G#K)S`p*LP*UK7JU z*ecy&{j9*!7fcGLmL}>8X(MEZf;VLEgEniIf}4w^`%=H9Occ_F1K<(ZE|eq(mZYHTSW86Teq2UzRo^XxNK~7hB3}ZRSw@n zA^biAI)6HyEk`EF>*>}4zx{AD8+|a-dI+9Zs3MkbS-cpXTSVF>WNrjs%VYHW73w-k z?Humo$KIun8O956R<@KcEjyzKYq5pS@Y->Lt!>d9WlPf8Xf9pV5U{jbj6LSBHPD|^ zWT&TV8<@`$X61v<`_Y`MDH~o}G1TvNcSXp2?9ceUuk_o%&-UJHvO(Jxj=J1>Y{ zxr*nZ_U9DQ3Hg}p-j>C;l?`mZ4WD<)H23ag9Q0`Tx#!TvV1MeEa>+|ASqWA7uz;K=QyEo$}3_|Z^ zJ){G9Kldqy{u4QUs@!QC<0Xl_**eJ%@at+xFdzxhTJZT`A(I?gvS`Z>|s zRte)UzHCsP@cezhOqh$+e{{t~!c%vk=7tTAGnU>1UBY%;>l7}4#UcMMHAf-*6>u5% zI?7Ek7g68S-GPSdiSODt1vqLMOXeml9HhDG8+`C3zs+X_(-8P4vp&$S@yXYp1=#EI zg&t|^oT4$>*`vDfzxc8(o_()UYh~7tJjdM7+A3X|xJj^62foqLrP0p8GoS_f%iuq$ ztR=4Y(0sVIA%riVxWo$42Khf*YdDlGz$bbx@?~`j?Z`*`3i_)A*?Ua3jO?IBaMico z=EvqmcUI?e@UPm6$bUhDnf5KU(rSm!HS^l-&YXG}IWK${~s?EFKm)oajzzPu|~q(?j% zPV51<)~>+@dPC*G&nMJZc&^0etzF&(4PH^ZwEvhF#?H5C*naTFgduaH3xGW#S*N}M z=?3aMQT1uepdP!PK|TMfdTd{6rDqDiE?wcRhdE!bIxo zgO*Rm`S{()I>)%R75JyF#Rhs%Yr?q!bWRjmwfYns52(#(=ev(SI?F5{(*F69cWJ#}_t88ogkzkZ@{N~qX ze#YEpj`?%{6zf|UEg08Vnqq?EG>220t?SGE{O>OD`RY=YKV1K?w^cuQFAz?ksKjd#!5FMKhFtwz%$zR(UaY1hH^vN z9ZS1G#f3~{alXIc?={smgeEgAO+4P*r}n{v!&tB=ot3>?icI0lxAlzvs`L{dZ(g6Z zb+@W6U#E<;eOruw`>?HL*C*(wH;1k=%$ZFIdTXRNXO7&XGQfDd>S4Ya@9n7xLThyF z+mCx`!zz@9P5m2iT?M}6Gl^3VbM6Q>p4QJI|D?RiqjdEAuSGNBm#SUIl^hwYxmiRhR5YT2vbMUEBD@&;OA`l%8tvue~E1aT^-E5f6-d#1}z>| zee4UvM>Gu^Cx(3&57nZH7oQB1uL7AXST(`K824uP z1e3FYKML&gGOMhQzEEkY3D_YQo6uAl2|&Te?PRgh}SfiyN8LsT&%w7UGdl*arKk<&)WDE=-jHNE5MJ&F5%}x zI0ruiqAR#568!jRW7^kO&mJJgEcs1`Y3|9~Zg%F_bHdq5XZ?33-!JoJ?^XgIMdItS z!MXy8X;JJ^V4OjiCcLb11%8^Urr!criQu|pn+Y^dHlh2`nY}yX!E^;S=C$$F@}J8# z1%_~Dg*RWKZx3j{UV1WVC!08O|2F+965ZDzgW{)EkC~Xy1KQU(04~;e{Zl`^KHj?B zM46xT$?vN#dDimowq6>|HNJxnb56P1WqhOW&zL~}y=A6#Q&jrh&dD*H1AK z+3%j-8uJkH{2zJ-{ubchvI#l&-|x9EQ2{TE*`)QG4xWK4y74LURsqeR*uORnM>mqQ${8;{6@cicbr+F7H)|IKQVA{ooeVO#@liqs^eQu%8_mzg2 zKj-lCs$75n!+w5nqCHr`1-zxS=cEs*>jcrR{y{T}HK&p8x>B=sGHZO)p?11Qm5$l~ zjhJudq{q-L(ex#(-Ctscksec7`Vk=%519TH7&GkAQaU&vm)A4mi@J+VQQdMAuVYQ{ zX2&FaK1sqSd(k;TXaLT|C!&LBAbx2m+L&TZ{u1GtHJa_>l~-O64h zQ=Q(dHBiP5PtH@wIq#WNItl+5`aJ!K_Wj8GLneCvPE*kOqH)+y5_P|gUaRKYmSDbD z6L8x~P4D)a5PKy8kL+ZQOaHWAf_Yq}+gd8QyPWS8;9+<@xaD~UFgkjcKH&W_J!>w~ z9VovXe$?DWd-0|#oxA~+@yia)dxi4ae6&fPnQEK&+2FL~SUB}@nE;pje4XdxFOSa# z`LF*!>%Nc)T?YOf^hbbk9KHW;2t88CdxUrPlDw;N@`_ux(f1aUwX*$$XcnstnZ(;` zXV728GtPN>GV!|7q&xF@$+z!N+~IsLdU5Di=?m&4-|j6xiSxQ~E9jec1&Y~Z@`kZL)gAddWdLWLxkC%ON z$93kc-kU08jn|no)-25B8gDm~+6dih)tzKca9}QTpb)+Wtqp~G7bd3l&aJe2uQdly z9a?+C2Q)M9ACO<$--mEe>DWDc)ees%fCt(|pAj9YGsb$rJJg%-WI0m~KVF{#PlTtb z>?U+8WzPj44ltfg+vpJH{@0l@!7DfgFL0iJG@KUa^j+`@pY(sL=5rn8RzIGz^(NaV zlVJ|LKA*V2c$^VU?Mud9Eb z>$tR-J+5XFykqB0;tTPK$7dh>NIb$=e;j!tgrku0-(!oY-e@~}(TI;(nI@igbFz=4 zo$q{LVL>*917P`%>VuBr;Slfh{CDX-XpWbB#9*i*{bGpUX>TgIMqZ@$=+-@M#ha5HN~ zzRXWU=J#v-kqt&aqsTFO?H%?b#!UMhGuhgUw^&+VkZJqbX05@mf*<_7HIY`v&1mP_ z!{Lblu#Nx*)&)6pG3UgHZ1v3K%_Y-JCF4Qd`dfkdEv?H@MtpQkyIlAHt^?RMF<|>7YmA z0gb=dlK!4HQve@%{zmu&U3(hiZ-VsarK>m0v39Su507DU?eldJ?P`pY-8IdQS<<1I z8MJ>pc4&&WL$+`W&`SijQD#4ZkWOf^N=05kEEesBG4$OkaW?m(XfGSxq`dnhD_Q%%B% z_ZcfIWoLo25VVzz#QyfgOyUjeip=|R2NgdSyu+`tjkA8a3p+pLR@V%*y`#z_8SEa# zK2h3ZuKzo5+@-lX_M2?*H`mT`_DgpvZ^#6`LOlT=KXJj5p9|3T<-Yynuk|?-DH9<6 z3dIX1lQS#uEl$K(99Z>ulK_qB8i9HJkP?Fr!UDj(iMXB||I)`X)F_2t)ntglw})6NfX z-G+XlZT6E6((n6S{3ygPQ9AHNJlLIp;3MwK>LX*(An&#uaD18kS1Uhl^{OtO^KD)D z-_YhP@|*exbMIj*JNTzYh(`F&t`_e{JNN%MovqNG_!G4Ug!GsnzY>|gpZKvy#s4Gm zn}{ECRQzJ%HxQpVD*gw=-$(ojN5wBBzRlXi@D2QOai)4r68ub6`$PEVx8fW6f0g8k zPrLA9>FUw^A>nNZ?_B2DT(YS~uaNx&pIz?rxRuTPJ2kow|A1x0ka={K>Y&cg+J1TEzTv}oIn8}l{7IQ{k}F_H2nOJ~%EDD> z<+Dd|lBXeXd^s;a$Zwa@k7{?a-|olME}zc|r}STPdKuw8gfsL!gucT>-#qOpGZq{b zDqqMPul;Fuo(ha-Qn%{*7o`byyPs?>d&eHIYv`w_?GMv`aCx5o)G=0hs2{d5qeWx- zeDaV!H`_iRmP>mUjW++P{KtGDkl zDcK|PBQS3+w)psUxsmZ`c=@0{@~X-AiE0weoL@}k0b4> z3ArA86cKEOahYEBD_%lBOzwT?MqlID5H$(PCn*~jZ(y^plds69&9~DJnv>eEGeO3I zVB=$Em^+7sndRX9YR3F~OU)hkm=XAD_w@uTU#;J5KGhR0GrK1@Xl>Z^1Q)!~J*xcR zh6wz!9=i&BuDJ&~f3M7>z=c022}ytO3FEu9>++WO>yfP;tpA?o*$TZe)?6;}(vdmq zClf7I790-Wy82)Rp&h45AG)VMvUToYjqtqnmRy=}SjXp$_EyZ0f5e?%YKH6uD%d*J zX;3=(N<{V7W~90G5MHU7Eek9I`C z2W!Rs_+@x6RGW(9+4`vR?Wga{s=w$mr1R;z{<>& zq~;iZNFmcH{3)s%-kYYniT_XH^*)ufBDIs(UHLlex3f0}zU_b~#JBVlS&W&~cJ|N{ z$GggfSYscBz8Y#r+p%rcd=uAPL_DH=s^70W=Jorq&m6yJA#*>~>D!I=T!1sAtrFq8 z@e0~naYS3if}OVPyhn23`!@&FuH;Ytq)hc&3mQptr^Z7)LG;Bj`m4U8(?%k1!_{AK zBR|TqU?-oWbL!y3=0i7sIG=pT3HV#}W~xs{ewDZ6?PKMoT}N|2`Q$QfZ!MtA!AA6k z^2(+W?qt`nj$+qSq?>HL|KQPvdcSeZdhykHz8>bBQ#D?gXMlq_kmrYvcE0|y%E3!t z^7OXO2fY45+f(rNSsrg|k7s_opq(AqdIv$RJ?GK72^$-^qh6JB(F<|;U^K4F_X1DO zl-$ei&)28CL+X2w`u0&@B=uF~m%6BDXDe&6dPhHCr{#8Fi^ZYY-}I%WeokI+mU_b2 z`CW$bK{)FQm&MV`p{{T;zh)pAIUw4I9_qVbr47q3$KcZgDR3;U7#dNaJAy_O6=k#q&|De}T&%$GRF;qkrXHP8F)+kx#Z4_^1zWtPT0kz`4xwpR3C z-4iJtZDsLh6Bq48bK-+4-xcMKg%)%wb839Z%q2a#O8!ODOzN!#nm=nViF7M{ETV6H zf}Q!b{OytUYfV9>HVgbUZ0H((KKro_kjGoYU5NYybtc&i*ZQBYvxo6Kh+pg5vhVTJ zkC#r$>!Zz+bGb+6n5)3ue=!e_hY}USq2~V+83!AR+)IvQtUEj(2ZlB~o&_x5g=J$A zXZ=$C^ET=C|B4U5%Wv_6PShSX+Cb*EAe+<5=)Z8q{J#eNXki@9Ch?V);H_kBGRa-MbIy-l}3xARRg@Xw$vhqARihcu3r&l!NTlVqibX;iRsuT{P z8~iYMm(B0>Jp!)21Fq~jVCH#`s6Ia55Uw~6WNj4r)%lvO9Y>DyyBiZhWb}#kjV1@a zl=nz{ffM2iz?ZEDTszVmvJYh!(%!?Wn>rp6-q;7T-1iecEPN6F@6Cq!;az4=Um&Uc z+kE&YN*CAPZ1&*)3iQuOs-1Cu+E}IWK329kxO0U&-Xp>tb?sJNypK|T>d3#_`7!mG z{(F<+o6W)#Flr96I<@t<6V! zQRL3sw|Kkd*{Se-h2qdvG3$qW%-T3bb=Wz~dlGeznQ{0*lQ&;%CgKMz#Sc2k*Ma9E zr>TxpC8IT!$l?NIbO|y#6B(V2++GQ-tB~Ef$nrJFX$^9^2suT5%i}t01Uv=O73?KM z9?g^Z=x<3^nhTIEeZDTe2w!+QIBU)(-R`6IY-J~vc6V7B7GKbhN$N9lSgf-)*w97n z?TK;TMsu9i=-H6;9_w=WL@o-MKB2!7)GEPWrqS)Bdzst-XNgicsqg zQ>=2*#X28D*@VvQaIPyRe~Qv5JC=Ce|6#z9-LK{@wRIksuSfYfM-w35aPkfK6{XHL+)MqT|=I~)tR!U3VktI za^_Un!m;yrPd7TU(@i7wp&Ol^M8f>bU52s1jkRwB-`Jsk-~6*pul*s9r)cMEPtcdM z-8pe1ymO|l++D@lolT|@+oee7c;uhuxsfwxT2By8US_Ui)&duBJDFMZ1KxF8lbYKk z*G{00?=h$Nw^GwoO~2bnt1b;dhj{xsa~1aiNv|#MpW+G+A$NW#BC#7aAIWl)988d;qAwJ^9!QCp6%T!JTu>)s=WujFINh`W_M$Y z>HXJABcH>bik3ic%Ywkh)5u>(AJLEQ`UPh9+@x_IEj1fL(8SFR?wM1u`o13l?`JI> zW8H5zseeW8l7wh-Av6d)Qq8!tQ0KEM13oQ+;LO?ZBWsJ;Jp=Tiuz$*G^~I(Mr*=QV znI11nS8iC%oca{neGweRX!CTtFVA(`T88528F$ALd1+=3anJ7#48VE3`$Vbb z!`?c0)be7L>HTSy<;A<}DN|h)aCelNM^?g%PnN~%t|kuu#HyRoFYx8=AF>~X_b#VN zcA?Rn9Gx13?)~&pJesHbv&|KDZH#?KyEIRW!ViMM&eKv$Mawt-AUM0mRT}np2eBoz zM!3H@Z9?mxX3%Jae%EgiZ=1H2dS*Z2Uf|(u&W4O&Z3$>!zk74SY~X}ME53Kz?`=y~ zqX!*-zBsaXUWNKv;&#*Lt4$KS_X6Poe3iR@KrYUyG%3cV-ldgB`@nY3Pa5~}vOv$s zCeu?`rarP)s>RUHi1-{B_o}Tm_nV;mVwFLDidtW^`&FNV#?p<9dH4d+q4=^^`(v#3 zk}z%$X5EU00O7CP$>kx&vL%dVGqL4nuX@Z>GLBuzI9A0tHkWa10pr*;@Mg`;kC{dO zIJT5N{y*B{AJ}=shi&m63}>(56~ZBK{zP!<9Npix#ougHpZ@o3@q^nwY>OX!(E2#8 z6E1WA6I*;g#&v-S6@o;kisYooCho2L8@}{vFR}_|H3eKHY!*JBfmh8AFl*1+PdofT*i9Ni;IkLMfh z9#Iz2I(%2Kp(w+C3(beS@x+BpylKcf>A;$ux@#j|E*#Ld-RD8ugKArJ_2}o(PCO#| z`upHMg)I>k5882bh5EFAwmUg)8Xq*Db}xyq_G|^`nbv!;X|e{|zw!ijm;7yi(@#K~ z*c;xwzhNDE@Kk$V<3Y`J)2+GhvZu`6Es=gacRTAJJ2kfRnc%L(rudvq3#T6+d|3N8 z`7}3h_XzP(bZM0M&6Js>GRn{AuBMb(M7rh=l>6WszuZqLH;#CysQAHye*7)JDZ_-aqa#e@aqwRb&` z_e%19g80kGTcpr$-4vNAf(KIEAV=!MB*_O9-_mXu4nibCf@g z_|wUoP)Pa-q)+wJFJ%4vdg4zd{S?AN(of?%f#;Knvmx&%Qsy&$nNK#XH20ByQb)*H z<%Q-{((OGj^yTACE1e~Tr#G%N?AkG>0t2I@IfXuAb(jgfPa+)8`&on^1BS(fCladM z7{VI}Payq#!sB`0KzLlkN@p42NaEpWQ_MS_0yCWY#t{}0CJ74&PbQ2KP9zKyilKsp zDNnv%8-~nA6~|b{`g2bEPmlJo?uFN}O?34z zBimE*nXawXnfcV*!+Q?aY%@>N<|Oo5oaZe(f1Kx{jTOzZzgMT`SpCi(m3=qx9%{eE zG)RX;J70ZHwjz7XoK|cJ-v5j(9mupa$NJ8;Ixv5p;dtpx)*tK0^M_1TbEs*BS;6y8 zp2Iw+2+_;0{)YB%r2PW&Yo8$d&tH84U++fZLaKxGy@bKFJolX)*PLXSdwT*e=@-mNU7-Zcvj?flIQ`f{ z;MCe!n(uUl%9Ms3TNdD)*>2?}-+26!7ROtsSQ(UGCakp7JbV^I@~{^$ zqP=eES*B!7mVIwu&s@;d2rTdc{RuTQj%>!}YR0B#Uwf)GW$){O<}bf0Uy%H~ocUMY z;i`8l=b2Pa;|HHm-JfYMm8qzE+~R(7X04)4uxnIhiP8iQv|O)wM#nhog9;|9YFQ6S z*u4d+n>Iq46J!7VS$qb)N`)Kw;jrC4v=12DZ5*~+65DN}Z@Wzbe*?%8doMlwiTA;$ zYzXW3U-Og+wqDDU*Qt`oVMW_Sn4e68*Ej)eY5$ z`{?&Wd*B&I^E{BZhZvXX&uvr8r&_OL?jQ7Mr}0#{PXEIEgzt*Rc`Q@~O3ND=H`)99 zY2f{WwUs+xeuaA)qOza$E?Tlqq92hK z9;Pns0o?1?d$eA}A1-{g#ASDFTuC42T3AGX=5d}qBLA4yU?oS;WU1EQqq%n%t1rR} zIEm`sGMynpw-hO!&oE?WuGio9CeuIWr@2Aq-tXuxQPTeo*b>yYfHb==pXYh$+KN#R zXJ@hogr9;tXLR2TZS@L%dpA(--6w@Rzh2>Oly~2e8E)_3pl$HDg!nS%1Uh$_6@217 z>aqAozwJ|fL-_G4y59reh58Z!zCl}m=NmswH^P@KmL>_w)dqCYv1H5V!Ew-K3phm= z)l9+;F9TQQ`1LM87geB(rh(V#;1QkFaxVU!sa6LG_fMc-!1IP*6UH#8D)0|2b}IXS zX770URr?atyeE+e^9?}X62a&1RT!DsMBeM58@e@_ZI;ZT*({K-O z@5U5@hrg-~FW(!N$^&3l1;zAl5 zq2KYWH4LO5GPQz@eE0uBd+OEj+eIEf1% z?Q<9(t7{es2G$!w(luIlNZrGjcxqOB`;|@b)kby)_1`|A_el}h8&TG?Wn7UlZH z3ti(9_MRj7=VAFpQp>3iKOpb-cR5MZf2YM?RC};fqDi%>V=tWiMejZH>iC0x`zQGD z{mjx7zV+h;&mBs;1K!;8^-Afm>Ah9Ew2nD(&!xLU$Y1FrH?q!#AHD8kQ-*Ki+`7lu zW9+cU_+nGR_%@aCZJIBWGwDyht!2k(>qfN&Y`>H3gZ$1V5Brg8mdLld0lCE2W6%2_ zuMNm=6Y^Vwj4wjI(S@e^-TmJIhQ#j+s zP700J@ampaHFP`KjAINxz}Ro?26*fELprLuxgt%UDLWgvECs$$+U36V&Q~vL&WexY zvGkRuXl>ejoaZ8*OE!JW#)l|J%Vr1hap^ny`6^@YF5x=UmZ@aSekQdF+vHNq&%a&e zFs3l8k&ZjjaOQEct;f=axY(vdW;$hlBijVunB?RM>0R{?AFAeYkqz6>kyo3drYYRF zwGF$7z1qCPi~BlKOIX9$M!&j}Q8GWR?)B?FL%MT`mPR^b|6PVjBQ7AhhC)!ikD zh~%HUJp#ynR&rmroqo_C`dgc!4dE6%-I8cwfdrgt9NQ4fTuJ&8^#lIIck$QntM4v+ z{>wtM9Nm=Q9EJ9_H0STI-cy(jb5>#;cBFKV@+5tGX4&SOutyVi&9Vr5g_`DKR829> zU9l}D177jlh9CW-Nny(ryAPwM&?Wd0D)G@yB>%+CYfWfRq9Wk7uvdYxCjDn~n%kBP z?FnYX?K@0R;|_fcZq|Cb3!L2bfG)c#UF}SApD8nar)LGzcf|u8C)xh)gtm!CpGH62 zW5&@&(eBF|#23lkvr5B0+y&3?z3V;f#ZWzZ#BGD`t~Mo}u7CS;-Q!Bb=^I&lx3n-} z_Jm8<6uC3vriWR&_)%k<m2rH7-01I zc<<%)SDNr)zJB?j6^aI zG{(KNL3{fYSI~YZ^VHi+=+>YK>KtzW+zRpS7H0Jf2kK;<>$BOc9oxc zKCgH_6Lg2~X2ykHlMJ}4liX2Y`L@_US3N>?s_r)Y9euH+%7)+*)@Up3JOP}Bx&jrd z>pa<~J`9e9q1D1RNp0a%2=?L$>d)9Z#?V$+ZR;K>?1981A;ZNirn$SM!t{nJ!lVao zjWEtr2W_69HjjowdL$2rbX#``Iq^#fj-&cBO!qR9S|C{9FMGB}b%OH{WrlTyXqU9s z)%25R^;7lp3F?kZ?X!S3Wvo?jCVE#$cZ)-_vz3QAyT;W|tj)rowaap>QIuqubE0R0 z@a>#*tqDR)`JqCsoVi+4Wnv0hlY*BjN3kww?_-x-u~&<`QTP5zceAILa+h@H+Y^DY zgl48t&dKX<;^K#Opm$${d>@DPuSw?hY{NtFimz+if5!7&NqB@iwNuU~J-utVgAYC5 zgiPEdJeC6Y%jcs@tb=eo!~X#(isT*7}Z` zQWH!KytfGZVhL?6#lEPmd(5P6cFgLVFJ`O3a?^10W2Vu!FVffy`*k;fbc}QYHUfKl z?x}R2h=*ObEWqBT(AN2uM}}z*<>`%kD$sXfH(MIeTKHDRU|>x8J}A-iV|rFz*|gj{ zuthSdzD+eryO$7L;Xkwc>Wc}#%sc)wGmEg0_pcHb5Y8ry64G<|&y0i<|C#wZU&f%9 z&X>;!`peEb)|$h9^+#~4e?#s?;4F#qDX=a89`)4r3)-p<(L&C4@8uAYs2#2Q~f7gkGd%Y!`;#)v2Qy@z>bdSjhAbXJ4- zkc9(Y01lo1KR{bY&)N5@k3(sKJs7ON1o>)J-}l=2gX-~oEyL2(Gxb<7w?A%HwD#cx z!T;0FTJUDpCq-lFIND%OXH86d=+g6>{@|v{V{Th{%$q;SH}u!%g*)!8k7$0AsJcCX zJrK@RS5*i;&FKVJ*N9SUI|5gW;2Q$h^}y8wT-Ki>U5~uQd>YA@vtKkgf==|Y9^72MbK|GdbIdfxn#*q!OW}cY_A4c65lQH+jijdYmI%cg@hD&Ri8C)f~>JmLGnuYAP$I;(%Z{Y3@%|5{cLIUn_o@u2>)jK=xkTL&lJ^^iH6MhpP*K=Q_&9iuTVDrjt@t~lz7J%jTZ_#zm$7iA z#zSCC!KagxtJyc%&^ia-=^QhqdqgGj`g*;}0gsgf;tut5h%7t_T+m`ml0M)!iWLE4 z3G+{UbS?O}vlE$nmNGw`#Qd{N_~+gavvxaYDy!Lh7_?)H`k*zhKhoB@&9%nd9AG0Y zXR@#{;N@!>}DLBmCxQ&Z;JPU^*yDN|2zxNkvRXRaDL}<6WHD8T0g7yp3ufS zo2W;7vGEbICw%|KUBO-P)>l$5p}D?YB$cEAo9u_q^}VyG8+|U;}QQ6|}Gc*MRDY<_3NZu4nkZ z$(rI4zDkDyh4eeV)tBxVpz! zTVXzpomh&UI0-wk%$MVG=_%+?zUqsF%5vA@O;Y90DS zzT%S+gbCWW`)q0Nc*fMZ#1}E2JCQI>dNt{J`)oLNSPl7PgH9)84cE*kwDwxG^99*f z;s^E~;Y+9`q4UMNeS7V1jnR8Oo!kOW#W5Lj~IZ@e1@`J&%y3okdf>?Ec+aerSsE7F_&T{UKaPo*DY$ z1DeYFx7ou|%=5H*_T#p0!jE%%jbSXwwf1vIdMFX)+?llw z(uddCwPvI->0#^!|E&M?-Lvdj{|NU_&Xg?C=D)AMopUtcM>J^Hyr;UkOXK;_wfFp4 z*{w576uxWq`RQIloqxtJo?E1`OTJgq*Q)M(8ED)@K6LOKbCuWkms{PD&qI0;eKVaq zq0Z`?ZE>No=IHZ#H~aFjO7jxd*zBG#9#;rYoX;)u&qm)gw0-i`X`OccVz=*-*^Q62>7@=Rq3?#J;6!%bsyg8YLl^6NgeT!m zu*ko9=L-0o^WygRJ)TAu7ad^(db0R1ve-s^8}(5OFh$j-*WPR6rDLf(rZLi!#ppt0 zF%!+bHc@$o*o}Xc4T7&^xnQHrMEEozzMxL#(w1hL!}0rr3DzuMe=$#U`fz{8gXT%{ z>5Q)<{2qnRkwfrl_sp}WV!qZndIHJ$!mp2uw=~Z138^08L!scv&pS1*VSG4rAD2HK zXsvL+Y(wb>-F>INYJ6b6!e0CqJ5J~v18_eD+&aJK-~aSNEqdW=y!-byZGh&ia&dw!z!pX6$D_I*mQ(b{A?VZnJFGid-!%>IFEN`yN-1?y8 z)BgTU=S%O}bp&8TkBowko}}Gkcq6}#U#Q;+wK}%5??mzhymiQzUiS3v>n|vjY=JKe z>xSwN&DGHD(Vrz+pO(Lj-&dLM=^CA7ipj2jTX&V=<6__5o&%o${iX9VR}(kK zj70D1?(E=CZ!_Pyn>hDcc>jU8Y3enBri)GJZpTFUjkWJK>@*A6D<4Q-V~Tsi<@G(` z_-!5Q?0zcFJXbV8=Z`~Q?kB6nU}-uacLH->L$ZX&>4bJw%pW_q0RfNby{ry`QBppE6giNrR66YS(8 z)-|-(hW4IiTnaEQ>2BV)m468DSzkE37l-#shVY!-L#lB{dmb~@_Z`@<^DS^G`g-#{ z&KNAySXDm*eG>5W525sP9RAt?4(u77Ox2bPqn-U5!TE5WKcn%K_w~TeTy@K5cwPt1 zQNgBIdm?#%nD}yj|0S=dw0CO<@mq*LPhXzz-*^S{zfoVCtukJ^J@YUY9{HR5BH+^l zz)v4y#^28BI(u-`qrcd&+n~=i0Bx1WtAaK`|YCX*1@hda|cU% z7gnMdE0w;aDP^uF{RFS<;KOS|xw76^h0-Wnp|VO-*`{<~?hN-uXuYyr>EF>l#UW*H zWH04JcSo7#DDS!}`Hil_^kD!24-{GgqO0>d=oZzNteV~Bm1uM$UngWvG;YOm%j-ajWj7I@O0Ozl0?{<%@4=ly;s5tp|+1H_9VPScplCy8yS za$|^>oo)Tf#E&Ij`!QvYYQH5mtFw(f5%QeimmNtSmo)5CXFKus?pn$gHmx*2A(Y*@ zn~=SOW+|b3pS6VYefE)uxp?3E@K=8Cpd(&^$By=?;1lrtV9e9)9Src9bPjvct!xD4 zqlM?;@4i9R$36Rl+>~AgV7Qx{H4gF;_hO(rp( zC-Ff|M5mVe`m{`Xhx2LH#?Mr6Rt)Y37ORKw)p4IhvWPvl7q&jm`O}mckzOw!9P3hT zCc!!U7-5s-j(uAfZsqrURhG5Q0Cxbt&K~y*^EQOvp6(0SCtaPlk)@~cSMSr9DE%v5 zZQCY4?zA`}`Z3F=XL9j~xApjCtsmPf8#+jQ;)t@)n|xLW_+{gn>efEuM$xY4C!{Z^gja}9 z9;2+)0VpMK^Ax*g`bxepKHNLW zXYV8eXWnn5clN%kq72Y&e*`0VXFs=i0Tq3iSC2k=}~w6pgws*kgMwSGLm zCDqGsC0|<$d=t?($G8_blwr*78PcCt-m~`ZyUE;rXK}K*M0TTe3O0Wqy!&5`n?3Lo z{99x1Qpuk)pkH0^P*OG*K1SwrTgGi%CE4%22cBY$aggVI-^8Y}`y`d0w4doNNBdhy zo%=2)Z7RP{2TxXp?tI1>1-^#ed4*HLo{Sjlk^H7!QaHRsc;ZZ(=rd z!izT_8GNj6g(+{k*OatBfextS{B>(tfPK)T-G^C2dt%Gs{UEKp&o5;kSZ|SA{m*uP zhWziW4}x>|2dNa#_yg?kJQ9!I{T;vaSeYWu`sq9SMrlur*4%;5>Xo|Le*Wv^W5~=! zZx<-Pzm9$=k7swf2c`cq%l-Ot`+tF7E##-YWz((|Z7MIM&*!DcM?2QfAiMzMbHWLq zPqD|h-0%PLL;Xh&+J3JC2lDY<&v!fh#~+O@kq?&svrn+o{p~UO|H)(Y|5p06;Bf!< z{PDl(|25$3KZf+*_DwkQ``D51qj%@xE3GN|-xX*mhZl7R%n`OJK9fWpXQX`{r@LUf z<)ifYG7Aq*W6X;&AJUx#hxu_6dc>3CkD3{tSFp<^V(Y z(BdEW^qln(4~0W@lP7F{Bi(OPan$vUV9vv)cGV{Fe^47dBV+Dkg29u&m;ceqAMbwJ zqle}1k-v)ODlMCFhKl+;L##JOpot)bF)f_E7A!zWNXJ`w{** z=r}x6ptI1lJD2vY?)7ER?hB>tm20Y?li=-im(gea?vTc-BmFbzbK)XyRZD<}z<0sy3ECSCH3YY3P`>FMPBz~o6F{~J`3>3K8Lu@T2=F`b4bGf z2-(-Nm7rr(c9Cpm-be5r@6tqY~tO=`@f$M1BPSyFb*(ZO4DA5d6I0V0@*pT zvt)C%at=ebmh3D(721;r3^DReVLqWy=fzItt9elwaS8>e_8o|yKJL$1{+@RMY{w|- zx`;O9Pdy*sx8^xIzoqvx3FV9YY+i3O$Cym~$EfF2Le+gb-{CxKe}r}uDJ-Il{mm@u zF2!Fyj`$MlKAlj0^-@C3rQ~0q=+}J``AWz?4p=mI(OgOUC=$dEBOFawNLWJX5RM`} zKo}>aH{2t((o_%@5l$r>M!wO6F~Z};8+<~#C(80(^=6fW$9tKhADS!SXZY}3N&Dj@ zW4gCVb0yivj72fs-vkY?iM{!`y|bxSb-GDx6rC|Tdd`LI(K61SN1#p0l|o$o5LKh{BQ(8cO??T_`}wGJAYMha_$QOya_8P+GNyNG>% z=z?a$-CbAH_DcMpDdZB0P*+tW>wL^v#D~%PdrX);W#T8zqeKvNiA@hFUH(l!T{=^J z`6W}YKK6^5)Pv7c-jrc2xa~KOn^TO6WtQ(N`82J?E;F~RO-IHT&F3E2& z+B*)d|GOtp9_S8~74p05`i=64{HlD%(SDot-*!GfraRE0`zNO9o%s8rozIh}@`NFA z8;C0=PQN3W&$o#<>Z}|yB<_CV!o=x!B>jB)t+eNXtMWwRW-zA2IOn0?--!F;Z2@Vc zxi2l|pNR>JE~3daQ)chhX}lBsFR6)%Cv~6B5P$N|(vzM2&_cYq-vsvt#ak!B8XKS9eBws@|CSAu-qQR% z()M>v8!kV@r{{?`>#yfdF5qDtD-wUw<~*&f!JF93@aEyU$H!<_Yqa)$WWtEv;R*O4 z0Uspn@1_X{MM?0VUcisbv zv(Fyx{=0Lb2U=HJe8~=wj${9g)-|7NQC)OpJoxAQ!*k8N<3E-k_@zss3;rf|67P}r zTTDH&UF@%E6>XkthPy4yZRYWtjOc0VjHzywr=D9WD_yDIW3p{R|Cfa`(pD-D^14^; zKy#F!{VgW>Qx532QL%X**7(Fa0yO^c9fsuFuQ820*2ZD4mUJ<;G;6z6oascSu(#Q# zxuHjQ&Qs6tQq`8nK5V~Kn+o#Af}PL50Znvn%YS!uSKy&{J(K5;vW4<_yg1k1C4-Gq z(VjA~6W!YlJ_OlToMkGrwpQaFeq$vN|5h;U-ZJRcsv{Z~KS{_}6yxCyykDd@l_)D?oMavIU^^dX z&87}l7J8{@6*h->8a(y+2~+-Jhg}OWG@Qu<5H&V ze@Q0FB(r||ANSiI8ds(`1E1A0T-x1H&mxyv(l6oFc4DUIs2M3t}jW8d) zAmjY~@wLUZ=1p72UzSyzWXzwJ2A2lR|A}e{csY77deCe!(8|{K0p()O!3ZUtw+77x z{C8CU{-wc50q0GXao!zg#u?}BTpVMP1lKaS!Z^7c&)k@1erQ4i(Jcxfxxommn*o;FGHl;QlE#WnQh6-KEWSovl;u5C z>>8KT(-)bGoM#YVZm=)|{JoOP{T3)47w~rHawAW1_V7RH^znbB(>pMbjXQ2IYbq>m zRMIH7leINgsr>5IX4LrX_^is0c2wSRRG$As%9{z}fy!|66`&30f5433zhj04bIun{ z;j(3zR3o1s&+wL0F8(VQGb{V7Tsytq`tXx?dx2^lZ|OEzliO+LIt>VOfWM1HA^WV< z0#j@vDm~2RRXdP7-)9~=Ln_=5Ms1;Jq-j*lG(4-1~;$B#T*Pvrf` zG2_GUM+$=_AFe0#UZf~E=EL#9ccVpz>K_7U;6QA6@a)6+^LTLHC>S36-1t~=j2Q3l zY|MXS6#sQU{;TS-ut9vlay+!)6J4^b>>^7E#}sE3GpbhqPpB1@6E%9CApY{H{B+Lz z)>v8-FW!Npro%fP|5bS@&Se9n`0>31rbP#%2%Ik#*T(SjjTb0bi>B6@X8(VI{{g44 zxp{dL_3_4k-d6wEDWYn&yw=hLd5qHdPueZ@A4;PxuQWNRooCuZFVNlyBbWv}m})&< zb!L>C@_dXZYrvZIU^Q_6GBch&=>HIisP#)8G|tsRrxVBx==9`8IqKp+ZFdas-8Hf62&YkG6h14;h3h^!D+vAwe%;nqVnDbCf`EU7^ zjwwIDdldi#;NlpAbJA3R&m&(=&?yR(g|e~#+uYT~Mo~rKb7qF!pdXfT$xlma9Euq2Hk(V!(HE?R>jmDKp+i@GQ#JZvJw z7{Hp)CtH1}OQ@0flkq!eX15EaK`|O{bMM@H?z#7#pSkCrGqc^Tck*t`%BM{;7OSt% z=i_EER>VCLkH?E_8ZoQh&R60(>>6pyv)M6RD-E5oVOW-JJC5t7(;n8z)-d%hWqRUC zrY&giC@^&lLRp%a4rraJHN&)cYYASuG95X}b_2*ihVe&^8umb`-d_RluYh|TSqPlm zY2bTi1c6Ub@8QV2aLpq<7XBYW5^y@%fWsBkx0~kcfV~Zk9BF5(3~x2b8*2PW6I`*{ZFuE;MQ4`G?T_G%f-{ljFmAXcAmWc zY%FU;0V9RkfTab-voV5Xgjod`2~4DfgAcaTV3{RWpbWH(u~G|q6JR~)Z77fx^h%9( z)%rE9+*|7>*3u*Im&j;zhs%_@wYg5vb$U4Z3Q1}!61F;|JM@}H1tz3k zR1|?SogXEvXEU34bz$xiR#IGr(&aYK~Ct^fT}#!U-dg&p2?{! z2s5Qq9`KNx+wdZElr%}ZGB*L*j4apB!+gp^B~0c1bN~>XCJ$rsz{gdR!osV-WWHuM zfTOBO)|7dh(g7`kBQR-~QfZ#1(J7i>_wGWz8@Ud-5qSkNb$7Ypg?I* z@kne57#CY|4b3@Wcn0cpCZI!dwCyUsx)XBU3LQMFG7R8Pw^hQg@jWU%mcXADZ$#x$ zdHPTDIsTGABAy8Rh!ufPBb0J*_WzyONsS~;kDx{<4eo9fJBi0Vj0_E4|Bz`cI72TT&&b5W}tp-JDtyC+en1!DG#p3tSJ9g9_o|_k%7@CGBEat z3{V#t>=qfM_KFNrdqf7QK9NCccS(1Ml7(;4+D&wa2pPJApZ!14-9O`dz4DDO%D$fO zi0HecEz~8nKBRolnSpOS0r>CqJy)Ji^!+1!LnBcAFIO+CYbcUXFcBXB&!$(Eksd?N<}e`{W4 zPo8mfcXJSrq6xU^`x_cKqVcBf7q@yrL>c;ukH_KRa7!FkjGqD_9=Cf)yvtr`H!>uM z8Swj$C?Q9b`^WHHh`W5h?rZM${quXd$M<*p>KdqnfHha?x+A{#oCh1PHofwM5D0Er zvAYr-hy@h}q;6@QwGW^hC8pQ1Oa~|N1`EEy!6BymE->|Z_(n(g5r^84vk%HZdJHB8e9;Q9;$tC~O7LZ6)kYk!Rat~H{ zlTUJiuNaGs4MxHAuwIa6Qx(WPgii)ov_QX`wA51rifh>6rSO-|?Bm*5!olseHj`zo z1?Km3nD+DJoFQr<=}Us|Dx6nQWaq>Qtgu4$H5cO#Q}w;0;JA*?aNSS&xDDG&xLP$3 wj$RM9LzR+n^{I#2#U$JFl!pepBRU`-Q2>Pmw`E{_KGuS+9^Obs+|rEZpERc%0{{R3 diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.18.43.bin b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/credo_sdk_fw/BE2.fw.2.18.43.bin new file mode 100644 index 0000000000000000000000000000000000000000..72285922019a993bb3b12eebb44e1247b885c43a GIT binary patch literal 54308 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 BJDZ;&-U!HdAY9sO`YND6cQgdU_LiUyN%mIXi(& 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 z z-SyU;LWY?ngLAplY9)<(oK#zT5RfXVvF@QYA>8yd+vcZRJCaqZlEp;f%d*O8?C=Ok zL~ZU@=d~%Z?PaBug0kH!EgU=My`u^mniKaY&X+T=C(7_JyndoIpo^w9RdyoQSNca| zT{(A9NQ^rak9yKk0|0K%x{WOfpp#ujZoR?Cqhr}U*Jh*}clSd^rVKOk(=?_T^PG{H zc}y#2I%YeDHk?WLnIB@d#&>nA>BaP6Hew2x68zONcL}C<(wsRDvj7udIx*$`CHJZ? z!5`we+sHLHVTgN82WFd*ze;1g!JcD$BoN=1Ig$xKVhp4{*dXFKF7PVg zL@Z)z8y|fxioKLgl$$9)r(*Q}Vr(>C=^F6QM-UA&B_K|L@Z9yXu=uVp#Wyt@!ExG4 z(^R}u@=;zijKcJ}bd~T-DIU+0kp*2w7B*u7OplSG=uCAwNnm1OKCryPOeHZyW4KkoL}A*}2=??1$0(N6 z7HM%DjjJxaR1Wo34$UHgDl5~uFe4VyC~hRvt!%omEa>r2{)nPBl&_)24CP}^SWqEB z$AFvZr+>fN$lvApy8JMn>B|d-*-=&~31YqWRS{=|lZA&>kXY7h@$ycH^cG0qclv=F zG7--*iHP97<|T$}RLbBsiPCPjbf>nY3XW^XValOyBki*=ZJ0g`Jg9vh20qdrV7f8A z7l_QGXX>U2Q5aHf`2J#p?H&J^+uN8Y~&tz*FDc+ z7O^^_hIH<2GqRHSEBd*EW93*`*bvsuFt;^?nJYQ*M9Xv_@B%a(*8Q=zh@}_8rCT&y zy5)p$LIco5rEt=t;iSiglQMi|;i9>)jErW)N*Qy>|6J($Cd#Po7EtDYEE;)XHf9p0 z4jNH;XYw#wz`8ZX0T@tqD@%1gxR@4qvVd)n9&7oK|8@=%seAY4vWm3 z>6(<&hQh-527Q z!d5Z4O`EKf_X6LfovfGl1ESf>$X(F(@jQH;u*SeiJl{{Jv)Oz;2ukT|dU5X4l9yl0 zCc?^^qek+9kr~j~4@Md3Ow+dxVzQb5{wt#UH6H#))m?s#2uFoySB?qKJO6@OBZcjm z`^KZAC=}E^;=YGV?hTpF0r-Z-&H;E==I%zqys(<^U5%ApC3j~g0Xi<=owbSPk~_#a zQ=w}MzqxVQkI;BLx0f(CWV`|Rj7C3#Yq(6>Y7W#XBhnAsyIR0CZR79mmAc|GXg=Fdm%|NWPo#3M$9}{|2y2x$8xB%BFy4HS5Crc)Ws_Uo{W2R& z$cK8#Zhis;`n0Wqi*cZ8G(<>(j(~zIp34*IjQ&J-QkSnW43fXJ2^nurtP=^^J+S#fxR4 zRMD&R=DTJAsXS<&GF!|6=Pc*j&K5V&0^6%nP&=7b3^$$(msd+*?seq2&ZNy4#)?S4ty~2ACT(vi@t32WB%s>BT)n8#-H?-mkS~81K(XKFnea@Bd-4T9;-lHSLq@+3x;R mVJgNX*}X&!j&t{idt`WZC0IUR`6I1oaa!S!wdY#H<9`DhK=y?I literal 0 HcmV?d00001 diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/Makefile b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/Makefile new file mode 100644 index 0000000000..82250a265d --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/Makefile @@ -0,0 +1,11 @@ + +ifndef CC + CC=gcc +endif + +all: + $(CC) cameo_mdio.c -fPIC -w -shared -o libcameo_mdio.so +clean: + rm libcameo_mdio.so + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.c new file mode 100644 index 0000000000..05cfac59af --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.c @@ -0,0 +1,404 @@ +#include +#include +#include +#include +#include +#include +#include +#include "cameo_mdio.h" +/*****************/ + +/*#define DEBUG*/ +#ifdef DEBUG +#define DEBUG_PRINT(fmt, ...) printf("[DEBUG] %s, %s(), line:%d, msg:" fmt, __FILE__, __func__, __LINE__, ##__VA_ARGS__) + +#else +#define DEBUG_PRINT(fmt, ...) +#endif + + + +#define SUCCESS 1 +#define FAIL 0 +#define READ_BACK_CHECK +#define READ_BACK_CHECK_MS 1 +#define MDIO_0 0x0 +#define MDIO_1 0x10 +#define MDIO_2 0x20 +#define MDIO_3 0x30 +#define PCI_DEV_MEM_SIZE 0x5000 +#define OP_WRITE 0x400 +#define OP_READ 0xC00 +#define OP_ADDR 0x0 +/* +#define ST_OP_PRTAD_DEVAD_REG 0x30 +#define PHY_DATA_REG 0x32 +#define GO_AND_DONE_REG 0x34 +*/ +#define ST_OP_PRTAD_DEVAD_REG 0x0 +#define PHY_DATA_REG 0x2 +#define GO_AND_DONE_REG 0x4 +/*tested 90ms is good!*/ +#define MDIO_0_1 0x0 +#define MDIO_1_1 0x10 +#define MDIO_2_1 0x20 +#define MDIO_3_1 0x30 + +#define MDIO_0_3 0x4 +#define MDIO_1_3 0x14 +#define MDIO_2_3 0x24 +#define MDIO_3_3 0x33 + +size_t BarSize; +int Board_fd = -1; +uint32_t *gP0Mmap; +int gTest = 0; +uint32_t gMdio_Reg_1 = MDIO_1 + ST_OP_PRTAD_DEVAD_REG; +uint32_t gMdio_Reg_2 = MDIO_1 + PHY_DATA_REG; +uint32_t gMdio_Reg_3 = MDIO_1 + GO_AND_DONE_REG; + +uint8_t port_addr[2] = {0,0}; + +uint8_t total_port_addr[16] = {0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, //card 1 3 5 7 + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17}; //card 2 4 6 8 + +void cameo_switch_phy_id(uint32_t id,uint32_t card) +{ + uint32_t index = (id-1)*2; + if (card % 2 == 0) + { + index = index + 8; + } + + switch (card) { + case 1: + case 2: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_0 ; + break; + case 3: + case 4: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_1 ; + break; + case 5: + case 6: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_2 ; + break; + case 7: + case 8: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_3 ; + break; + default: printf("unknown"); break; + } + gMdio_Reg_1 = gMdio_Reg_1 + ST_OP_PRTAD_DEVAD_REG; + gMdio_Reg_2 = gMdio_Reg_2 + PHY_DATA_REG; + gMdio_Reg_3 = gMdio_Reg_3 + GO_AND_DONE_REG; + DEBUG_PRINT("Using MDIO Reg 1: 0x%08x MDIO Reg 2: 0x%08x\n",gMdio_Reg_1,gMdio_Reg_3); + port_addr[0] = total_port_addr[index]; + port_addr[1] = total_port_addr[index+1]; + DEBUG_PRINT("\n-------+------------\n"); + DEBUG_PRINT(" Die 0 | 0x%08x \n",port_addr[0]); + DEBUG_PRINT(" Die 1 | 0x%08x \n",port_addr[1]); + DEBUG_PRINT("-------+------------\n"); + DEBUG_PRINT("gMdio_Reg_1 0x%02x gMdio_Reg_3 0x%02x \n",gMdio_Reg_1,gMdio_Reg_3); +} +void cm_sw_phy_card(uint32_t id,uint32_t card) +{ + uint32_t index = (id-1)*2; + if (card % 2 == 0) + { + index = index + 8; + } + + switch (card) { + case 1: + case 2: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_0 ; + break; + case 3: + case 4: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_1 ; + break; + case 5: + case 6: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_2 ; + break; + case 7: + case 8: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_3 ; + break; + default: printf("unknown"); break; + } + gMdio_Reg_1 = gMdio_Reg_1 + ST_OP_PRTAD_DEVAD_REG; + gMdio_Reg_2 = gMdio_Reg_2 + PHY_DATA_REG; + gMdio_Reg_3 = gMdio_Reg_3 + GO_AND_DONE_REG; + DEBUG_PRINT("Using MDIO Reg 1: 0x%08x MDIO Reg 2: 0x%08x\n",gMdio_Reg_1,gMdio_Reg_3); + port_addr[0] = total_port_addr[index]; + port_addr[1] = total_port_addr[index+1]; + DEBUG_PRINT("\n-------+------------\n"); + DEBUG_PRINT(" Die 0 | 0x%08x \n",port_addr[0]); + DEBUG_PRINT(" Die 1 | 0x%08x \n",port_addr[1]); + DEBUG_PRINT("-------+------------\n"); + DEBUG_PRINT("gMdio_Reg_1 0x%02x gMdio_Reg_3 0x%02x \n",gMdio_Reg_1,gMdio_Reg_3); +} + +void mdio_write(int phyad, int devad, int offset_in_mmd, int data) +{ + DEBUG_PRINT("mdio_write phyad %x devad %x mmd %x data %x \n",phyad,devad,offset_in_mmd,data); + + int output=0; + output = port_addr[phyad]; + int addr = 0; + int action = 0; + output = (offset_in_mmd << 16) | OP_ADDR | (output << 5) | devad; + + DEBUG_PRINT("mdio_write 1 output 0x%x \n",output); + + + addr = gMdio_Reg_1; + *(gP0Mmap + addr/4) = output; + + output = 0x1; + addr = gMdio_Reg_3; + *(gP0Mmap + addr/4) = output; + +#ifdef READ_BACK_CHECK + int i=0; + while(i<100) + { + i++; + addr = gMdio_Reg_3; + action = 0; + action = *(gP0Mmap + addr/4); + usleep(READ_BACK_CHECK_MS); + if ((action & 0x1) == 0x1) + { + break; + } + } +#endif + output = 0; + output = port_addr[phyad]; + output = (data << 16) | OP_WRITE | (output << 5) | devad; + + DEBUG_PRINT("mdio_write 2 output 0x%x \n",output); + + addr = gMdio_Reg_1; + *(gP0Mmap + addr/4) = output; + + + output = 0x1; + addr = gMdio_Reg_3; + + *(gP0Mmap + addr/4) = output; + +#ifdef READ_BACK_CHECK + i=0; + while(i<100) + { + i++; + addr = gMdio_Reg_3; + action = 0; + action = *(gP0Mmap + addr/4); + usleep(READ_BACK_CHECK_MS); + if ((action & 0x1)== 0x1) + { + break; + } + } +#endif +} + +unsigned short mdio_read(int phyad, int devad, int offset_in_mmd) +{ + DEBUG_PRINT("mdio_read phyad %x devad %x mmd %x \n",phyad,devad,offset_in_mmd); + + int addr = 0; + int output= 0; + int read_result = 0,action = 0; + unsigned short data = 0; + output = port_addr[phyad]; + output = (offset_in_mmd << 16) | OP_ADDR | (output << 5) | devad; + + DEBUG_PRINT("mdio_read 1 output 0x%x \n",output); + + + addr = gMdio_Reg_1; + *(gP0Mmap + addr/4) = output; + + + output = 0x1; + addr = gMdio_Reg_3; + *(gP0Mmap + addr/4) = output; + +#ifdef READ_BACK_CHECK + int i=0; + while(i<100) + { + i++; + addr = gMdio_Reg_3; + action = 0; + action = *(gP0Mmap + addr/4); + usleep(READ_BACK_CHECK_MS); + if ((action & 0x1) == 0x1) + { + break; + } + } +#endif + + output = 0; + output = port_addr[phyad]; + output = OP_READ|(output << 5)|devad; + + addr = gMdio_Reg_1; + *(gP0Mmap + addr/4) = output; + + + output = 0x2; + addr = gMdio_Reg_3; + *(gP0Mmap + addr/4) = output; + + DEBUG_PRINT("mdio_read 2 output 0x%x \n",output); +#ifdef READ_BACK_CHECK + i=0; + while(i<100) + { + i++; + addr = gMdio_Reg_3; + action = 0; + action = *(gP0Mmap + addr/4); + usleep(READ_BACK_CHECK_MS); + if ((action & 0x2) == 0x2) + { + break; + } + } +#endif + + addr = gMdio_Reg_1; + read_result = 0; + read_result = *(gP0Mmap + addr/4); + data = (read_result>>16); + + DEBUG_PRINT("mdio_read 3 output 0x%08x data 0x%08x \n",output,read_result); + + + return data; +} +bool slot_addr_check(unsigned short card,unsigned short slot_addr) +{ + switch (card) { + case 1: + case 3: + case 5: + case 7: + if (slot_addr==0x18 || slot_addr==0x1A || slot_addr==0x1C || slot_addr==0x1E) + { + return true; + } + break; + case 2: + case 4: + case 6: + case 8: + if (slot_addr==0x10 || slot_addr==0x12 || slot_addr==0x14 || slot_addr==0x16) + { + return true; + } + break; + default: printf("unknown"); return true; + } + + return false; + +} +unsigned short mdio_read_slot(unsigned short card,unsigned short prtad, unsigned short devad, unsigned int reg) +{ + if (!slot_addr_check(card,prtad)){ + printf("Error! mdio_read_slot(card,prtad,devad,reg)\n"); + return 0; + } + switch (card) { + case 1: + case 2: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_0 ; + break; + case 3: + case 4: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_1 ; + break; + case 5: + case 6: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_2 ; + break; + case 7: + case 8: + gMdio_Reg_1=gMdio_Reg_2=gMdio_Reg_3=MDIO_3 ; + break; + default: printf("unknown"); break; + } + gMdio_Reg_1 = gMdio_Reg_1 + ST_OP_PRTAD_DEVAD_REG; + gMdio_Reg_2 = gMdio_Reg_2 + PHY_DATA_REG; + gMdio_Reg_3 = gMdio_Reg_3 + GO_AND_DONE_REG; + port_addr[0] = prtad; + port_addr[1] = prtad+1; + return mdio_read(0, devad, reg); +} + + +int lscpcie_open() +{ + int fd; + char filename[256]; + BarSize = PCI_DEV_MEM_SIZE; // default for our demo BAR1 + + sprintf(filename, "/dev/ECP3_Basic_1"); + + /* Open the kernel mem object to gain access + */ + /*fd = open(region, O_RDWR, 0666); */ + fd = open(filename, O_RDWR | O_SYNC); + if (fd == -1) + { + perror("ERROR open(): "); + return FAIL; + } + + + + gP0Mmap = mmap(0, /* choose any user address */ + BarSize, /* This big */ + PROT_READ | PROT_WRITE, /* access control */ + MAP_SHARED, /* access control */ + fd, /* the object */ + 0); /* the offset from beginning */ + if (gP0Mmap == MAP_FAILED) + { + perror("mmap: "); + return FAIL; + } + + Board_fd = fd; + DEBUG_PRINT("lscpcie_open Seccess.\n"); + return SUCCESS; +} + + +uint32_t lscpcie_close() +{ + int sysErr; + + /* Release the shared memory. It won't go away but we're done with it */ + sysErr = munmap(gP0Mmap, BarSize); + if (sysErr == -1) + { + perror("munmap: "); + return FAIL; + } + + close(Board_fd); + + return SUCCESS; +} + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.h new file mode 100644 index 0000000000..ade94b14cb --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/cameo_mdio.h @@ -0,0 +1,12 @@ + + +#ifndef __CAMEOMDIO_H__ +#define __CAMEOMDIO_H__ + +void ForDelay(); +void mdio_write(int phyad, int devad, int offset_in_mmd, int data); +unsigned short mdio_read(int phyad, int devad, int offset_in_mmd); +int lscpcie_open(); +uint32_t lscpcie_close(); + +#endif /* __CAMEOMDIO_H__ */ diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/libcameo_mdio.so b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/lib/libcameo_mdio.so deleted file mode 100755 index 1ce1cf53b5ad21db43b6ae8f75a774cfdffd8f42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17312 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 MiMLo#Q@j5E04T@nwg3PC diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_12_00_20190715_cameo_gearbox.pyc b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_12_00_20190715_cameo_gearbox.pyc deleted file mode 100644 index a2dedaf4410a50da19cccd4f1dbcce08190fae41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 502922 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%0D$72c`o_}8kdfxKJ> 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�?KjpPzdI(T7A7&3#^m5vbwlUjYzy|Rt&u> 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 diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_18.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_18.py new file mode 100755 index 0000000000..b42d4644e3 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/BaldEagleSdk_v2_18.py @@ -0,0 +1,14231 @@ +#################################################################################################### +# 2020-09-07, Credo BALD EAGLE SDK Software scripts +# +# CREDO Semiconductors Inc. Confidential +# +#################################################################################################### +# These sets of scripts are for use with Bald Eagle, with the Binary FW +#2 +# To be able to run the functions inside this file, execute this file at the python prompt: +# +# >>> execfile("CredoSdk.py") +# +# +#################################################################################################### +from __future__ import division +import re, sys, os, time, datetime, struct +from sys import * +#import numpy as np +import math +import ctypes +sys.path.insert(0,os.getcwd()) +cameolibpath=os.getenv('CAMEOLIB') +fw_path=os.getenv('CREDO_100G_PATH') +#libcameo = ctypes.CDLL("libcameo_mdio.so") +ctypes.cdll.LoadLibrary(cameolibpath) +libcameo = ctypes.CDLL(cameolibpath) + +#import /usr/lib/python2.7/site-packages/DosComponent/BabbageLib/baldeagle_phoenix_reg as phoenix +#import /usr/lib/python2.7/site-packages/DosComponent/BabbageLib/baldeagle_eagle_reg as eagle + +import baldeagle_phoenix_reg as Pam4Reg +import baldeagle_eagle_reg as NrzReg +try: + reload(NrzReg) + reload(Pam4Reg) +except NameError: + pass + +##########################[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ] +lane_name_list = [ 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] +#lane_rx_input_mode_list = [ 'dc', 'dc', 'dc', +try: + lane_rx_input_mode_list +except NameError: + lane_rx_input_mode_list = ['dc']*16 +try: + lane_mode_list +except NameError: + lane_mode_list = ['pam4'] *16 +try: + chan_est_list +except NameError: + chan_est_list = [1.010,63,62] *16 + + +lane_offset = { 'A0': 0x7000,'A1': 0x7200,'A2': 0x7400,'A3': 0x7600, + 'A4': 0x7800,'A5': 0x7a00,'A6': 0x7c00,'A7': 0x7e00, + 'B0': 0x8000,'B1': 0x8200,'B2': 0x8400,'B3': 0x8600, + 'B4': 0x8800,'B5': 0x8a00,'B6': 0x8c00,'B7': 0x8e00,} + +gPrbsPrevCount = { 'A0': 0,'A1': 0,'A2': 0,'A3': 0, + 'A4': 0,'A5': 0,'A6': 0,'A7': 0, + 'B0': 0,'B1': 0,'B2': 0,'B3': 0, + 'B4': 0,'B5': 0,'B6': 0,'B7': 0,} + + +MDIO_CONNECTED = 0 +MDIO_DISCONNECTED = 1 +MDIO_LOST_CONNECTION = 2 +gCard = None +gChipName = 'Baldeagle' +gSetupFileName = 'Baldeagle_RegSetup.txt' +gUsbPort = 0 # eval board USB port0 or port 1, Can run 2 Credo boards in 2 python shells on the same PC +gSlice = 0 # Slice 0 or 1 +gRefClkFreq = 195.3125 # 156.25 +gNrzLanes = [8,9,10,11,12,13,14,15] #[0,1,2,3,4,5,6,7] +gPam4Lanes = [0,1,2,3,4,5,6,7] #[8,9,10,11,12,13,14,15] +gPrbsEn = True +gPam4_En = 1 +gLane = list(range(16)) #[0,1,2,3,4,5,6,7] #or 'ALL' +gDebugPrint = 1 +gNrzTxSourceIsCredo = 1 # 0: means do not touch NRZ lane's TX taps, as it's driving another NRZ lane's RX +gPam4TxSourceIsCredo = 1 # 0: means do not touch PAM4 lane's TX taps, as it's driving another NRZ lane's RX +gFecThresh = 15 +gSltVer = 0.0 +gDualSliceMode = False +c = Pam4Reg +# RxPolarityMap +# TxPolarityMap +# RxGrayCodeMap +# TxGrayCodeMap +# RxPrecoderMap +# TxPrecoderMap +# RxMsbLsbMap; +# TxMsbLsbMap +# gLanePartnerMap +gFwFileName = fw_path + '/BE2.fw.2.18.43.bin'; +gFwFileNameLastLoaded = None +gFecStatusPrevTimeStamp = [] +gFecStatusCurrTimeStamp = [] +gMode_sel = True #MDIO:True, I2C:False +gSlice_grop = [] + +for i in range(32): + gFecStatusPrevTimeStamp.append(time.time()); + gFecStatusCurrTimeStamp.append(time.time()); + +#gFecStatusPrevTimeStamp[0] = time.time() # Slice 0 +#gFecStatusPrevTimeStamp[1] = time.time() # Slice 1 +#gFecStatusCurrTimeStamp[0] = time.time() # Slice 0 +#gFecStatusCurrTimeStamp[1] = time.time() # Slice 1 + + +gPrbsResetTime=time.time() +gDebugTuning = False +try: + gDebugTuning +except NameError: + gDebugTuning = False +try: + gPrint +except NameError: + gPrint = True +try: + gLane +except NameError: + gLane = [0] + + +########################## +# Define Globals here once +########################## SMK Board's TX Source for each lane's RX is its own TX (assuming loop-back) +#gLanePartnerMap; +gLanePartnerMap=[[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7], [0,8],[0,9],[0,10],[0,11],[0,12],[0,13],[0,14],[0,15]], # Slice 0, TX Source for each lane's RX + [[1,0],[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7], [1,8],[1,9],[1,10],[1,11],[1,12],[1,13],[1,14],[1,15]], # Slice 1, TX Source for each lane's RX + [[2,0],[2,1],[2,2],[2,3],[2,4],[2,5],[2,6],[2,7], [2,8],[2,9],[2,10],[2,11],[2,12],[2,13],[2,14],[2,15]], # Slice 2, TX Source for each lane's RX + [[3,0],[3,1],[3,2],[3,3],[3,4],[3,5],[3,6],[3,7], [3,8],[3,9],[3,10],[3,11],[3,12],[3,13],[3,14],[3,15]], # Slice 3, TX Source for each lane's RX + [[4,0],[4,1],[4,2],[4,3],[4,4],[4,5],[4,6],[4,7], [4,8],[4,9],[4,10],[4,11],[4,12],[4,13],[4,14],[4,15]], # Slice 4, TX Source for each lane's RX + [[5,0],[5,1],[5,2],[5,3],[5,4],[5,5],[5,6],[5,7], [5,8],[5,9],[5,10],[5,11],[5,12],[5,13],[5,14],[5,15]], # Slice 5, TX Source for each lane's RX + [[6,0],[6,1],[6,2],[6,3],[6,4],[6,5],[6,6],[6,7], [6,8],[6,9],[6,10],[6,11],[6,12],[6,13],[6,14],[6,15]], # Slice 6, TX Source for each lane's RX + [[7,0],[7,1],[7,2],[7,3],[7,4],[7,5],[7,6],[7,7], [7,8],[7,9],[7,10],[7,11],[7,12],[7,13],[7,14],[7,15]], # Slice 7, TX Source for each lane's RX + [[8,0],[8,1],[8,2],[8,3],[8,4],[8,5],[8,6],[8,7], [8,8],[8,9],[8,10],[8,11],[8,12],[8,13],[8,14],[8,15]], # Slice 8, TX Source for each lane's RX + [[9,0],[9,1],[9,2],[9,3],[9,4],[9,5],[9,6],[9,7], [9,8],[9,9],[9,10],[9,11],[9,12],[9,13],[9,14],[9,15]], # Slice 9, TX Source for each lane's RX + + [[10,0],[10,1],[10,2],[10,3],[10,4],[10,5],[10,6],[10,7], [10,8],[10,9],[10,10],[10,11],[10,12],[10,13],[10,14],[10,15]], # Slice 10, TX Source for each lane's RX + [[11,0],[11,1],[11,2],[11,3],[11,4],[11,5],[11,6],[11,7], [11,8],[11,9],[11,10],[11,11],[11,12],[11,13],[11,14],[11,15]], # Slice 11, TX Source for each lane's RX + [[12,0],[12,1],[12,2],[12,3],[12,4],[12,5],[12,6],[12,7], [12,8],[12,9],[12,10],[12,11],[12,12],[12,13],[12,14],[12,15]], # Slice 12, TX Source for each lane's RX + [[13,0],[13,1],[13,2],[13,3],[13,4],[13,5],[13,6],[13,7], [13,8],[13,9],[13,10],[13,11],[13,12],[13,13],[13,14],[13,15]], # Slice 13, TX Source for each lane's RX + [[14,0],[14,1],[14,2],[14,3],[14,4],[14,5],[14,6],[14,7], [14,8],[14,9],[14,10],[14,11],[14,12],[14,13],[14,14],[14,15]], # Slice 14, TX Source for each lane's RX + [[15,0],[15,1],[15,2],[15,3],[15,4],[15,5],[15,6],[15,7], [15,8],[15,9],[15,10],[15,11],[15,12],[15,13],[15,14],[15,15]], # Slice 15, TX Source for each lane's RX + [[16,0],[16,1],[16,2],[16,3],[16,4],[16,5],[16,6],[16,7], [16,8],[16,9],[16,10],[16,11],[16,12],[16,13],[16,14],[16,15]], # Slice 16, TX Source for each lane's RX + [[17,0],[17,1],[17,2],[17,3],[17,4],[17,5],[17,6],[17,7], [17,8],[17,9],[17,10],[17,11],[17,12],[17,13],[17,14],[17,15]], # Slice 17, TX Source for each lane's RX + [[18,0],[18,1],[18,2],[18,3],[18,4],[18,5],[18,6],[18,7], [18,8],[18,9],[18,10],[18,11],[18,12],[18,13],[18,14],[18,15]], # Slice 18, TX Source for each lane's RX + [[19,0],[19,1],[19,2],[19,3],[19,4],[19,5],[19,6],[19,7], [19,8],[19,9],[19,10],[19,11],[19,12],[19,13],[19,14],[19,15]], # Slice 19, TX Source for each lane's RX + + [[20,0],[20,1],[20,2],[20,3],[20,4],[20,5],[20,6],[20,7], [20,8],[20,9],[20,10],[20,11],[20,12],[20,13],[20,14],[20,15]], # Slice 20, TX Source for each lane's RX + [[21,0],[21,1],[21,2],[21,3],[21,4],[21,5],[21,6],[21,7], [21,8],[21,9],[21,10],[21,11],[21,12],[21,13],[21,14],[21,15]], # Slice 21, TX Source for each lane's RX + [[22,0],[22,1],[22,2],[22,3],[22,4],[22,5],[22,6],[22,7], [22,8],[22,9],[22,10],[22,11],[22,12],[22,13],[22,14],[22,15]], # Slice 22, TX Source for each lane's RX + [[23,0],[23,1],[23,2],[23,3],[23,4],[23,5],[23,6],[23,7], [23,8],[23,9],[23,10],[23,11],[23,12],[23,13],[23,14],[23,15]], # Slice 23, TX Source for each lane's RX + [[24,0],[24,1],[24,2],[24,3],[24,4],[24,5],[24,6],[24,7], [24,8],[24,9],[24,10],[24,11],[24,12],[24,13],[24,14],[24,15]], # Slice 24, TX Source for each lane's RX + [[25,0],[25,1],[25,2],[25,3],[25,4],[25,5],[25,6],[25,7], [25,8],[25,9],[25,10],[25,11],[25,12],[25,13],[25,14],[25,15]], # Slice 25, TX Source for each lane's RX + [[26,0],[26,1],[26,2],[26,3],[26,4],[26,5],[26,6],[26,7], [26,8],[26,9],[26,10],[26,11],[26,12],[26,13],[26,14],[26,15]], # Slice 26, TX Source for each lane's RX + [[27,0],[27,1],[27,2],[27,3],[27,4],[27,5],[27,6],[27,7], [27,8],[27,9],[27,10],[27,11],[27,12],[27,13],[27,14],[27,15]], # Slice 27, TX Source for each lane's RX + [[28,0],[28,1],[28,2],[28,3],[28,4],[28,5],[28,6],[28,7], [28,8],[28,9],[28,10],[28,11],[28,12],[28,13],[28,14],[28,15]], # Slice 28, TX Source for each lane's RX + [[29,0],[29,1],[29,2],[29,3],[29,4],[29,5],[29,6],[29,7], [29,8],[29,9],[29,10],[29,11],[29,12],[29,13],[29,14],[29,15]], # Slice 29, TX Source for each lane's RX + + [[30,0],[30,1],[30,2],[30,3],[30,4],[30,5],[30,6],[30,7], [30,8],[30,9],[30,10],[30,11],[30,12],[30,13],[30,14],[30,15]], # Slice 30, TX Source for each lane's RX + [[31,0],[31,1],[31,2],[31,3],[31,4],[31,5],[31,6],[31,7], [31,8],[31,9],[31,10],[31,11],[31,12],[31,13],[31,14],[31,15]]] # Slice 31, TX Source for each lane's RX + + +########################## SMK Board's RX and TX Polarities for Slice 0 and 1 +RxPolarityMap = [] +TxPolarityMap = [] +for i in range(32): RxPolarityMap.append([]); + #Slice [A0.............A7, B0,..........B7] +RxPolarityMap[0]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 0 lanes, RX Polarity +RxPolarityMap[1]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 1 lanes, RX Polarity +RxPolarityMap[2]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 2 lanes, RX Polarity +RxPolarityMap[3]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 3 lanes, RX Polarity +RxPolarityMap[4]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 4 lanes, RX Polarity +RxPolarityMap[5]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 5 lanes, RX Polarity +RxPolarityMap[6]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 6 lanes, RX Polarity +RxPolarityMap[7]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 7 lanes, RX Polarity +RxPolarityMap[8]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 8 lanes, RX Polarity +RxPolarityMap[9]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 9 lanes, RX Polarity +RxPolarityMap[10]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 10 lanes, RX Polarity +RxPolarityMap[11]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 11 lanes, RX Polarity +RxPolarityMap[12]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 12 lanes, RX Polarity +RxPolarityMap[13]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 13 lanes, RX Polarity +RxPolarityMap[14]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 14 lanes, RX Polarity +RxPolarityMap[15]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 15 lanes, RX Polarity +RxPolarityMap[16]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 16 lanes, RX Polarity +RxPolarityMap[17]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 17 lanes, RX Polarity +RxPolarityMap[18]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 18 lanes, RX Polarity +RxPolarityMap[19]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 19 lanes, RX Polarity +RxPolarityMap[20]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 20 lanes, RX Polarity +RxPolarityMap[21]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 21 lanes, RX Polarity +RxPolarityMap[22]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 22 lanes, RX Polarity +RxPolarityMap[23]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 23 lanes, RX Polarity +RxPolarityMap[24]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 24 lanes, RX Polarity +RxPolarityMap[25]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 25 lanes, RX Polarity +RxPolarityMap[26]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 26 lanes, RX Polarity +RxPolarityMap[27]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 27 lanes, RX Polarity +RxPolarityMap[28]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 28 lanes, RX Polarity +RxPolarityMap[29]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 29 lanes, RX Polarity +RxPolarityMap[30]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 30 lanes, RX Polarity +RxPolarityMap[31]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 31 lanes, RX Polarity + +for i in range(32): TxPolarityMap.append([]); + #Slice [A0.............A7, B0,..........B7] +TxPolarityMap[0]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 0 lanes, TX Polarity +TxPolarityMap[1]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 1 lanes, TX Polarity +TxPolarityMap[2]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 2 lanes, TX Polarity +TxPolarityMap[3]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 3 lanes, TX Polarity +TxPolarityMap[4]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 4 lanes, TX Polarity +TxPolarityMap[5]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 5 lanes, TX Polarity +TxPolarityMap[6]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 6 lanes, TX Polarity +TxPolarityMap[7]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 7 lanes, TX Polarity +TxPolarityMap[8]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 8 lanes, TX Polarity +TxPolarityMap[9]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 9 lanes, TX Polarity +TxPolarityMap[10]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 10 lanes, TX Polarity +TxPolarityMap[11]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 11 lanes, TX Polarity +TxPolarityMap[12]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 12 lanes, TX Polarity +TxPolarityMap[13]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 13 lanes, TX Polarity +TxPolarityMap[14]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 14 lanes, TX Polarity +TxPolarityMap[15]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 15 lanes, TX Polarity +TxPolarityMap[16]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 16 lanes, TX Polarity +TxPolarityMap[17]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 17 lanes, TX Polarity +TxPolarityMap[18]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 18 lanes, TX Polarity +TxPolarityMap[19]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 19 lanes, TX Polarity +TxPolarityMap[20]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 20 lanes, TX Polarity +TxPolarityMap[21]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 21 lanes, TX Polarity +TxPolarityMap[22]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 22 lanes, TX Polarity +TxPolarityMap[23]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 23 lanes, TX Polarity +TxPolarityMap[24]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 24 lanes, TX Polarity +TxPolarityMap[25]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 25 lanes, TX Polarity +TxPolarityMap[26]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 26 lanes, TX Polarity +TxPolarityMap[27]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 27 lanes, TX Polarity +TxPolarityMap[28]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 28 lanes, TX Polarity +TxPolarityMap[29]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 29 lanes, TX Polarity +TxPolarityMap[30]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 30 lanes, TX Polarity +TxPolarityMap[31]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] # Slice 31 lanes, TX Polarity + + +########################## Channel Estimates per lane per Slice +gChanEst = [] +for i in range(32): gChanEst.append([]); + # [Chan Est, OF, HF] +gChanEst[0]=[[0.0,0,0]]*16 # Slice 0, Channel Estimates for each lane's RX +gChanEst[1]=[[0.0,0,0]]*16 # Slice 1, Channel Estimates for each lane's RX +gChanEst[2]=[[0.0,0,0]]*16 # Slice 2, Channel Estimates for each lane's RX +gChanEst[3]=[[0.0,0,0]]*16 # Slice 3, Channel Estimates for each lane's RX +gChanEst[4]=[[0.0,0,0]]*16 # Slice 4, Channel Estimates for each lane's RX +gChanEst[5]=[[0.0,0,0]]*16 # Slice 5, Channel Estimates for each lane's RX +gChanEst[6]=[[0.0,0,0]]*16 # Slice 6, Channel Estimates for each lane's RX +gChanEst[7]=[[0.0,0,0]]*16 # Slice 7, Channel Estimates for each lane's RX +gChanEst[8]=[[0.0,0,0]]*16 # Slice 8, Channel Estimates for each lane's RX +gChanEst[9]=[[0.0,0,0]]*16 # Slice 9, Channel Estimates for each lane's RX +gChanEst[10]=[[0.0,0,0]]*16 # Slice 10, Channel Estimates for each lane's RX +gChanEst[11]=[[0.0,0,0]]*16 # Slice 11, Channel Estimates for each lane's RX +gChanEst[12]=[[0.0,0,0]]*16 # Slice 12, Channel Estimates for each lane's RX +gChanEst[13]=[[0.0,0,0]]*16 # Slice 13, Channel Estimates for each lane's RX +gChanEst[14]=[[0.0,0,0]]*16 # Slice 14, Channel Estimates for each lane's RX +gChanEst[15]=[[0.0,0,0]]*16 # Slice 15, Channel Estimates for each lane's RX +gChanEst[16]=[[0.0,0,0]]*16 # Slice 16, Channel Estimates for each lane's RX +gChanEst[17]=[[0.0,0,0]]*16 # Slice 17, Channel Estimates for each lane's RX +gChanEst[18]=[[0.0,0,0]]*16 # Slice 18, Channel Estimates for each lane's RX +gChanEst[19]=[[0.0,0,0]]*16 # Slice 19, Channel Estimates for each lane's RX +gChanEst[20]=[[0.0,0,0]]*16 # Slice 20, Channel Estimates for each lane's RX +gChanEst[21]=[[0.0,0,0]]*16 # Slice 21, Channel Estimates for each lane's RX +gChanEst[22]=[[0.0,0,0]]*16 # Slice 22, Channel Estimates for each lane's RX +gChanEst[23]=[[0.0,0,0]]*16 # Slice 23, Channel Estimates for each lane's RX +gChanEst[24]=[[0.0,0,0]]*16 # Slice 24, Channel Estimates for each lane's RX +gChanEst[25]=[[0.0,0,0]]*16 # Slice 25, Channel Estimates for each lane's RX +gChanEst[26]=[[0.0,0,0]]*16 # Slice 26, Channel Estimates for each lane's RX +gChanEst[27]=[[0.0,0,0]]*16 # Slice 27, Channel Estimates for each lane's RX +gChanEst[28]=[[0.0,0,0]]*16 # Slice 28, Channel Estimates for each lane's RX +gChanEst[29]=[[0.0,0,0]]*16 # Slice 29, Channel Estimates for each lane's RX +gChanEst[30]=[[0.0,0,0]]*16 # Slice 30, Channel Estimates for each lane's RX +gChanEst[31]=[[0.0,0,0]]*16 # Slice 31, Channel Estimates for each lane's RX + + +########################## PRBS and BER Statistics per lane per Slice +gLaneStats = [] +for i in range(32): gLaneStats.append([]); + #[PrbsCount, PrbsCount-1, PrbsCount-2, PrbsRstTime, PrbsLastReadoutTime] +gLaneStats[0]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 0, PRBS Statistics for each lane's RX +gLaneStats[1]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 1, PRBS Statistics for each lane's RX +gLaneStats[2]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 2, PRBS Statistics for each lane's RX +gLaneStats[3]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 3, PRBS Statistics for each lane's RX +gLaneStats[4]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 4, PRBS Statistics for each lane's RX +gLaneStats[5]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 5, PRBS Statistics for each lane's RX +gLaneStats[6]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 6, PRBS Statistics for each lane's RX +gLaneStats[7]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 7, PRBS Statistics for each lane's RX +gLaneStats[8]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 8, PRBS Statistics for each lane's RX +gLaneStats[9]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 9, PRBS Statistics for each lane's RX +gLaneStats[10]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 10, PRBS Statistics for each lane's RX +gLaneStats[11]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 11, PRBS Statistics for each lane's RX +gLaneStats[12]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 12, PRBS Statistics for each lane's RX +gLaneStats[13]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 13, PRBS Statistics for each lane's RX +gLaneStats[14]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 14, PRBS Statistics for each lane's RX +gLaneStats[15]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 15, PRBS Statistics for each lane's RX +gLaneStats[16]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 16, PRBS Statistics for each lane's RX +gLaneStats[17]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 17, PRBS Statistics for each lane's RX +gLaneStats[18]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 18, PRBS Statistics for each lane's RX +gLaneStats[19]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 19, PRBS Statistics for each lane's RX +gLaneStats[20]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 20, PRBS Statistics for each lane's RX +gLaneStats[21]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 21, PRBS Statistics for each lane's RX +gLaneStats[22]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 22, PRBS Statistics for each lane's RX +gLaneStats[23]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 23, PRBS Statistics for each lane's RX +gLaneStats[24]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 24, PRBS Statistics for each lane's RX +gLaneStats[25]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 25, PRBS Statistics for each lane's RX +gLaneStats[26]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 26, PRBS Statistics for each lane's RX +gLaneStats[27]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 27, PRBS Statistics for each lane's RX +gLaneStats[28]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 28, PRBS Statistics for each lane's RX +gLaneStats[29]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 29, PRBS Statistics for each lane's RX +gLaneStats[30]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 30, PRBS Statistics for each lane's RX +gLaneStats[31]=[[0,0,0,0,0,0,0,0,0,0,0]]*16 # Slice 31, PRBS Statistics for each lane's RX + +########################## Line Encoding mode and Data Rate per lane per Slice +gEncodingMode = [] +for i in range(32): gEncodingMode.append([]); + #[PAM4/NRZ, 53.125/25.78125/20.625/10.3125] +gEncodingMode[0]=[['pam4', 53.125]]*16 # Slice 0, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[1]=[['pam4', 53.125]]*16 # Slice 1, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[2]=[['pam4', 53.125]]*16 # Slice 2, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[3]=[['pam4', 53.125]]*16 # Slice 3, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[4]=[['pam4', 53.125]]*16 # Slice 4, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[5]=[['pam4', 53.125]]*16 # Slice 5, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[6]=[['pam4', 53.125]]*16 # Slice 6, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[7]=[['pam4', 53.125]]*16 # Slice 7, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[8]=[['pam4', 53.125]]*16 # Slice 8, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[9]=[['pam4', 53.125]]*16 # Slice 9, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[10]=[['pam4', 53.125]]*16 # Slice 10, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[11]=[['pam4', 53.125]]*16 # Slice 11, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[12]=[['pam4', 53.125]]*16 # Slice 12, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[13]=[['pam4', 53.125]]*16 # Slice 13, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[14]=[['pam4', 53.125]]*16 # Slice 14, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[15]=[['pam4', 53.125]]*16 # Slice 15, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[16]=[['pam4', 53.125]]*16 # Slice 16, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[17]=[['pam4', 53.125]]*16 # Slice 17, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[18]=[['pam4', 53.125]]*16 # Slice 18, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[19]=[['pam4', 53.125]]*16 # Slice 19, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[20]=[['pam4', 53.125]]*16 # Slice 20, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[21]=[['pam4', 53.125]]*16 # Slice 21, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[22]=[['pam4', 53.125]]*16 # Slice 22, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[23]=[['pam4', 53.125]]*16 # Slice 23, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[24]=[['pam4', 53.125]]*16 # Slice 24, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[25]=[['pam4', 53.125]]*16 # Slice 25, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[26]=[['pam4', 53.125]]*16 # Slice 26, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[27]=[['pam4', 53.125]]*16 # Slice 27, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[28]=[['pam4', 53.125]]*16 # Slice 28, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[29]=[['pam4', 53.125]]*16 # Slice 29, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[30]=[['pam4', 53.125]]*16 # Slice 30, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz +gEncodingMode[31]=[['pam4', 53.125]]*16 # Slice 31, Data Rate for each lane, will be updated by pll() or init_pam4/init_nrz + +gCameo400G_EQ = [] +gCameo400G_EQ.append([ \ +{'card':8,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}]) + +gCameo100G_EQ = [] +gCameo100G_EQ.append([ \ +{'card':1,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':1,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':2,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':3,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':4,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':18,'tap4':9,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':5,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-4,'tap3':19,'tap4':8,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':6,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':7,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':1,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':2,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':3,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':1,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':0,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':1,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':2,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':3,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':4,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':5,'tap1':0,'tap2':-3,'tap3':20,'tap4':8,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':6,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}, +{'card':8,'chip':4,'slice':0,'lane':7,'tap1':0,'tap2':0,'tap3':0,'tap4':0,'tap5':0}]) + +#################################################################################################### +def slice_power_up_init(slice=0): + + slices = get_slice_list(slice) + need_to_load_fw = False + + if slice == [0,1]: + hard_reset() + + for slc in slices: + print("\n...Slice %d Power-Up-Initialization Started..."%slc), + sel_slice(slc) + slice_reset() + set_bandgap('on', range(16)) + set_top_pll(pll_side='both', freq=195.3125) + pll_cal_top() + print (get_top_pll()) + if not fw_loaded(): + need_to_load_fw = True + if need_to_load_fw: + fw_load(slice=slices) + + + return slices + +def convert_to_loopback(): + fw_config_cmd(config_cmd=0x9090,config_detail=0x0000) #Destroy Gearbox mode [A0:A1] to [B0:B3] + fw_config_cmd(config_cmd=0x9091,config_detail=0x0000) #Destroy Gearbox mode [A2:A3] to [B4:B7] + for ln in range(4): + fw_config_cmd(config_cmd=0x80F0+ln,config_detail=0x0000) # Set [A0:A3] as PAM4 loopback mode + for ln in range(8,16): + fw_config_cmd(config_cmd=0x80E0+ln,config_detail=0x0000) # Set [B0:B7] as NRZ loopback mode + +def convert_to_gearbox(): + for ln in range(4): + fw_config_cmd(config_cmd=0x90F0+ln,config_detail=0x0000) # Destroy [A0:A3] PAM4 loopback mode + for ln in range(8,16): + fw_config_cmd(config_cmd=0x90E0+ln,config_detail=0x0000) # Destroy [B0:B7] NRZ loopback mode + fw_config_cmd(config_cmd=0x8090,config_detail=0x0000) #Set Gearbox mode [A0:A1] to [B0:B3] + fw_config_cmd(config_cmd=0x8091,config_detail=0x0000) #Set Gearbox mode [A2:A3] to [B4:B7] + +def check_gearbox(): + slices=[2,3,6,7,14,15,30,31] + for idx in range(8): + sel_slice(slices[idx]) + print ("Slice: " + str(slices[idx]) + ", " +str(MdioRdh(0))) + +#################################################################################################### +# config_baldeagle(slice=[0,1], mode='nrz-28G', input_mode='ac', lane='all', cross_mode=False, chip_reset=True) +# config_baldeagle(slice=[0,1], mode='nrz-28G-RETIMER', input_mode='ac', lane='all', cross_mode=False, chip_reset=True) +# +# +#################################################################################################### +def config_baldeagle(slice=[0,1], mode='nrz', input_mode='ac', lane='all', cross_mode=False, chip_reset=True): + + lanes = get_lane_list(lane) + if 'RETIME' in mode.upper(): + all_lanes = get_retimer_lane_list(lane, cross_mode) + else: # PHY Mode + all_lanes = lanes + global gLane; gLane=all_lanes + + if chip_reset==True: + slices = slice_power_up_init(slice) + else: + slices = get_slice_list(slice) + + #auto_pol_en=0 + + + for slc in slices: + sel_slice(slc) + init_lane_for_fw (mode=mode,input_mode=input_mode,lane=all_lanes) + + for slc in slices: + sel_slice(slc) + #fw_reg(115,0xffff) # Disable FFE Adaptation + #reg(0x20,0x380) # CDR BW Kp=6 + #reg(0x1d6,0xcc80) # az short pulse + #reg(0x7b,0x0004) # Enable BLWC + if 'RETIMER' in mode.upper(): # if Retimer Mode + prbs_mode_select(lane=all_lanes, prbs_mode='functional') + fw_config_retimer (mode=mode, lane=lanes, cross_mode=cross_mode) + #fw_config_wait (max_wait=None, lane=all_lanes, print_en=0) + elif 'LOOPBACK' in mode.upper(): # if Retimer Mode + prbs_mode_select(lane=all_lanes, prbs_mode='functional') + fw_config_loopback (mode=mode, lane=lanes,print_en=0) + for ln in range(16): + prbs_mode_select(lane=ln,prbs_mode='prbs') + tx_prbs_mode(lane=ln,patt='PRBS31') + rx_prbs_mode(lane=ln,patt='PRBS31') + msblsb(lane=ln,print_en=0,rx_msblsb=0,tx_msblsb=0) + #fw_config_wait (max_wait=None, lane=all_lanes, print_en=0) + else: # Phy mode or OFF mode + fw_config_lane (mode=mode,lane=all_lanes) + for ln in range(16): + prbs_mode_select(lane=ln,prbs_mode='prbs') + tx_prbs_mode(lane=ln,patt='PRBS31') + rx_prbs_mode(lane=ln,patt='PRBS31') + msblsb(lane=ln,print_en=0,rx_msblsb=0,tx_msblsb=0) + + #if 'OFF' not in mode.upper(): + # for slc in slices: + # sel_slice(slc) + # fw_adapt_wait (max_wait=None, lane=all_lanes, print_en=1) + # fw_config_wait(max_wait=None, lane=all_lanes, print_en=1) + + #for slc in slices: + # sel_slice(slc) + # fw_serdes_params(lane=all_lanes) + + #if auto_pol_en: + # for slc in slices: + # sel_slice(slc) + # if 'RETIMER' in mode.upper(): + # auto_pol(tx_prbs='dis') # Put TX in FUNCTIONAL mode if in RETIMER mode, then run auto RX polarity correction + # else: + # auto_pol(tx_prbs='en') # Enable TX PRBS Gen if in PHY mode, then run auto RX polarity correction + + # for slc in slices: + # sel_slice(slc) + # fw_slice_params(lane='ALL') + + #for slc in slices: + # sel_slice(slc) + # if gSltVer>0: slt_mode(slt_ver=gSltVer) + #for slc in slices: + # sel_slice(slc) + # rx_monitor(rst=1,lane=all_lanes) + + sel_slice(slices[0]) + +#################################################################################################### +# config_pam4_nrz_phy(slice=[2,3,6,7,14,15,30,31], mode='nrz-28G', input_mode='ac', lane='all', cross_mode=False, chip_reset=True) +# config baldeage A lane [0,1,2,3] to Pam4-phy, B lane [8,9,10,11,12,13,14,15] to NRZ-phy +# +# +#################################################################################################### +#def config_pam4_nrz_phy(slice=[2,3,6,7,14,15,30,31], mode='nrz', lane=range(4)+range(8,16), cross_mode=False, chip_reset=True): +def config_pam4_nrz_phy(slice=[2,3,6,7,14,15,30,31], mode='nrz', lane=[0,1,2,3,8,9,10,11,12,13,14,15], cross_mode=False, chip_reset=True): + + lanes = get_lane_list(lane) + if 'RETIME' in mode.upper(): + all_lanes = get_retimer_lane_list(lane, cross_mode) + else: # PHY Mode + all_lanes = lanes + global gLane; gLane=all_lanes + + if chip_reset==True: + slices = slice_power_up_init(slice) + else: + slices = get_slice_list(slice) + + #auto_pol_en=0 + + for slc in slices: + sel_slice(slc) + init_lane_for_fw (mode='nrz-phy',input_mode='ac',lane=[8,9,10,11,12,13,14,15]) + init_lane_for_fw (mode='pam4-phy',input_mode='dc',lane=[0,1,2,3]) + + + for slc in slices: + sel_slice(slc) + if 'RETIMER' in mode.upper(): # if Retimer Mode + fw_config_retimer (mode=mode, lane=lanes, cross_mode=cross_mode) + prbs_mode_select(lane=all_lanes, prbs_mode='functional') + fw_config_wait (max_wait=None, lane=all_lanes, print_en=0) + else: # Phy mode or OFF mode + #fw_config_lane (mode=mode,lane=all_lanes) + fw_config_lane (mode='pam4-phy', lane=[0,1,2,3]) + fw_config_lane (mode='nrz-phy', lane=[8,9,10,11,12,13,14,15]) + #prbs_mode_select(lane=all_lanes, prbs_mode='functional') + + if 'OFF' not in mode.upper(): + for slc in slices: + sel_slice(slc) + fw_adapt_wait (max_wait=None, lane=all_lanes, print_en=1) + fw_config_wait(max_wait=None, lane=all_lanes, print_en=1) + + for slc in slices: + sel_slice(slc) + fw_serdes_params(lane=all_lanes) + + # if auto_pol_en: + # for slc in slices: + # sel_slice(slc) + # if 'RETIMER' in mode.upper(): + # auto_pol(tx_prbs='dis') # Put TX in FUNCTIONAL mode if in RETIMER mode, then run auto RX polarity correction + # else: + # auto_pol(tx_prbs='en') # Enable TX PRBS Gen if in PHY mode, then run auto RX polarity correction + + # for slc in slices: + # sel_slice(slc) + # fw_slice_params(lane='ALL') + + for slc in slices: + sel_slice(slc) + rx_monitor(rst=1,lane=all_lanes) + + sel_slice(slices[0]) + + +#################################################################################################### +def config_active_switchover(mode=None): + + #slc=0 + + + A_lanes=[0,1,2,3] + B_lanes0=[8,9,10,11] + B_lanes1=[12,13,14,15] + cross_mode = True if mode!=None and 'cross' in mode else False + if cross_mode==True: + main_B_lanes = B_lanes1 + standby_B_lanes = B_lanes0 + else: + main_B_lanes = B_lanes0 + standby_B_lanes = B_lanes1 + + all_lanes= A_lanes + main_B_lanes + standby_B_lanes + global gLane; gLane=all_lanes + + if mode!=None and 'init' in mode.lower(): + #slices = slice_power_up_init(slc) + init_lane (mode='nrz',lane=all_lanes) + for ln in range(16): # Set the polarities of the lanes + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + fw_reg_wr(9,0xffff) + fw_reg_wr(8,0xffff) + fw_reg_wr(128,0xffff) + fw_reg_wr(115,0) + prbs_mode_select(lane= all_lanes, prbs_mode='functional') + prbs_mode_select(lane= standby_B_lanes, prbs_mode='prbs') + fw_config_retimer (mode ='nrz', lane = A_lanes, cross_mode = cross_mode) + fw_config_lane (mode ='nrz', lane = standby_B_lanes) + fw_adapt_wait (max_wait=None, lane=all_lanes, print_en=1) + fw_config_wait (max_wait=None, lane=A_lanes, print_en=1) + fw_serdes_params(lane=all_lanes) + fw_slice_params(lane=all_lanes) + fw_reg_wr(8,0) + fw_reg_wr(128,0) + else: + #fw_config_lane (mode ='nrz', lane = standby_B_lanes) + if mode is None and rreg([0x9855,[15,12]])==0xF: # Already in Crossed mode, switch to Direct mode + print("\n Swithing from Cross Mode to Direct Mode") + cross_mode= False + else: + print("\n Swithing from Direct Mode to Cross Mode") + cross_mode= True + fw_config_retimer (mode ='nrz', lane = A_lanes, cross_mode = cross_mode) + + reg([0x9855,0x985f,0x98d1,0x98d2,0x98d3,0x98d4]) + ############################################################################## +def config_baldeagle_gearbox(slice=[2,3,6,7,14,15,30,31], A_lanes=[0,1,2,3], gearbox_type='100G-1', gearbox_by_fw=True, fec_b_bypass=False): + #fw_load(gFwFileName) + if '50' in gearbox_type: + # For 50G-2 Gearbox mode, 3 options supported for A-Lane groups + group0_50G=[0] # A_lanes group 1 -> [A0] <-> [ 8, 9] + group1_50G=[1] # A_lanes group 2 -> [A1] <-> {10,11] + group2_50G=[2] # A_lanes group 3 -> [A2] <-> [12,13] + group3_50G=[3] # A_lanes group 4 -> [A3] <-> [14,15] + group4_50G=[4] # A_lanes group 4 -> [A4] <-> [12,13] + group5_50G=[5] # A_lanes group 5 -> [A5] <-> [14,15] + + #Determine the corresponding B-Lanes for each group of A-Lanes + group0_selected=0 + group1_selected=0 + group2_selected=0 + group3_selected=0 + group4_selected=0 + group5_selected=0 + + #Determine the corresponding B-Lanes for each group of A-Lanes + B_lanes=[] + if all(elem in A_lanes for elem in group0_50G): # If A_lanes contains [0] + B_lanes+=[ 8, 9] + group0_selected=1 + if all(elem in A_lanes for elem in group1_50G): # If A_lanes contains [1] + B_lanes+=[10,11] + group1_selected=1 + if all(elem in A_lanes for elem in group2_50G): # If A_lanes contains [2] + B_lanes+=[12,13] + group2_selected=1 + if all(elem in A_lanes for elem in group3_50G): # If A_lanes contains [3] + B_lanes+=[14,15] + group3_selected=1 + if all(elem in A_lanes for elem in group4_50G): # If A_lanes contains [2] + B_lanes+=[12,13] + group4_selected=1 + if all(elem in A_lanes for elem in group5_50G): # If A_lanes contains [3] + B_lanes+=[14,15] + group5_selected=1 + if group0_selected==0 and group1_selected==0 and group2_selected==0 and group3_selected==0 and group4_selected==0 and group5_selected==0: + print("\n*** 50G-1 Gearbox Setup: Invalid Target A-Lanes specified!"), + print("\n*** Options: A_lanes=[0]"), + print("\n*** A_lanes=[1]"), + print("\n*** A_lanes=[2]"), + print("\n*** A_lanes=[3]"), + print("\n*** A_lanes=[4]"), + print("\n*** A_lanes=[5]"), + print("\n*** A_lanes=[0,1,2,3]") + print("\n*** A_lanes=[0,1,4,5]") + return + else: # '100' in gearbox_type + # For 100G-2 Gearbox mode, 3 options supported for A-Lane groups + group0_100G=[0,1] # A_lanes group 1 -> [A0,A1] <-> [ 8, 9,10,11] + group1_100G=[2,3] # A_lanes group 2 -> [A2,A3] <-> [12,13,14,15] + group2_100G=[4,5] # A_lanes group 3 -> [A4,A5] <-> [12,13,14,15] + + #Determine the corresponding B-Lanes for each group of A-Lanes + #group0_selected=0 + group1_selected=0 + group2_selected=0 + B_lanes=[] + if all(elem in A_lanes for elem in group0_100G): # If A_lanes contains [0,1] + B_lanes+=[8,9,10,11] + #group0_selected=1 + if all(elem in A_lanes for elem in group1_100G): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + group1_selected=1 + elif all(elem in A_lanes for elem in group2_100G): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + group2_selected=1 + if group1_selected==0 and group2_selected==0: # can only select group 1 or 2, not both + print("\n*** 100G-1 Gearbox Setup: Invalid Target A-Lanes specified!"), + print("\n*** Options: A_lanes=[0,1]"), + print("\n*** A_lanes=[2,3]"), + print("\n*** A_lanes=[4,5]"), + print("\n*** A_lanes=[0,1,2,3]"), + print("\n*** A_lanes=[0,1,4,5]") + return + + lanes = get_lane_list(lane=A_lanes+B_lanes) + global gLane; gLane=lanes + slices = slice_power_up_init(slice) + + if gearbox_by_fw: # use FW Command to setup and monitor Gearbox + #fw_reg_wr=(14,gb_fec_test_wait) + for slc in slices: + sel_slice(slc) + init_lane_for_fw(mode='pam4',input_mode='dc',lane=A_lanes) + init_lane_for_fw(mode='nrz' ,input_mode='ac',lane=B_lanes) + for ln in range(16): + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + if '50' in gearbox_type: + fw_config_gearbox_50G (A_lanes,fec_b_byp=fec_b_bypass) + else: + if 'LT' in gearbox_type: + print("Link training Enable!!!!!!!!!!!!") + fw_config_gearbox_100G_LT(A_lanes,fec_b_byp=fec_b_bypass) + else: + fw_config_gearbox_100G(A_lanes,fec_b_byp=fec_b_bypass) + + for slc in slices: + sel_slice(slc) + #start_time=time.time() # start timer to get gearbox-ready time + #fw_adapt_wait(max_wait=10, lane=A_lanes+B_lanes, print_en=1) + #print("\n...Waiting for FEC Status Lock (fec_wait=%d) ... "%(fw_reg_rd(14))), + + else: # use FW to adapt lanes and use software to setup and monitor Gearbox + for slc in slices: + sel_slice(slc) + opt_lane (mode='pam4',input_mode='dc',lane=A_lanes) + opt_lane (mode='nrz' ,input_mode='ac',lane=B_lanes) + for ln in range(16): + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + if '50' in gearbox_type: + sw_config_gearbox_50G (A_lanes,fec_b_byp=fec_b_bypass) + else: + sw_config_gearbox_100G(A_lanes,fec_b_byp=fec_b_bypass) + #start_time=time.time() # start timer to get gearbox-ready time + + #for slc in slices: + # sel_slice(slc) + # fw_gearbox_wait (max_wait=10, print_en=1) + #for slc in slices: + # sel_slice(slc) + # fw_serdes_params(lane=lanes) + #for slc in slices: + # sel_slice(slc) + # fec_status() + # +#################################################################################################### +# Initialize and Optimize Baldeagle in BITMUX mode +# +# This function configures and Optimizes Baldeagle A-lanes in NRZ 20G and B lanes in 10G modes +# +# It assumes QSFP cables connected between: Slice 0: cable between A0-3 to A4-7 +# Slice 0: loopback modules on B0-7 +# Slice 1: cable between A0-3 to A4-7 +# Slice 1: loopback modules on B0-7 +# +# The main idea behind the bitmux setup is to make sure all three receivers (the one on the A side and two on the B side) are ready together. If one or more are not ready, the traffic on both directions (A-to-B and B-to-A) stops. +# +# The bitmux setup sequence: +# 1. Call any software init to the lanes going to be set up in bitmux mode (do not call software init to the lanes from this step forward) +# 2. Enable Bitmux mode configuration +# 3. Issue Configure Commands to the lanes, 20G and 10G (and start adaptation) +# 4. while (!rxAdaptationComplete ) ( timeout = 2sec ) --- Stay in the while loop until all three lanes adaptations done +# Keep PRBS Generator ON (this is needed if Credo is TX source, such as loopback module or cable between two ports) +# On timeout, issue HW lane-reset (or go back to step 3 and reconfigure the lanes) +# 5. All three lanes adaptation complete ---> Disable PRBS Generator +# +#################################################################################################### +def config_baldeagle_bitmux(slice=[0,1], A_lanes=[0,1,2,3], bitmux_type='20G',print_en=1, chip_reset=True): + + sel_slice(slice) + global gLane + + #auto_pol_en=0 + global RxPolarityMap; RxPolarityMap=[] + #Slice [A0.............A7, B0,..........B7] + RxPolarityMap.append([]); RxPolarityMap[0]=[ 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0 ] # Slice 0 lanes, RX Polarity + RxPolarityMap.append([]); RxPolarityMap[1]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] # Slice 1 lanes, RX Polarity + + #### edit by Jeff for Falcon #### + #RxPolarityMap.append([]); RxPolarityMap[0]=[1,1,0,0,1,1,0,0, 0,1,1,0,0,1,1,0] # Slice 0 lanes, RX Polarity + #RxPolarityMap.append([]); RxPolarityMap[1]=[0,0,0,0,0,0,0,0, 0,1,0,0,1,1,1,0] # Slice 1 lanes, RX Polarity + #TxPolarityMap.append([]); TxPolarityMap[0]=[0,0,0,0,0,0,0,0, 0,1,1,1,0,0,0,0] # Slice 0 lanes, TX Polarity + #TxPolarityMap.append([]); TxPolarityMap[1]=[1,0,1,0,1,0,1,0, 0,1,1,0,0,0,0,1] # Slice 1 lanes, TX Polarity + + #for ln in gLane: # Set Polarity of each lane according the pol_list + #pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + # For Bitmux mode, 3 options supported for A-Lane groups + group1_bitmux=[0,1] # A_lanes group 1 -> [A0,A1] <-> [B0,B1,B2,B3] + group2_bitmux=[2,3] # A_lanes group 2 -> [A2,A3] <-> [B4,B5,B6,B7] + group3_bitmux=[4,5] # A_lanes group 3 -> [A4,A5] <-> [B4,B5,B6,B7] + #Determine the corresponding B-Lanes for each group of A-Lanes + group1_selected=0 + group2_selected=0 + B_lanes=[] + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + B_lanes +=[8,9,10,11] + group1_selected=1 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + group2_selected=1 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + group2_selected=1 + if group1_selected==0 and group2_selected==0: + print("\n*** Bitmux Setup: Invalid Target A-Lanes specified!"), + print("\n*** Options: A_lanes=[0,1]"), + print("\n*** A_lanes=[2,3]"), + print("\n*** A_lanes=[4,5]"), + print("\n*** A_lanes=[0,1,2,3]"), + print("\n*** A_lanes=[0,1,4,5]"), + return + + lanes = get_lane_list(lane=A_lanes+B_lanes) + gLane=lanes + if chip_reset==True: + slice_power_up_init(slice) #slices = slice_power_up_init(slice) + # else: + # slices = get_slice_list(slice) + + #init_lane (mode='nrz20',input_mode='ac',lane=A_lanes) + #init_lane (mode='nrz10',input_mode='ac',lane=B_lanes) + #global gPrbsEn; gPrbsEn=False + if '53' in bitmux_type: + init_lane_for_fw('pam4',input_mode='ac',lane=A_lanes) + elif '51' in bitmux_type: + init_lane_for_fw('pam4',input_mode='ac',lane=A_lanes) + else: + init_lane_for_fw('nrz',input_mode='ac',lane=A_lanes) + + init_lane_for_fw('nrz',input_mode='ac',lane=B_lanes) + + #for ln in lanes: # Set Polarity of each lane according the pol_list + for ln in range(16): + for Slices in range(slice): + pol(TxPolarityMap[Slices][ln],RxPolarityMap[Slices][ln],ln,0) + + prbs_mode_select(lane=lanes, prbs_mode='functional') + + if '53' in bitmux_type: + fw_config_bitmux_53G(A_lanes) + elif '51' in bitmux_type: + fw_config_bitmux_51G(A_lanes) + else: + fw_config_bitmux_20G(A_lanes) + + prbs_mode_select(lane=lanes, prbs_mode='functional') + #pll_cap(81,150,lane=14) + fw_bitmux_wait(lane=A_lanes, max_wait=10, print_en=print_en) + + prbs_mode_select(lane=lanes, prbs_mode='functional') + #if auto_pol_en: auto_pol(tx_prbs='dis') # Do not enable TX PRBS Gen if in RETIMER mode, for auto polarity correction + fw_serdes_params(lane=lanes) + rx_monitor(rst=1,lane=lanes) + +#################################################################################################### +def opt_tx_taps(slice=0, mode='nrz', input_mode='ac', lane=None): + global gLaneStats #[per Slice][per lane], [PrbsCount, PrbsCount-1,PrbsCount-2, PrbsRstTime, PrbsLastReadoutTime] + pre2 = 2 + pre1 = -8 + main = 17 + post1 = 0 + post2 = 0 + tx_taps(pre2, pre1, main, post1, post2) + Eye_best = eye_pam4(lane) + Ber_best, PostBerBest = ber(lane,rst=1,t=5)[lane] + pre2_best = pre2 + pre1_best = pre1 + main_best = main + post1_best = post1 + post2_best = post2 + #pre2_next = pre2 + pre1_next = pre1 + main_next = main + post1_next = post1 + post2_next = post2 + + for x in range(-6,6): #pre2 range + tx_taps(x, pre1_next, main_next, post1_next, post2_next) + if mode == 'pam4': + Eye_post = eye_pam4(lane) + elif mode == 'nrz': + Eye_post = eye_nrz(lane) + Ber_post, PostFecBer = ber(lane,rst=1,t=5)[lane] + serdes_params(lane) + time.sleep(1) + if (Eye_post > Eye_best and Ber_post < Ber_best): + Eye_best = Eye_post + Ber_best = Ber_post + pre2_best = x + print('\nBest pre 2 setting so far is : %d' %pre2_best) + pre2_next = x + #serdes_params() + #time.sleep(1) + + for y in range(-12,0): #pre1 range + tx_taps(pre2_next, y, main_next, post1_next, post2_next) + if mode == 'pam4': + Eye_post = eye_pam4(lane) + elif mode == 'nrz': + Eye_post = eye_nrz(lane) + Ber_post, PostFecBer = ber(lane,rst=1,t=5)[lane] + serdes_params(lane) + time.sleep(1) + if (Eye_post > Eye_best and Ber_post < Ber_best): + Eye_best = Eye_post + Ber_best = Ber_post + pre1_best = y + print('\nBest pre 1 setting so far is : %d' %pre1_best) + pre1_next = y + #serdes_params() + #time.sleep(1) + + for z in range(-16,21): #main range + tx_taps(pre2_next, pre1_next, z, post1_next, post2_next) + if mode == 'pam4': + Eye_post = eye_pam4(lane) + elif mode == 'nrz': + Eye_post = eye_nrz(lane) + Ber_post,PostFecBer = ber(lane,rst=1,t=5)[lane] + serdes_params(lane) + time.sleep(1) + if (Eye_post > Eye_best and Ber_post < Ber_best): + Eye_best = Eye_post + Ber_best = Ber_post + main_best = z + print('\nBest main setting so far is : %d' %main_best) + main_next = z + #serdes_params() + #time.sleep(1) + + for p in range(-7,0): #post1 range + tx_taps(pre2_next, pre1_next, main_next, p, post2) + if mode == 'pam4': + Eye_post = eye_pam4(lane) + elif mode == 'nrz': + Eye_post = eye_nrz(lane) + Ber_post,PostFecBer = ber(lane,rst=1,t=5)[lane] + serdes_params(lane) + time.sleep(1) + if (Eye_post > Eye_best and Ber_post < Ber_best): + Eye_best = Eye_post + Ber_best = Ber_post + post1_best = p + print('\nBest post1 setting so far is : %d' %post1_best) + post1_next = p + #time.sleep(1) + + for q in range(-3,3): #post2 range + tx_taps(pre2_next, pre1_next, main_next, post1_next, q) + if mode == 'pam4': + Eye_post = eye_pam4(lane) + elif mode == 'nrz': + Eye_post = eye_nrz(lane) + Ber_post,PostFecBer = ber(lane,rst=1,t=5)[lane] + serdes_params(lane) + time.sleep(1) + if (Eye_post > Eye_best and Ber_post < Ber_best): + Eye_best = Eye_post + Ber_best = Ber_post + post2_best = q + print('\nBest post2 setting so far is : %d' %post2_best) + post2_next = q + + print ('\nOptimal precursor 2 value is: %d' %pre2_best) + print ('\nOptimal precursor 1 value is: %d' %pre1_best) + print ('\nOptimal main cursor value is: %d' %main_best) + print ('\nOptimal post cursor 1 value is: %d' %post1_best) + print ('\nOptimal post cursor 2 value is: %d' %post2_best) + + tx_taps(pre2, pre1, main, post1, post2) + serdes_params(lane) + + +#################################################################################################### +# First step inside a python shell is to establish connection +# to Credo Serdes Eval boards+Dongle+USB Cable to PC +# +# Usage: +# *** mdio() : Show current status of Credo MDIO connection +# +# *** mdio('connect',0) : Connect to Credo Slice 0 (on USB port 0) +# *** mdio('connect',1) : Connect to Credo Slice 1 (on USB port 0) +# *** mdio('connect',0,1) : Connect to Credo Slice 0 (on USB port 1) +# *** mdio('connect',1,1) : Connect to Credo Slice 1 (on USB port 1) +# +# *** mdio('disconnect',0) : Disconnect MDIO to Credo Slice 0 (on USB port 0) +# *** mdio('disconnect',1) : Disconnect MDIO to Credo Slice 1 (on USB port 0) +# *** mdio('disconnect',0,1) : Disconnect MDIO to Credo Slice 0 (on USB port 1) +# *** mdio('disconnect',1,1) : Disconnect MDIO to Credo Slice 1 (on USB port 1) +# +#################################################################################################### +def mdio(connect=None, Slice=None, usb_port=None): + time.sleep(0.5) + global gUsbPort + global gSlice + global gMode_sel + + #SWAPPING_USB_PORT=0 + SWAPPING_SLICE=0 + + if (connect is None): # only checking MDIO connection status + mdio_status = get_mdio_status() + if (mdio_status == MDIO_DISCONNECTED): + print ('\n...Credo MDIO Already Disconnected from USB Port %d Slice %d'%(gUsbPort,gSlice)), + elif(mdio_status == MDIO_CONNECTED): + print ('\n...Credo MDIO Already Connected to USB Port %d Slice %d'%(gUsbPort,gSlice)), + else: # mdio_status = MDIO_LOST_CONNECTION + val0 = rreg(0x0,0) + print ('\n***> Credo MDIO Connection is LOST on USB Port %d Slice %d'%(gUsbPort,gSlice)), + print ('\n***> Reading back invalid value 0x%04X for Credo Registers' % val0), + print ('\n***> Disconnecting MDIO on USB Port %d Slice %d'%(gUsbPort,gSlice)) + chip.disconnect() + #mdio_status = MDIO_DISCONNECTED + + else: # asked to connect/dis-connect + if usb_port!=None and usb_port!=gUsbPort: + #SWAPPING_USB_PORT=1 + gUsbPort=usb_port + + if Slice!=None and Slice!=gSlice: + SWAPPING_SLICE=1 + gSlice=Slice + + if connect == 1 or connect =='connect': + mdio_status= get_mdio_status() + if ( SWAPPING_SLICE==0 and mdio_status == MDIO_CONNECTED): # Already connected and reading valid values + print ('\n...Credo MDIO Already Connected to USB Port %d Slice %d'%(gUsbPort,gSlice)), + else: # changing Slice or not connected to any Slice yet, issue connect() command + #if (SWAPPING_SLICE and mdio_status == MDIO_CONNECTED) + #chip.connect(phy_addr=gSlice, usb_sel=gUsbPort) + mdio_status= get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + print ('\n...Credo MDIO Connected to USB Port %d Slice %d'%(gUsbPort,gSlice)), + else: + #val0 = rregLane(0x0) + print ('\n***> Credo MDIO Connection Attempt Failed on USB Port %d Slice %d'%(gUsbPort,gSlice)), + #print ('\n***> Reading back 0x%04X! for SerDes Registers' % val0), + print ('\n***> Disconnecting Python from MDIO on USB Port %d Slice %d'%(gUsbPort,gSlice)), + print ('\n***> Fix Dongle Connection Issue and Try again!') + chip.disconnect() + #mdio_status = MDIO_DISCONNECTED + + elif connect == 0 or connect =='disconnect': # connect == 0 (i.e. Disconnect MDIO) + #mdio_status = get_mdio_status() + #if (mdio_status != MDIO_CONNECTED): + #chip.connect(phy_addr=gSlice, usb_sel=gUsbPort) + #chip.disconnect() + print ('\n...Credo MDIO Disconnected from USB Port %d Slice %d'%(gUsbPort,gSlice)) + #mdio_status = MDIO_DISCONNECTED + time.sleep(0.5) +#################################################################################################### +# Select Slice/slicer inside the part to work with. +# Sets Global variable "gSlice" to the selected Slice +# +# Usage: +# *** sel_slice() : Show current Slice conencted to. returns 0: Slice 0, 1: Slice 1 +# *** sel_slice(0) : Connect to Slice/slicer 0 +# *** sel_slice(1) : Connect to Slice/slicer 1 +#################################################################################################### +def sel_slice(slice=None,mdio=None): + global gSlice + global gMode_sel + global gUsbPort + + if (slice!=None): # asked to connect to a particular Slice inside the same chip, sharing MDIO/I2c bus + gSlice=slice + # try: + # #chip.connect(phy_addr=slice, usb_sel=gUsbPort,mdio=gMode_sel) + # gSlice=slice + # except: + # #chip.connect(phy_addr=slice, usb_sel=gUsbPort,mdio=gMode_sel) + # gSlice=slice + + return gSlice +#################################################################################################### +def get_mdio_status(): + mdio_status = MDIO_LOST_CONNECTION + val0 = rreg(0x0,0) + val1 = rreg(0x1,0) + + if ((val0==0xffff or val0==0x7fff) and val1==val0): + mdio_status = MDIO_LOST_CONNECTION + + elif ((val0==0x0001) and val1==val0): + mdio_status = MDIO_DISCONNECTED + + elif (val0!=0x0000 and val0!=0x0001 and val0!=0xffff and val1!=val0): # Already connected and reading valid values + mdio_status = MDIO_CONNECTED + + return mdio_status + +#################################################################################################### +# +# Process the specific lane(s) passed +# and return an integer list of "lanes" to the calling function to loop through list of lanes +# +################################################################################################### +def get_slice_list(slice=None): + + if slice is None: slices=[gSlice] # single slice download mode on the Slice already selected + elif type(slice)== int: slices=[slice] # single slice download mode + elif type(slice)== list: slices=slice # single slice download mode + else: slices=[0,1] # broadcast download mode to both slices + + return slices +#################################################################################################### +# +# Process the specific lane(s) passed +# and return an integer list of "lanes" to the calling function to loop through list of lanes +# +#################################################################################################### +def get_lane_list(lane=None): + if lane is None: lanes=gLane + if type(lane)==int: lanes=[lane] + elif type(lane)==list: lanes=lane + elif type(lane)==str and lane.upper()=='ALL': + lanes=list(range(len(lane_name_list))) + + return lanes +#################################################################################################### +# register write/read +# intended for engineering mode use only +# specifically made for use in python shell command +# and not be called from other functions +#################################################################################################### +def reg(addr, val=None, lane=None,slice=None,print_en=1): + + full_addr=False + lanes = get_lane_list(lane) + slices = get_slice_list(slice) + + if type(addr)==int: addr_list=[addr] + elif type(addr)==list: addr_list=addr + + if addr_list[0]>= 0x1000: # less than 0x1000 taken as per-lane registers + full_addr=True + lanes=[0] + + if print_en: + ##### Print Headers + print("\nSlice ADDR:"), + #print("\n ADDR:"), + if full_addr: + print("VALUE"), + else: + for ln in lanes: + print(" %s" %(lane_name_list[ln])), + + ##### Write registers first, if value given + if val!=None: + for slc in slices: + sel_slice(slc) + for add in addr_list: + for ln in lanes: + wreg(add,val,ln) + ##### Read registers, one address per row + for add in addr_list: + for slc in slices: + sel_slice(slc) + if print_en: + if full_addr: print("\n S%d %04X:" % (gSlice,add) ), + else: print("\n S%d %03X:"% (gSlice,add) ), + for ln in lanes: + print("%04X" % (rreg(add,ln)) ), + +#################################################################################################### +def rreg(addr, lane = 0): + ''' + read from a register address, register offset or register field + ''' + #if lane is None: lane=gLane + + #lane_mode_list + if type(addr) == int: + if (addr & 0xf000) == 0: addr += (0x7000 + lane*0x200) #addr += lane_offset[lane_name_list[lane]] + return MdioRd(addr) + elif type(addr) == list: + val = 0 + i = 0 + while(i < (len(addr)-1)): + full_addr = addr[i] + if (addr[i] & 0xf000) == 0: full_addr += (0x7000 + lane*0x200)#lane_offset[lane_name_list[lane]] + val_tmp = MdioRd(full_addr) + i += 1 + mask = sum([1<>addr[i][-1] + val = (val<<(addr[i][0]-addr[i][-1]+1)) + val_tmp + i += 1 + return val + else: + print("\n***Error reading register***") + return -1 + +#################################################################################################### +def wreg_new(addr, val, lane=None, slice=None): + #mdio_log_en=0 + lanes = get_lane_list(lane) + if lane is None: lanes=[gLane[0],gLane[0]+1] + slices = get_slice_list(slice) + + if type(addr) == list: # Address and bits given + reg_addr = addr[0] + bit_hi = addr[1][0] + bit_lo = addr[1][-1] + else: # Address given, but no bit, meaning all bits [15:0] + reg_addr = addr + bit_hi = 15 + bit_lo = 0 + + + for slc in slices: + if slice!=None: sel_slice(slc) + for ln in lanes: + if (reg_addr & 0xf000) == 0: # per-lane address + full_addr = reg_addr + lane_offset[lane_name_list[ln]] + else: + full_addr = reg_addr + + if type(addr) == int: # Address given, but no bit, meaning all bits [15:0] + MdioWr(full_addr, val) + #if mdio_log_en: print("wreg( [0x%04X, [%2d,%2d]], 0x%04X, lane=%2d ) # Slice %d "%(full_addr,bit_hi,bit_lo,val,ln, slc)) + elif type(addr) == list: # Address and bits given + curr_val = MdioRd(full_addr) + mask = sum([1<I', fw_data[start :start+4 ])[0] + file_crc_code = struct.unpack_from('>H', fw_data[start+4 :start+6 ])[0] + #file_date_code = struct.unpack_from('>H', fw_data[start+6 :start+8 ])[0] + entryPoint = struct.unpack_from('>I', fw_data[start+8 :start+12])[0] + length = struct.unpack_from('>I', fw_data[start+12:start+16])[0] + ramAddr = struct.unpack_from('>I', fw_data[start+16:start+20])[0] + data = fw_data[start+20:] + + # d=datetime.date(1970, 1, 1) + datetime.timedelta(file_date_code) + + # if print_en: print ("fw_load Hash Code : 0x%06x" % file_hash_code) + # if print_en: print ("fw_load Date Code : 0x%02x (%04d-%02d-%02d)" % (file_date_code, d.year, d.month, d.day)) + # if print_en: print ("fw_load CRC Code : 0x%04x" % file_crc_code) + # if print_en: print ("fw_load Length : %d" % length) + # if print_en: print ("fw_load Entry : 0x%08x" % entryPoint) + # if print_en: print ("fw_load RAM : 0x%08x" % ramAddr) + + dataPtr = 0 + sections = (length+23)/24 + + ##### FW Unload + wreg(FW2, 0xFFF0) + wreg(FW1, 0x0AAA) + wreg(FW1, 0x0000) + + if broadcast_mode.upper()=='ON': # broadcast download mode, use fixed delay + time.sleep(.01) + else: # single-slice download mode, status read back + #start_time=time.time() + checkTime = 0 + status = rreg(FW2) + while status != 0: + status = rreg(FW2) + checkTime += 1 + if checkTime > 100000: + print ('\n...FW LOAD ERROR: : Wait for FW2=0 Timed Out! FW2 = 0x%X'% status) #Wait for FW2=0: 0.000432 sec + break + #stop_time=time.time() + wreg(FW2, 0x0000) + ##### FW Unload Done + + download_start_time=time.time() + + ##### Main FW Download loop + i = 0 + while i < sections: + checkSum = 0x800c + wreg(FW0+12, ramAddr>>16) + wreg(FW0+13, (ramAddr & 0xFFFF)) + checkSum += ( ramAddr >> 16 ) + ( ramAddr & 0xFFFF ) + for j in range( 12 ): + if (dataPtr > length): + mdioData = 0x0000 + else: + mdioData = struct.unpack_from('>H', data[dataPtr:dataPtr+2])[0] + wreg(FW0+j, mdioData) + checkSum += mdioData + dataPtr += 2 + ramAddr += 2 + + wreg(FW0 + 14, (~checkSum+1) & 0xFFFF) + wreg(FW0 + 15, 0x800C) + #print '\nDEBUG fw_load: section %d, Checksum %X' % (i, checkSum), + + + if broadcast_mode.upper()=='ON': # broadcast download mode, use fixed delay passed to the function + time.sleep(wait) + else: # single-slice download mode, status read back per section + checkTime = 0 + status = rreg(FW0 + 15) + while status == 0x800c: + status = rreg(FW0 + 15) + checkTime += 1 + if checkTime > 1000: + print ('\n...FW LOAD ERROR: Write to Ram Timed Out! FW0 = %x'% status) + break + + #if checkTime>0: + #if print_en: print ('\nfw_load: section %d, CheckTime= %d' % (i, checkTime)) + + if status != 0: + print("\n...FW LOAD ERROR: Invalid Write to RAM, section %d, Status %d"%(i,status)) + i += 1 + print("\b\b\b\b\b%3.0f%%"%(100.0 *i/sections)), # Display % download progressed + ##### End of Main FW Download loop + + ##### Last steps of FW Download + wreg(FW0 + 12, entryPoint>>16) + wreg(FW0 + 13, ( entryPoint & 0xFFFF )) + checkSum = ( entryPoint >> 16 ) + ( entryPoint & 0xFFFF ) + 0x4000 + wreg(FW0 + 14, ( ~checkSum+1 ) & 0xFFFF) + wreg(FW0 + 15, 0x4000) + time.sleep(.1) + + download_time = time.time()-download_start_time + fw_file_ptr.close() + + return download_time, file_crc_code +#################################################################################################### +def cameo_fw_unload_all(): + cameo_drv_open() + slice=[0,1] + slices = get_slice_list(slice) + for card in range(1,9): + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + #print("\ncard %d chip %d\n" % (card,num)) + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + fw_unload(print_en=1) + cameo_drv_close() + +def cameo_fw_unload(card): + cameo_drv_open() + slice=[0,1] + slices = get_slice_list(slice) + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + #print("\ncard %d chip %d\n" % (card,num)) + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + fw_unload(print_en=1) + cameo_drv_close() + +def cameo_fw_load_status_all() : + cameo_drv_open() + slice=[0,1] + slices = get_slice_list(slice) + + print("+--------------------------------------------------+") + print("| Card | Chip | Slice | Status | Version |") + print("+--------------------------------------------------+") + for card in range(1,9): + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + ver_code = fw_ver(print_en=0) + ver_str = "VER_%02d.%02d.%02d" %(ver_code>>16&0xFF,ver_code>>8&0xFF,ver_code&0xFF) + if not fw_loaded(print_en=0): + print("| %d | %d | %d | Not Loaded | N/A |" % (card,num,slice_num)) + else: + print("| %d | %d | %d | Loaded | %s |" % (card,num,slice_num,ver_str)) + else: + for slice_num in slices: + sel_slice(slice_num) + print("| %d | %d | %d | N/A | N/A |" % (card,num,slice_num)) + print("+--------------------------------------------------+") + cameo_drv_close() +def fw_load_status (file_crc_code, slice=0): + ##### Check FW CRC for each slice and confirm a good download + fw_info(slice=slice) + crc_code = fw_crc (print_en=0) + if crc_code != file_crc_code: + print("\n\n...Slice %d FW LOAD ERROR: CRC Code Not Matching, Expected CRC: 0x%04x -- Actual CRC: 0x%04x\n\n" %(slice,file_crc_code,crc_code)) + return False + else: + return True + #return hash_code, crc_code, date_code +def cameo_drv_open(): + libcameo.lscpcie_open() + cameo_change_chip_card(1,1) + sel_slice(0) +def cameo_drv_close(): + libcameo.lscpcie_close() +def cameo_change_chip_card(chip,card): + if card > 8 or card < 1: + print ("card out of range") + return + if chip > 4 or chip < 1: + print ("chip out of range") + return + #print "change to card %d" % card + libcameo.cm_sw_phy_card(chip,card) + sel_slice(0) +def cameo_fw_load_2_card (card=1,file_name=None,path_name=None,slice=[0,1], wait=0.0001): + if card==2 or card==4 or card==6 or card==8: + card = card - 1 + if card>8 or card<1: + return + cameo_drv_open() + global gMode_sel + + slices = get_slice_list(slice) + + cameo_change_chip_card(1,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + sel_slice(slices[0]) + present_card = card + else: + cameo_change_chip_card(1,card+1) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + sel_slice(slices[0]) + present_card = card+1 + else: + print ("Card MDIO fail!") + return + + if gMode_sel== True: + #if len(slices) > 1: + broadcast_mode='ON' + print("\n...Broadcast-Mode Downloading FW to both slices... "), + #### 1. Define FW file folder and the filename according to chip revision + fw_file_name = fw_load_file_init(file_name,path_name) + if fw_file_name == False: + return + + ##### 2. Before download, make sure Top PLL is set, cal'ed and FW is Unloaded in each slice + cameo_change_chip_card(1,card) + sel_slice(slices[0]) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + fw_load_init() + time.sleep(0.1) + if gMode_sel== True: + fw_load_broadcast_mode(broadcast_mode) + cameo_change_chip_card(1,card+1) + sel_slice(slices[0]) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for num in range(1,5): + cameo_change_chip_card(num,card+1) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + fw_load_init() + time.sleep(0.1) + if gMode_sel== True: + fw_load_broadcast_mode(broadcast_mode) + time.sleep(0.5) + + ##### 3. if broadcast FW download mode, enable it in each slice first before moving forward + #if gMode_sel== True: + # cameo_change_chip_card(1,card) + # sel_slice(slices[0]) + # mdio_status = get_mdio_status() + # + # if (mdio_status == MDIO_CONNECTED): + # for num in range(1,5): + # cameo_change_chip_card(num,card) + # mdio_status = get_mdio_status() + # if (mdio_status == MDIO_CONNECTED): + # for slice_num in slices: + # sel_slice(slice_num) + # mdio_status = get_mdio_status() + # if (mdio_status == MDIO_CONNECTED): + # fw_load_broadcast_mode(broadcast_mode) + # cameo_change_chip_card(1,card+1) + # sel_slice(slices[0]) + # mdio_status = get_mdio_status() + # if (mdio_status == MDIO_CONNECTED): + # for num in range(1,5): + # cameo_change_chip_card(num,card) + # mdio_status = get_mdio_status() + # if (mdio_status == MDIO_CONNECTED): + # for slice_num in slices: + # sel_slice(slice_num) + # mdio_status = get_mdio_status() + # if (mdio_status == MDIO_CONNECTED): + # print "Set slice %d to bcast" % slice_num + # fw_load_broadcast_mode(broadcast_mode) + + cameo_change_chip_card(1,present_card) + ##### 4. FW Download starts here + if gMode_sel== True: + sel_slice(slices[0]) + download_time, expected_crc_code = fw_load_main(fw_file_name,broadcast_mode,wait) + + else: + for slice_num in slices: + sel_slice(slice_num) + download_time, expected_crc_code = fw_load_main(fw_file_name,broadcast_mode,wait) + + ##### 5. if in broadcast FW download mode mode, disable it right away in each slice + if gMode_sel== True: + cameo_change_chip_card(1,card) + sel_slice(slices[0]) + mdio_status = get_mdio_status() + + if (mdio_status == MDIO_CONNECTED): + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + fw_load_broadcast_mode('OFF') + cameo_change_chip_card(1,card+1) + sel_slice(slices[0]) + mdio_status = get_mdio_status() + + if (mdio_status == MDIO_CONNECTED): + for num in range(1,5): + cameo_change_chip_card(num,card+1) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + fw_load_broadcast_mode('OFF') + + print(' (%2.2f sec)'% (download_time)) + #print("\r"), + + ##### 6. Check FW CRC for each slice and confirm a good download + for slice_num in slices: + sel_slice(slice_num) + fw_load_status(expected_crc_code,slice_num) + + sel_slice(slices[0]) # select the first slice before exiting + cameo_drv_close() +#################################################################################################### +# FW_LOAD() +# +# Downloads FW to one slice or both slices of a chip at the same time +# +# usage: +# fw_load('1.19.00') # load FW ver 1.19.00 to slice already selected +# fw_load('1.19.00', slice=[0]) # load FW ver 1.19.00 to slice 0 +# fw_load('1.19.00', slice=[1]) # load FW ver 1.19.00 to slice 1 +# fw_load('1.19.00', slice=[0,1]) # load FW ver 1.19.00 to both slices in parallel +#################################################################################################### +def fw_load (file_name=None,path_name=None,slice=[0,1], wait=0.0001): + global gMode_sel + + slices = get_slice_list(slice) + + + if gMode_sel== True: + if len(slices) > 1: + broadcast_mode='ON' + print("\n...Broadcast-Mode Downloading FW to both slices... "), + else: + broadcast_mode='OFF' + print("\n...Downloading FW to slice %d... "%slices[0]), + else: + broadcast_mode ='OFF' + #### 1. Define FW file folder and the filename according to chip revision + fw_file_name = fw_load_file_init(file_name,path_name) + if fw_file_name == False: + return False + + ##### 2. Before download, make sure Top PLL is set, cal'ed and FW is Unloaded in each slice + for slice_num in slices: + sel_slice(slice_num) + fw_load_init() + + ##### 3. if broadcast FW download mode, enable it in each slice first before moving forward + if gMode_sel== True: + for slice_num in slices: + sel_slice(slice_num) + fw_load_broadcast_mode(broadcast_mode) + + ##### 4. FW Download starts here + if gMode_sel== True: + sel_slice(slices[0]) + download_time, expected_crc_code = fw_load_main(fw_file_name,broadcast_mode,wait) + + else: + for slice_num in slices: + sel_slice(slice_num) + download_time, expected_crc_code = fw_load_main(fw_file_name,broadcast_mode,wait) + + ##### 5. if in broadcast FW download mode mode, disable it right away in each slice + if gMode_sel== True: + for slice_num in slices: + sel_slice(slice_num) + fw_load_broadcast_mode('OFF') + + print(' (%2.2f sec)'% (download_time)) + #print("\r"), + + ##### 6. Check FW CRC for each slice and confirm a good download + for slice_num in slices: + sel_slice(slice_num) + ret_fw_load_st = fw_load_status(expected_crc_code,slice_num) + if ret_fw_load_st is False: + return False + + sel_slice(slices[0]) # select the first slice before exiting + +#################################################################################################### +# This function checks real time for ALL FW related parameters +# +#################################################################################################### +def fw_info(slice=[0,1],print_en=True): + global gFwFileName + global gFwFileNameLastLoaded + try: + gFwFileNameLastLoaded + except NameError: + fw_bin_filename = 'FW_FILENAME_UNKNOWN' + else: + fw_bin_filename = gFwFileNameLastLoaded + + slices = get_slice_list(slice) + for slc in slices: + sel_slice(slc) + magic_code = fw_magic(print_en=0) # Expected FW magic word = 0x6A6A + ver_code = fw_ver(print_en=0) # + hash_code = fw_hash(print_en=0) + crc_code = fw_crc(print_en=0) + date_code = fw_date(print_en=0) + d=datetime.date(1970, 1, 1) + datetime.timedelta(date_code) + + ver_str = "VER_%02d.%02d.%02d" %(ver_code>>16&0xFF,ver_code>>8&0xFF,ver_code&0xFF) + date_str = "DATE_%04d%02d%02d"%(d.year, d.month, d.day) + hash_str = "HASH_0x%06X" %(hash_code) + crc_str = "CRC_0x%04X" %(crc_code) + magic_str = "MAGIC_0x%04X" %(magic_code) + + if print_en: + if hash_code==0 or hash_code==0xFFFFFF: # A quick check for zero value + print("\n...Slice %d has no FW Loaded!"%slc), + else: + print("\n...Slice %d FW Info:"%(slc)) + print("'%s'," %(fw_bin_filename)) + print("%s," %(ver_str)) + print("%s," % (date_str)) + print("%s," %(hash_str)) + print("%s," %(crc_str)) + print("%s" %(magic_str)) + + if not print_en: + return fw_bin_filename, ver_str, date_str, hash_str, crc_str, magic_str +#################################################################################################### +# This function reads MAGIC WORD if a valid FW already loaded in Serdes +# +#################################################################################################### +def fw_magic(print_en=1): + magic_word = rreg(Pam4Reg.fw_load_magic_word_addr) # reading back FW MAGIC Code + if (magic_word == Pam4Reg.fw_load_magic_word): + if print_en==1: print("\n...FW Magic Word : 0x%04X (Download Successful)\n" % magic_word), + return magic_word + else: + if print_en==1: print("\n...FW Magic Word : 0x%04X (INVALID!!! Expected: 0x%04X)\n" % (magic_word, Pam4Reg.fw_load_magic_word)), + return 0 + #return magic_word +#################################################################################################### +# This function reads SerDes Chips Revision version number for the FW already loaded in Serdes +# +# This routine check for Chip Revsion ID using know register and value +# If ID in efuse is supported, it also read efuse ID +# +# Returns: 1.0 for rev A0 +# 1.1 for rev A1 +# 1.2 for rev A2 +# 2.0 for rev B0 +# 2.1 for rev B1 +# 3.0 for rev C0 +# +#################################################################################################### +def chip_rev(print_en=0): + rev_id_addr = [0x91,[15,0]] + + rev_id_reg_val = rreg(rev_id_addr,lane=8) # readback chip rev regsiter + + if rev_id_reg_val == 0x0100: + rev_id = 2.0 + if print_en==1: print("\n...Credo Silicon Revision : B0"), + elif rev_id_reg_val == 0x0000: + rev_id = 1.0 + if print_en==1: print("\n...Credo Silicon Revision : A0"), + else: + rev_id = -1.0 + if print_en==1: print("\n...Credo Silicon Revision Invalid ==> (%04X)\n" %(rev_id_reg_val)), + + return rev_id +#################################################################################################### +# This function reads FW version number for the FW already loaded in Serdes +# +# This routine check for FW version support. +# Earlier FW did not support version command (0xF003) and return the same +# value for date_code and ver_code. +# +#################################################################################################### +def fw_ver(print_en=1): + #date_code = fw_date(print_en=0) # readback date code (cmd = 0xF002). + # wreg(Pam4Reg.fw_ver_word_lo_addr, 0x0000) # clear readback-low value first before gets updated by next cmd + # wreg(Pam4Reg.fw_ver_word_hi_addr, 0x0000) # clear readback-high value first before gets updated by next cmd + wreg(Pam4Reg.fw_ver_read_en_addr, Pam4Reg.fw_ver_read_en) # enable reading back FW VERSION code + # cnt=0 + # while(rreg(Pam4Reg.fw_ver_read_en_addr)& Pam4Reg.fw_ver_read_status != Pam4Reg.fw_ver_read_status): + # cnt+=1 + # if (cnt > 100): break + # pass + high_word = rreg(Pam4Reg.fw_ver_word_hi_addr) # upper byte + low_word = rreg(Pam4Reg.fw_ver_word_lo_addr) # lower word + ver_code = (high_word <<16) + low_word + + # if date_code == low_word: # if this is an older FW version that didn't support version command 0xF003. put month/day of date as version number + # d=datetime.date(1970, 1, 1) + datetime.timedelta(date_code) + # ver_code = ((d.month)<<8) + d.day + # if print_en==1: print("\n...FW Version : %02d.%02d.%02d\n" %(ver_code>>16&0xFF,ver_code>>8&0xFF,ver_code&0xFF)) + # else: # if this is a FW that support version command 0xF003. get the actual FW version + if print_en==1: print("\n...FW Version : %02d.%02d.%02d\n" %(ver_code>>16&0xFF,ver_code>>8&0xFF,ver_code&0xFF)) + + return ver_code +#################################################################################################### +# This function reads HASH CODE for the FW already loaded in Serdes +# +#################################################################################################### +def fw_hash(print_en=1): + wreg(Pam4Reg.fw_hash_word_lo_addr, 0x0000) # clear readback value first before gets updated by next cmd + wreg(Pam4Reg.fw_hash_read_en_addr, Pam4Reg.fw_hash_read_en) # enable reading back FW HASH code + cnt=0 + while(rreg(Pam4Reg.fw_hash_read_en_addr)& Pam4Reg.fw_hash_read_status != Pam4Reg.fw_hash_read_status): + cnt+=1 + if (cnt > 100): break + #pass + high_word = rreg(Pam4Reg.fw_hash_word_hi_addr) # upper byte + low_word = rreg(Pam4Reg.fw_hash_word_lo_addr) # lower word + hash_code = (high_word <<16) + low_word + if print_en==1: print("\n...FW Hash Code : 0x%06X\n" %(hash_code)), + return hash_code +#################################################################################################### +# This function reads CRC CODE for the FW already loaded in Serdes +# +#################################################################################################### +def fw_crc(print_en=1): + wreg(Pam4Reg.fw_crc_word_addr, 0x0000) # clear readback value first before gets updated by next cmd + wreg(Pam4Reg.fw_crc_read_en_addr, Pam4Reg.fw_crc_read_en) # Enable reading back FW CRC Code + time.sleep(.01) + checksum_code = rreg(Pam4Reg.fw_crc_word_addr) + if print_en==1: print("\n...FW CRC Code : 0x%04X\n" %(checksum_code)) , + return checksum_code +#################################################################################################### +# This function Calculates CRC CODE for the Code+ReadOnly Section of the FW in Memory +# +#################################################################################################### +def fw_crc_calc(print_en=1): + wreg(0x9806, 0xA0F0) # Enable reading back FW CRC Code + time.sleep(.1) + + for i in range(1000): + checksum_cmd_status = rreg(0x9806) # wait for 0x0A01 indicating command done + if checksum_cmd_status==0x0A01: # ==0x0A01 + break + + if checksum_cmd_status != 0x0A01: + checksum_code=-1 + if print_en==1: print("\n...CRC Calc for Code+ReadOnly Execution Failed. Expected: 0x0A01, Actual: 0x%04X\n" %(checksum_cmd_status)) , + else: + checksum_code = rreg(0x9807) + if print_en==1: print("\n...CRC Calc for Code+ReadOnly Memory: 0x%04X\n" %(checksum_code)), + return checksum_code +#################################################################################################### +# This function reads DATE CODE for the FW already loaded in Serdes +# +#################################################################################################### +def fw_date(print_en=1): + wreg(Pam4Reg.fw_date_word_addr, 0x0000) # clear readback value first before gets updated by next cmd + wreg(Pam4Reg.fw_date_read_en_addr, Pam4Reg.fw_date_read_en) # Enable Reading back FW Date Code + time.sleep(.01) + datecode = rreg(Pam4Reg.fw_date_word_addr) + d=datetime.date(1970, 1, 1) + datetime.timedelta(datecode) + + if print_en==1: print ("\n...FW Date Code : %04d-%02d-%02d\n" % (d.year, d.month, d.day)) + return datecode +#################################################################################################### +# This function reads WATCHDOG Counter value +# +# The watchdog timer is incremented only by the FW, if FW is loaded in Serdes +# +#################################################################################################### +def fw_watchdog(count=None): + if count != None: + wreg(Pam4Reg.fw_watchdog_timer_addr,0x0000) # clear the counter if asked + + watchdog_count = rreg(Pam4Reg.fw_watchdog_timer_addr) + return watchdog_count + +fw_tick=fw_watchdog + +#################################################################################################### +# This function checks if a FW is loaded +# +# Returns 0: if FW is not loaded +# Returns 1: if FW is loaded +# +#################################################################################################### +def fw_loaded(print_en=1): + val0 = fw_hash(print_en=0) # check the hash code to see if it valid counter to see if FW is incrementing it + if val0==0 or val0==0xFFFFFF: # A quick check for zero value + fw_loaded_stat=0 # hash code counter is zero, FW is not loaded + if print_en==1: print("\n...Slice %d has no FW Loaded!"%gSlice) + else: + fw_loaded_stat=1 # hash code is not zero, a FW not loaded + if print_en==1: + print("\n...Slice %d has FW Loaded" %(gSlice)), + print (fw_info(slice=gSlice, print_en=0)) + + return fw_loaded_stat +#################################################################################################### +# This function checks if a FW is loaded and is running? +# +# Returns 0: if FW is not running or not loaded +# Returns 1: if FW is running +# +#################################################################################################### +def fw_running(): + val0 = fw_watchdog() # check the watchdog counter to see if FW is incrementing it + if val0==0: # A quick check for zero value + fw_running_stat=0 # watchdog counter is zero, FW is not loaded + else: + time.sleep(1.8) # wait more than one second + val1 = fw_watchdog() # check the watchdog counter once more + if val1 > val0: # watchdog counter is moving, then FW is loaded and running + #wreg(fw_load_magic_word_addr, fw_load_magic_word) # if FW is loaded but magic word is corrupted, correct it + fw_running_stat=1 # watchdog counter is moving, then FW is loaded and running + else: + fw_running_stat=0 # watchdog counter is not moving, then FW is not loaded or halted + fw_watchdog(0) # clear the counter so the next fw_running check goes faster + + return fw_running_stat +#################################################################################################### +# This function removes any FW already loaded in Serdes +# +#################################################################################################### +def fw_unload(print_en=1,slice=None): + slices = get_slice_list(slice) + for slc in slices: + sel_slice(slc) + wreg(Pam4Reg.fw_unload_addr, Pam4Reg.fw_unload_word) # Enable Unloading the FW from Slice + cpu_reset() # Need to reset CPU + time.sleep(0.1) + #wreg(Pam4Reg.fw_unload_addr, 0) # Clear the Unload register after cpu reset + fw_unload_status = rreg(Pam4Reg.fw_unload_addr) # Read and check to make sure Boot ROM register is cleared after cpu reset + if fw_unload_status != 0: + if print_en: print("\n*** Slice %d FW Unload FAILED or CPU Not Running! ***"%slc) + #result = False + else: + for ln in range(len(lane_name_list)): + for core in [Pam4Reg, NrzReg]: + wreg(core.rx_bp1_st_addr, 0, ln) + wreg(core.rx_bp1_en_addr, 0, ln) + wreg(core.rx_sm_cont_addr, 0, ln) + time.sleep(0.001) + wreg(core.rx_sm_cont_addr, 1, ln) + if print_en: print("\n...Slice %d FW Unloaded Successfully"%slc), + +#################################################################################################### +def fw_cmd(cmd): + wreg(c.fw_cmd_addr, cmd) # fw_cmd_addr = 0x9806 + for i in range(1000): + result=rreg(c.fw_cmd_addr) # fw_cmd_addr = 0x9806 + if result!=cmd: # ==0x800 or result==0xb00: + break + if result == 0x302: + result=-1 + #print("\n*** fw_cmd %04x Failed. Return Status = 0x%04X" %(cmd, result)) + #print("\n*** FW Command %04x failed. is firmware loaded?" % cmd) + return result + +#################################################################################################### +# Get FW Debug Information +#################################################################################################### +def fw_debug_info(section=2, index=2,lane=None): + lanes = get_lane_list(lane) + result = {} + #timeout=0.2 + for ln in lanes: + result[ln] = fw_debug_cmd(section, index, ln) + + return result +#################################################################################################### +# Get FW Debug Information +#################################################################################################### +def fw_debug(section=None, index=None,lane=None): + + if section is None: sections=[2] + if type(section)==int: sections=[section] + elif type(section)==list: sections=section + + if index is None: indices=[2] + if type(index)==int: indices=[index] + elif type(index)==list: indices=index + + lanes = get_lane_list(lane) + result = {} + #timeout=0.2 + for sec in sections: + for idx in indices: + for ln in lanes: + result[ln].append(fw_debug_cmd(sec, idx, ln)) + + return result +#################################################################################################### +# Get FW Debug Information +#################################################################################################### +def fw_debug_cmd(section=2, index=7, lane=0): + #timeout=0.2 + result=0 + cmd = 0xB000 + ((section&0xf)<<4) + lane + wreg(c.fw_cmd_detail_addr, index,lane) # fw_cmd_detail_addr = 0x9807 + status = fw_cmd(cmd) # fw_cmd_addr = 0x9806 + if(status!=0x0b00+section): + #print("FW Debug CMD Section %d, Index %d, for Lane %s failed with code 0x%04x" %(section, index, lane_name_list[lane],status)) + result = -1 + else: + result = rreg(c.fw_cmd_detail_addr,lane) # fw_cmd_detail_addr = 0x9807 + + return result +#################################################################################################### +# Get FW config Information +#################################################################################################### +def fw_config_cmd(config_cmd=0x8090,config_detail=0x0000): + wreg(c.fw_cmd_detail_addr, config_detail) # fw_cmd_detail_addr = 0x9807 + status = fw_cmd(config_cmd) # fw_cmd_addr = 0x9806 + if(status==0x302): # Retry sending config command one more time + #print("FW Config CMD 0x%04X, Config Detail: 0x%04X, Failed with Status 0x%04X. RETRYING..."%(config_cmd, config_detail ,status)) + status = fw_cmd(config_cmd) # fw_cmd_addr = 0x9806 + + if(status==0x302): # Failed again on the second retry + status=-1 + #print("FW Config CMD 0x%04X, Config Detail: 0x%04X, Failed with Status 0x%04X. AFTER RETRY"%(config_cmd, config_detail ,status)) + + + return status +#################################################################################################### +# +# lane_reset fully managed by FW +#################################################################################################### +def fw_lane_reset (lane=None): + + # if not fw_loaded(print_en=0): + # print("\n*** No FW Loaded. Skipping fw_lane_reset().\n") + # return + + fw_lane_reset_cmd = 0xA000 + lanes = get_lane_list(lane) + + for ln in lanes: + fw_config_cmd(config_cmd=fw_lane_reset_cmd+ln,config_detail=0x0000) + + global gLaneStats #lane statistics, used in rx_monitor() + for ln in lanes: gLaneStats[gSlice][ln][3]=0 +#################################################################################################### +# +# lane_reset by toggling HW bit (but when FW is loaded) +#################################################################################################### +def hw_lane_reset(lane=None): + + lanes = get_lane_list(lane) + get_lane_mode(lanes) # update the Encoding modes of all lanes for this Slice + + for ln in lanes: + c = Pam4Reg if gEncodingMode[gSlice][ln][0].upper() == 'PAM4' else NrzReg # Lane is in PAM4 or NRZ mode? + wreg(c.rx_lane_rst_addr, 0x1, ln) + time.sleep(.050) + for ln in lanes: + c = Pam4Reg if gEncodingMode[gSlice][ln][0].upper() == 'PAM4' else NrzReg # Lane is in PAM4 or NRZ mode? + wreg(c.rx_lane_rst_addr, 0x0, ln) + time.sleep(.050) + + global gLaneStats #lane statistics, used in rx_monitor() + for ln in lanes: gLaneStats[gSlice][ln][3]=0 + +#################################################################################################### +# +# lane_reset fully managed by SDK on HW State Machine (used only when FW is NOT loaded) +#################################################################################################### +def hw_lane_reset_no_fw(lane=None): + + lanes = get_lane_list(lane) + get_lane_mode(lanes) # update the Encoding modes of all lanes for this Slice + + for lane in lanes: + if gEncodingMode[gSlice][lane][0] == 'pam4': # Lane is in PAM4 mode + c=Pam4Reg + + #print"\nSlice %d Lane %s (PAM4) is Reset"%(gSlice,lane_name_list[lane]), + #wreg(0x002,0xc000,lane) # final cntr target + super_cal = rreg(c.rx_mu_ow_addr,lane) + if super_cal != 0: + wreg(c.rx_mu_owen_addr,1,lane) # super-cal disable + wreg(c.rx_mu_ow_addr,0,lane) # super-cal disable + updn = rreg(c.rx_theta_update_mode_addr,lane) + if updn != 0: + wreg(c.rx_theta_update_mode_addr, 0, lane) + blc = rreg([0x07b,[8,6]],lane) # BLC? + wreg([0x07b,[8,6]],0,lane) # BLC off + wreg(c.rx_theta_update_mode_addr,0,lane) # up/dn mode disable - rajan + + wreg(c.rx_lane_rst_addr, 0x1, lane) + time.sleep(.050) + wreg(c.rx_lane_rst_addr, 0x0, lane) + + # Before exiting Lane Reset, Restore parameters + if updn != 0: wreg(c.rx_theta_update_mode_addr,updn,lane) # up/dn mode enable - rajan + wreg(c.rx_mu_owen_addr,1,lane) # super-cal enable + if super_cal != 0: wreg(c.rx_mu_ow_addr,super_cal,lane) # super-cal enable + wreg([0x07b,[8,6]],blc,lane) # BLC restored + + else: # Lane is in NRZ mode + c=NrzReg + #print"\nSlice %d Lane %s (NRZ) is Reset"%(gSlice,lane_name_list[lane]), + wreg([0x07b,[8,6]],0,lane) # BLC off + wreg(c.rx_cntr_target_addr, 0x100, lane) + wreg(c.rx_lane_rst_addr, 0x1, lane) + time.sleep(.050) + wreg(c.rx_lane_rst_addr, 0x0, lane) + wreg(c.rx_cntr_target_addr, 0x002, lane) + + # Clear lane statistics, used in rx_monitor() + #rx_monitor_clear(lane=lanes,fec_thresh=fec_thresh) + global gLaneStats #lane statistics, used in rx_monitor() + for ln in lanes: gLaneStats[gSlice][ln][3]=0 + +#################################################################################################### +def lane_reset (lane=None): + + if (not fw_loaded(print_en=0)) or (fw_reg_rd(128)==0): # FW not loaded or loaded but halted + #lane_reset_method = 'sw_manage_lane_reset_with_no_fw' + hw_lane_reset_no_fw(lane=lane) + else: # FW loaded and running + if fw_date(print_en=0)<18268: # FW Date is older than 2020-01-07 + #lane_reset_method = 'sw_manage_lane_reset_with_fw' + hw_lane_reset (lane=lane) + else: # FW Date is on or after 2020-01-07 + l#ane_reset_method = 'fw_manage_lane_reset_fw_fully' + fw_lane_reset (lane=lane) + +#################################################################################################### +# +# lane_reset (used when FW is loaded) +#################################################################################################### +def lr(lane=None): + lane_reset(lane) + +#################################################################################################### +# +# Here is how to get a lane speed +# 1. For address 0x9807, write 0x0004 +# 2. For address 0x9806, write 0xB00x (x is the lane number, 0 to 0xF) +# 3. Read 0x9807 for return value. +# +# The return value would be 0x00~0x06. +# 0x00 -> ??? +# 0x01 -> 10G +# 0x02 -> 20G +# 0x03 -> 25G +# 0x04 -> 26G +# 0x05 -> 28G +# 0x06 -> ??? +# 0x07 -> ??? +# 0x08 -> 50G +# 0x09 -> 53G +# 0x0A -> 56G +# +#################################################################################################### +def fw_lane_speed(lane=None): + #[ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B ] + speed_list=['OFF','10G','20G','25G','26G','28G','53G','07?', '51G', '53G', '56G','0x0B?'] + mode_list =['off','nrz','nrz','nrz','nrz','nrz','pam4','07?','pam4','pam4','pam4','????'] + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + speed_index= fw_debug_cmd(section=0,index=4,lane=ln) + result[ln] = [mode_list[speed_index],speed_list[speed_index]] + #result[ln] = speed_index + return result +#################################################################################################### +# show current mode assigned to the lane by the FW +# +# index of the mode: +# 0: set_mode before opt +# 1: opt_mode +# +# mode: +# 0: lane in OFF +# 1: lane is in NRZ mode +# 2: lane is in PAM4 mode +#################################################################################################### +def fw_lane_mode (lane=None): + + lanes = get_lane_list(lane) + result = {} + # print current fw_modes of the lanes + #dbg_mode=0 + #dbg_cmd=c.fw_debug_info_cmd # 0xb000 + mode_list=['OFF','NRZ','PAM4'] + mode_idx=[0,1] + opt_status_list=['-','OPT'] + #opt_status_bit=[0,1] + + for ln in lanes: + for idx in range(2): # get both fw modes [0]:set_mode [1]: opt_mode + mode_idx[idx] = fw_debug_cmd(section=0, index=idx, lane=ln) # for index=1 ===> 0: OFF, 1: NRZ, 2: PAM4 + opt_status_bit = (rreg(c.fw_opt_done_addr) >> ln) & 0x0001 + result[ln] = (mode_list[mode_idx[0]], mode_list[mode_idx[1]], opt_status_list[opt_status_bit]) + return result +#################################################################################################### +# pause/restart FW in target lane(s) +# +# +#################################################################################################### +def fw_pause (fw_mode=None,lane=None, print_en=1): + + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. Skipping fw_pause() \n") + return + + top_fw_addr = 9 + serdes_fw_addr = 8 + tracking_fw_addr = 128 + ffe_fw_addr = 115 + + off_list = ['OFF','DIS','PAUSE','STOP'] + mode_list= ['off','ON'] + + lanes = get_lane_list(lane) + result = {} + + if fw_mode!=None: # Write FW Registers to pause/restart FW + en = 0 if any(i in fw_mode.upper() for i in off_list ) else 1 + if print_en: + if en==0: + print ("\n...PAUSED FW on Lanes: " + str(lanes)) + else: + print ("\n...Restarted FW on Lanes: " + str(lanes)) + + for ln in lanes: + val1=fw_reg(addr=top_fw_addr, print_en=0)[top_fw_addr ] + val2=fw_reg(addr=serdes_fw_addr,print_en=0)[serdes_fw_addr] + val3=fw_reg(addr=tracking_fw_addr, print_en=0)[tracking_fw_addr ] + val4=fw_reg(addr=ffe_fw_addr, print_en=0)[ffe_fw_addr ] + + ####### Proper sequence to Pause FW + if en==0: + ### Pause Top FW + if any(i in fw_mode.upper() for i in ['TOP','ALL']): + val = (val1 & ~(1<>ln) & 1 + status2=(fw_reg(addr=serdes_fw_addr,print_en=0)[serdes_fw_addr]>>ln) & 1 + status3=(fw_reg(addr=tracking_fw_addr, print_en=0)[tracking_fw_addr ]>>ln) & 1 + status4=(fw_reg(addr=ffe_fw_addr, print_en=0)[ffe_fw_addr ]>>ln) & 1 + result[ln]=status1,status2,status3,status4 + + ### Print FW Pause/Active Status for all lanes + if print_en: + print("\n------------------------"), + print(" FW Pause/Off or Active/ON Status Per Lane"), + print(" ------------------------"), + print("\n... Lane:"), + for ln in range(16): + print(" %3s" %(lane_name_list[ln])), + + print("\n... Top FW:"), + for ln in range(16): + print(" %3s" %(mode_list[result[ln][0]])), + print("\n... Serdes FW:"), + for ln in range(16): + print(" %3s" %(mode_list[result[ln][1]])), + print("\n...Tracking FW:"), + for ln in range(16): + print(" %3s" %(mode_list[result[ln][2]])), + print("\n... FFE FW:"), + for ln in range(16): + print(" %3s" %(mode_list[~result[ln][3]])), + fw_reg(addr=[top_fw_addr,serdes_fw_addr,tracking_fw_addr,ffe_fw_addr]) + else: + return result +#################################################################################################### +# Use FW Command to Squelch or Unsquelch TX output +# +# +#################################################################################################### +def fw_tx_squelch(mode=None,lane=None, print_en=1): + + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. Skipping fw_tx_squelch().\n") + return + + squelch_en_cmd = 0x7011 + squelch_dis_cmd = 0x7010 + squelch_status_addr = 0x98cd + hw_tx_control_addr = 0xA0 + + squelch_en_list = ['ON','EN','SQ','SQUELCH'] + squelch_dis_list = ['OFF','DIS','UNSQ','UNSQUELCH'] + mode_list= ['dis','EN'] + + lanes = get_lane_list(lane) + result = {} + + if print_en: print("\n-----------------------------"), + if print_en: print(" FW TX Squelch/En or Unsquelch/Dis Status Per Lane"), + if print_en: print(" -----------------------------"), + if print_en: print("\n Lane:"), + if print_en: + for ln in range(16): + print(" %4s" %(lane_name_list[ln])), + + if mode!=None: # Write FW Commands + for ln in lanes: + if any(i in mode.upper() for i in squelch_en_list): + val = 1<>ln) & 1 + status2=rreg(addr=hw_tx_control_addr,lane=ln) + result[ln]=status1,status2 + + if print_en: # Print Status + print("\n FW TX Squelch :"), + for ln in range(16): + print(" %4s" %(mode_list[result[ln][0]])), + print("\n HW TX Reg 0xA0:"), + for ln in range(16): + print(" %04X" %(result[ln][1])), + else: + return result +############################################################################## +# Use FW Command to Configure a lane in Optic Mode +# +# +############################################################################## +def fw_optic_mode(mode=None,lane=None, print_en=1): + + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. Skipping fw_tx_squelch().\n") + return + + optic_fw_reg_addr = 20 + optic_mode_reg_val = fw_reg_rd(optic_fw_reg_addr) + + optic_en_list = ['ON','EN','OPTIC'] + optic_dis_list = ['OFF','DIS','COPPER'] + mode_list= ['dis','EN'] + + lanes = get_lane_list(lane) + result = {} + + if print_en: print("\n-----------------------------------"), + if print_en: print(" FW Optic Mode Status Per Lane"), + if print_en: print(" -----------------------------------"), + if print_en: print("\n Lane:"), + if print_en: + for ln in range(16): + print(" %4s" %(lane_name_list[ln])), + + + if mode!=None: # Write FW Commands + for ln in lanes: + if any(i in mode.upper() for i in optic_en_list): + optic_mode_reg_val = (optic_mode_reg_val | (1<> ln) & 1 + result[ln]=lane_optic_mode + + if print_en: # Print Status + print("\n FW Optic Mode :"), + for ln in range(16): + print(" %4s" %(mode_list[result[ln]])), + else: + return result +############################################################################## +# wait until all lanes are done with FW-based RX ADAPTATION +# +# Status of all lanes RX and FECs set up as gearbox: +# 0: lane's RX adaptation not done or incomplete +# 1: lane's RX adaptation complete +############################################################################## +def fw_gearbox_wait (max_wait=2000, print_en=0): + + fec_b_bypass = True if rreg([0x9857,[7,4]])==0 else False + start_time=time.time() + + cnt=1 + gearbox_done=0 + final_state_count=0 + final_gearbox_state = 6 if fec_b_bypass==True else 12 # When FECB Bypassed, final Gearbox FW State = 6, else 12 + if print_en: print("\n...Waiting for FEC Locks (fec_wait=%d) "%(fw_reg_rd(14))), + while ( not gearbox_done ): + if print_en: print("\b\b\b\b\b\b%4.1fs"%(time.time()-start_time)), + if print_en: print("\n%4.1fs"%(time.time()-start_time)), + cnt+=1 + time.sleep(.1) + gb_state0 = fw_debug_cmd(section=3,index=0, lane=0) + gb_state2 = fw_debug_cmd(section=3,index=0, lane=2) + gb_state8 = fw_debug_cmd(section=3,index=0, lane=8) + gb_state12 = fw_debug_cmd(section=3,index=0, lane=12) + + if print_en: + # tx_output_a0 = hex(rreg(0xa0, 0)) + # tx_output_a2 = hex(rreg(0xa0, 2)) + # tx_output_b0 = hex(rreg(0xa0, 8)) + # tx_output_b4 = hex(rreg(0xa0,12)) + fec_stat, fec_counts = fec_status(print_en=0) + adapt_stat = hex(rreg(0x98c9)) + reg1=hex(rreg(0x4880));reg2=hex(rreg(0x4a80));reg3=hex(rreg(0x5880));reg4=hex(rreg(0x5a80)) + #print gb_state0,gb_state2,gb_state8,gb_state12, tx_output_a0, tx_output_a2, tx_output_b0, tx_output_b4, adapt_stat, reg1,reg2,reg3,reg4, fec_stat, + if print_en: print (gb_state0,gb_state2,gb_state8,gb_state12, adapt_stat, reg1,reg2,reg3,reg4, fec_stat) + + if gb_state0==final_gearbox_state and gb_state2==final_gearbox_state and gb_state8==final_gearbox_state and gb_state12==final_gearbox_state: + if final_state_count<3: + final_state_count+=1 + else: + gearbox_done=1 + if cnt>max_wait : + gearbox_done=1 + #fec_status() + if print_en: print("...Done!\n") + + global gFecStatusPrevTimeStamp + global gFecStatusCurrTimeStamp + gFecStatusPrevTimeStamp[gSlice] = time.time() + gFecStatusCurrTimeStamp[gSlice] = time.time() + + return gearbox_done +#################################################################################################### +# wait until all lanes are done with FW-based RX ADAPTATION +# +# Status of all lanes RX and FECs set up as gearbox: +# 0: lane's RX adaptation not done or incomplete +# 1: lane's RX adaptation complete +#################################################################################################### +def fw_gearbox_wait_orig (max_wait=None, lane=None, print_en=1): + + lanes = get_lane_list(lane) + start=time.time() + adapt_done_total_prev = 0 + adapt_done_total = 0 + adapt_done_lane_prev = [0]*16 + adapt_done_lane_curr = [0]*16 + + if max_wait is None: + maxWait = 30 + else: + maxWait = max_wait + + if(print_en==1): + print("\n...Slice %d Lanes %d-%d RX Adaptation In Progress. . . \n"%(gSlice,lanes[0],lanes[-1])) + for ln in lanes: + print("%2s" %(lane_name_list[ln]) ), + + if(print_en==2): print("\n...Slice %d Lanes %d-%d RX Adaptation In Progress. . ."%(gSlice,lanes[0],lanes[-1])), + + while adapt_done_total < len(lanes): + if(print_en==1): print("") + if(print_en==2): print("."), + adapt_done_total=0 + for ln in lanes: + adapt_done_lane_curr[ln] = (rreg(c.fw_opt_done_addr) >> ln) & 1 + adapt_done_total += adapt_done_lane_curr[ln] + if(print_en==2 and adapt_done_total_prev==0 and adapt_done_total>0): + print("\n"), + if(print_en==2 and adapt_done_lane_curr[ln]==1 and adapt_done_lane_prev[ln]==0 ): + print("%s"%(lane_name_list[ln])), + if(print_en==1): + print("%2d" %(adapt_done_lane_curr[ln]) ), + adapt_done_lane_prev[ln] = adapt_done_lane_curr[ln] + adapt_done_total_prev += adapt_done_total + + t2 = time.time() - start + if(print_en==1): print(" %2.2fs"%t2), + if (t2 > maxWait ): + break + + time.sleep(.1) + + if(print_en==1): + print ("") + for ln in lanes: + print("%2s" %(lane_name_list[ln]) ), + print ("\n") + + adapt_done_all = 1 if adapt_done_total==len(lanes) else 0 + + return [adapt_done_all, t2] + + + +#################################################################################################### +# wait until all lnaes are done with FW-based RX ADAPTATION +# +# Status of each lane: +# 0: lane's RX adaptation not done or incomplete +# 1: lane's RX adaptation complete +#################################################################################################### +def fw_config_wait (max_wait=None, lane=None, print_en=1): + + lanes = get_lane_list(lane) + config_done_this_lane = [0]*16 + config_done_all_lanes=0 + + if max_wait is None: + maxWait = 3.0 + # if any of the lanes is PAM4 mode, set the max wait to 20 seconds, otherwise 3 seconds max + for ln in lanes: + #lane_speed_index = fw_debug_cmd(section=0, index=4, lane=ln) + curr_fw_lane_mode = fw_lane_mode (ln) + if any('PAM4' in s for s in curr_fw_lane_mode[ln]): maxWait =8 + else: + maxWait = max_wait + + start=time.time() + while config_done_all_lanes < len(lanes): + config_done_all_lanes=0 + for ln in lanes: + config_code_this_lane= fw_debug_cmd(section=0, index=38, lane=ln) + ### Config is GB, BM or Retimer but not PHY mode + if config_code_this_lane<0xA0: + config_done_this_lane[ln] = (fw_debug_cmd(section=0, index=40, lane=ln) >> ln) & 1 + #### Config is PHY Mode. Get its status register 0x98c9 + else: + config_done_this_lane[ln] = (rreg(c.fw_opt_done_addr) >> ln) & 1 + + config_done_all_lanes += config_done_this_lane[ln] + t2 = time.time() - start + if (t2 > maxWait ): + break + time.sleep(.1) + + config_done_all = 1 if config_done_all_lanes==len(lanes) else 0 + + return [config_done_all, t2] + +#################################################################################################### +# wait until all lnaes are done with FW-based RX ADAPTATION +# +# Status of each lane: +# 0: lane's RX adaptation not done or incomplete +# 1: lane's RX adaptation complete +#################################################################################################### +def fw_adapt_wait (max_wait=None, lane=None, print_en=1): + + lanes = get_lane_list(lane) + start=time.time() + adapt_done_total_prev = 0 + adapt_done_total = 0 + adapt_done_reg=0 + adapt_done_reg_prev=0 + adapt_done_lane_prev = [0]*16 + adapt_done_lane_curr = [0]*16 + + if max_wait is None: + maxWait = 3.0 + # if any of the lanes is PAM4 mode, set the max wait to 20 seconds, otherwise 3 seconds max + for ln in lanes: + curr_fw_lane_mode = fw_lane_mode (ln) + if any('PAM4' in s for s in curr_fw_lane_mode[ln]): maxWait =8 + else: + maxWait = max_wait + + if(print_en==1): + print("\n...Slice %d Lanes %d-%d RX Adaptation In Progress... \n"%(gSlice,lanes[0],lanes[-1])) + print(" "), + for ln in lanes: + print("%2s" %(lane_name_list[ln]) ), + print("") + if(print_en==2): print("\n...Slice %d Lanes %d-%d RX Adaptation In Progress..."%(gSlice,lanes[0],lanes[-1])), + + while adapt_done_total < len(lanes): + adapt_done_reg_prev = adapt_done_reg + adapt_done_reg = rreg(c.fw_opt_done_addr) + if(print_en==1): + print(" "), + if(print_en==2): + print("\b."), + adapt_done_total=0 + for ln in lanes: + adapt_done_lane_curr[ln] = (adapt_done_reg >> ln) & 1 + adapt_done_total += adapt_done_lane_curr[ln] + if(print_en==2 and adapt_done_total_prev==0 and adapt_done_total>0): + print("\r...Slice %d Lanes %d-%d RX Adaptation In Progress..."%(gSlice,lanes[0],lanes[-1])), + if(print_en==2 and adapt_done_lane_curr[ln]==1 and adapt_done_lane_prev[ln]==0 ): + print("\b%s."%(lane_name_list[ln])), + if(print_en==1): + print("%2d" %(adapt_done_lane_curr[ln]) ), + adapt_done_lane_prev[ln] = adapt_done_lane_curr[ln] + adapt_done_total_prev += adapt_done_total + + + t2 = time.time() - start + if(print_en==1): + print(" %4.1fs"%t2), + if(adapt_done_reg!=adapt_done_reg_prev): + print('\n'), # ERASE_LINE = '\x1b[2K, CURSOR_UP_ONE = '\x1b[1A' + else: + print('\r'), + if (t2 > maxWait ): + break + time.sleep(.1) + + if(print_en==1): + print(" "), + for ln in lanes: + print("%2s" %(lane_name_list[ln]) ), + print("\n"), + + adapt_done_all = 1 if adapt_done_total==len(lanes) else 0 + + return [adapt_done_all, t2] +#################################################################################################### +# wait until all Bitmux Config are done with FW-based BITMUX +# +# Status of each Bitmux: +# 0: lane's Bitmux Config not done or incomplete +# 1: lane's Bitmux Config complete +#################################################################################################### +def fw_bitmux_wait (lane=[0,1,2,3], max_wait=None, print_en=1): + + lanes = get_lane_list(lane) + b_lanes=[[8,9],[10,11],[12,13],[14,15],[12,13],[14,15]] + #print b_lanes + start=time.time() + bitmux_done_total = 0 + done_total_prev = 0 + done_total = 0 + + bitmux_tx_reg_lane_curr = [0]*16 + bitmux_done_lane_prev = [0]*16 + bitmux_state_lane_curr = [0]*16 + bitmux_done_lane_curr = [0]*16 + #adapt_done_lane_prev = [0]*16 + adapt_done_lane_curr = [0]*16 + + if max_wait is None: + maxWait = 10.0 + else: + maxWait = max_wait + + if(print_en!=0): + print("\n...Slice %d Lanes %d-%d Bitmux Config In Progress..."%(gSlice,lanes[0],lanes[-1])), + + if(print_en==1): + print("\n "), + for a_ln in lanes: + print("BM%d" %(a_ln) ), + print("%2s" %(lane_name_list[a_ln]) ), + for b_ln in b_lanes[a_ln]: + print("%2s" %(lane_name_list[b_ln]) ), + print(""), + print("") + + while bitmux_done_total < len(lanes): + if(print_en==1): + print(" "), + if(print_en==2): + print("\b."), + if(bitmux_done_total==0 ): + print("\b\b\b\b..."), + bitmux_done_total=0 + done_total=0 + + + for a_ln in lanes: + bitmux_tx_reg_lane_curr[a_ln] = rreg(0x0A0,lane=14) # get bitmux TX registers 0xA0 + bitmux_state_lane_curr[a_ln] = fw_debug_cmd(4, 0,a_ln) # get bitmux state number + bitmux_done_lane_curr[a_ln] = 1 if fw_debug_cmd(8, 99,a_ln)==1 else 0 # get bitmux done for this group + bitmux_done_total += bitmux_done_lane_curr[a_ln] + done_total += bitmux_done_lane_curr[a_ln] + + adapt_done_lane_curr[a_ln] = (rreg(c.fw_opt_done_addr) >> a_ln) & 1 # get adapt done for this group + done_total += adapt_done_lane_curr[a_ln] + + for b_ln in b_lanes[a_ln]: # get adapt done for this group + adapt_done_lane_curr[b_ln] = (rreg(c.fw_opt_done_addr) >> b_ln) & 1 + done_total += adapt_done_lane_curr[b_ln] + + if(print_en==1): + print("%d" %(bitmux_state_lane_curr[a_ln])), + print("%d" %(bitmux_done_lane_curr[a_ln])), + print("%2d" %(adapt_done_lane_curr[a_ln])), + #print("0x%04x" %(bitmux_tx_reg_lane_curr[a_ln])), + for b_ln in b_lanes[a_ln]: + print("%2d" %(adapt_done_lane_curr[b_ln]) ), + print(""), + if(print_en==2): + if(bitmux_done_lane_curr[a_ln]==1 and bitmux_done_lane_prev[a_ln]==0 ): + print("\b\bBM%d.."%(a_ln)), + bitmux_done_lane_prev[a_ln]=bitmux_done_lane_curr[a_ln] + + t2 = time.time() - start + if(print_en==1): + print(" %4.1fs"%t2), + if(done_total!=done_total_prev): + print('\n'), # ERASE_LINE = '\x1b[2K, CURSOR_UP_ONE = '\x1b[1A' + else: + print('\r'), + done_total_prev = done_total + if (t2 > maxWait ): + break + time.sleep(.01) + + if(print_en==1): + print(" "), + for a_ln in lanes: + print("BM%d" %(a_ln) ), + print("%2s" %(lane_name_list[a_ln]) ), + for b_ln in b_lanes[a_ln]: + print("%2s" %(lane_name_list[b_ln]) ), + print(""), + + bitmux_done_all = 1 if bitmux_done_total==len(lanes) else 0 + + return [bitmux_done_all, t2] +#################################################################################################### +# +# "Adaptation" counter for SerDes PHY. Rolls over at 0xFFFF. +# +#################################################################################################### +def fw_adapt_cnt(lane=None): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + if not fw_loaded(print_en=0): + result[ln] =-1 + continue + get_lane_mode(ln) + if gEncodingMode[gSlice][ln][0]=='pam4': # Lane is in PAM4 mode + result[ln] = fw_debug_cmd(section=2,index=7,lane=ln) + else: # Lane is in NRZ mode + result[ln] = fw_debug_cmd(section=1,index=10,lane=ln) + + return result +#################################################################################################### +# +# "Re-adaptation" counter for SerDes PHY. Clears on read, saturates to 0xFFFF. +# This increments with fw_adapt_cnt (FW does a lane-restart) +# +#################################################################################################### +def fw_readapt_cnt(lane=None): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + if not fw_loaded(print_en=0): + result[ln] =-1 + continue + get_lane_mode(ln) + result[ln] = fw_debug_cmd(section=8,index=1,lane=ln) + + return result +#################################################################################################### +# +# "Link lost" counter for SerDes PHY. Clears on read, saturates to 0xFFFF. +# +#################################################################################################### +def fw_link_lost_cnt(lane=None): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + if not fw_loaded(print_en=0): + result[ln] =-1 + continue + get_lane_mode(ln) + result[ln] = fw_debug_cmd(section=8,index=0,lane=ln) + + return result +#################################################################################################### +# +# "Gearbox FEC link lost" count, Clears on read, saturates to 0xFFFF. +# +#################################################################################################### +def fw_gearbox_lost_cnt(lane=None): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + if not fw_loaded(print_en=0): + result[ln] =-1 + continue + get_lane_mode(ln) + result[ln] = fw_debug_cmd(section=11,index=0,lane=ln) + return result +#################################################################################################### +# +# "Adaptation" counter for SerDes PHY. Rolls over at 0xFFFF. +# +#################################################################################################### +def fw_chan_est(lane=None): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + if not fw_loaded(print_en=0): + result[ln] =gChanEst[gSlice][ln] + continue + get_lane_mode(ln) + [lane_mode,lane_speed]=fw_lane_speed(ln)[ln] + sect = 2 if lane_mode.upper()=='PAM4' else 1 + chan_est =(fw_debug_info(section=sect, index=2,lane=ln)[ln]) / 256.0 + of = fw_debug_info(section=sect, index=4,lane=ln)[ln] + hf = fw_debug_info(section=sect, index=5,lane=ln)[ln] + gChanEst[gSlice][ln]=[chan_est,of,hf] + result[ln] = [chan_est,of,hf] + return result +#################################################################################################### +def fw_reg_rd(addr): + c = Pam4Reg + wreg(c.fw_cmd_detail_addr, addr,lane=0) # fw_cmd_detail_addr = 0x9807 + result=fw_cmd(0xe010) # fw_cmd_addr = 0x9806 + if result!=0x0e00: + print("\n*** FW Register read error, code=%04x" % result) + return rreg(c.fw_cmd_status_addr) # fw_cmd_status_addr = 0x98C7 + +#################################################################################################### +def fw_reg_wr(addr, data): + c = Pam4Reg + wreg(c.fw_cmd_detail_addr, addr,lane=0) # fw_cmd_detail_addr = 0x9807 + wreg(c.fw_cmd_status_addr, data,lane=0) # fw_cmd_status_addr = 0x98C7 + result=fw_cmd(0xe020) # fw_cmd_addr = 0x9806 + if result!=0x0e00: + print("\n*** FW Register write error, code=%04x" % result) + +#################################################################################################### +def fw_reg(addr=None, data=None, print_en=1): + + + if addr is None: + addr_list=range(201) # read all FW registers + data=None # Make sure not to write more than one address at a time. Just read FW registers and exit! + elif type(addr)==int: + addr_list=[addr] # read single FW register + elif type(addr)==list: + addr_list=addr # read list of FW registers + data=None # Make sure not to write more than one address at a time. Just read FW registers and exit! + + result = {} + c = Pam4Reg + + str="" + #### FW Reg Write if data-to-write is not given + if data!=None: + wreg(c.fw_cmd_detail_addr, addr_list[0],lane=0) # fw_cmd_detail_addr = 0x9807 + wreg(c.fw_cmd_status_addr, data,lane=0) # fw_cmd_status_addr = 0x98C7 + cmd_status=fw_cmd(0xe020) # fw_cmd_addr = 0x9806 + if cmd_status!=0x0e00: + print("\n*** FW Register write error: Addr %d Code=0x%04x" %(addr, cmd_status)) + return False + + line_separator= "\n#+-------------------------+" + title = "\n#+ FWReg | Value |" + str += line_separator + title + line_separator + #### FW Reg Read + for reg_addr in addr_list: + wreg(c.fw_cmd_detail_addr, reg_addr,lane=0) # fw_cmd_detail_addr = 0x9807 + cmd_status=fw_cmd(0xe010) # fw_cmd_addr = 0x9806 + if cmd_status!=0x0e00: + # Undefined FW register address or the read of a "defined" FW register failed + #print("\n*** FW Register read error: Addr %d Code=0x%04x" % (reg_addr,cmd_status)) + break + else: + result[reg_addr] = rreg(c.fw_cmd_status_addr) + str += ("\n#| %3d | 0x%04x (%-5d) |"%(reg_addr,result[reg_addr],result[reg_addr])) + + str += line_separator + if print_en == 1: + print (str) + else: + return result + +#################################################################################################### +# Instruct the FW to configure a lane (PHY) to a mode (and a speed) +# +# Options for 'mode': 'nrz' : NRZ 25G (25.78125Gbps) +# : 'pam4' : PAM4 53G (53.125 Gbps) +# +# : 'nrz-10G' : NRZ 10G (10.3125 Gbps) +# : 'nrz-20G' : NRZ 20G (20.6250 Gbps) +# : 'nrz-25G' : NRZ 25G (25.78125Gbps) +# : 'nrz-26G' : NRZ 26G (26.5625 Gbps) +# : 'nrz-28G' : NRZ 28G (28.125 Gbps) +# +# : 'pam4-51G' : PAM4 50G (51.5625 Gbps) +# : 'pam4-50G' : PAM4 53G (53.125 Gbps) +# : 'pam4-53G' : PAM4 53G (53.125 Gbps) +# : 'pam4-56G' : PAM4 56G (56.25 Gbps) +# +#################################################################################################### +def fw_config_lane (mode=None, datarate=None, lane=None): + + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. Skipping fw_config_lane().\n") + return + + lanes = get_lane_list(lane) + curr_fw_lane_mode = fw_lane_mode (lanes) # learn which mode (nrz/pam4/off) each lane is in now + + speed_str_list =['10','20','25','26','28','51','50','53','56'] # speed as part of mode argument + speed_code_list=[0x11,0x22,0x33,0x44,0x55,0x88,0x99,0x99,0xAA] # speed codes to be written to 0x9807[7:0] + + if mode is None: # no arguments? then just print current fw_modes of the lanes and exit + print ("") + for ln in lanes: + print(" %4s" %(lane_name_list[ln])), + for idx in [1,2]: # show both fw modes [0]:set_mode [1]: opt_mode [2]: adapt_done flag + print ("") + for ln in lanes: + print(" %4s"%curr_fw_lane_mode[ln][idx]), + else: # configure (either activate or turn off) the lanes + if 'NRZ' in mode.upper(): + mode_code_cmd = 0x80C0 # command to activate lane in NRZ + speed_code_cmd = 0x33 # default NRZ speed is 25G + if datarate!=None: mode=mode+str(int(round((datarate-1.0)/5.0)*5.0)) # add datarate to mode so we can find it in the speed codes + for i in range(len(speed_str_list)): # if NRZ speed is specified, take it + if speed_str_list[i] in mode: speed_code_cmd = speed_code_list[i] + + elif 'PAM4' in mode.upper(): + mode_code_cmd = 0x80D0 # command to activate lane in PAM4 + speed_code_cmd = 0x99 # default PAM4 speed is 53G + for i in range(len(speed_str_list)): # if PAM4 speed is specified, take it + if speed_str_list[i] in mode: speed_code_cmd = speed_code_list[i] + + elif 'OFF' in mode.upper(): # command to deactivate lane (Turn it OFF) + mode_code_cmd = 0x90D0 if(curr_fw_lane_mode[lanes[0]][1] == 'PAM4') else 0x90C0 + speed_code_cmd = 0x00 # For deactivating the lane, speed code does not matter + + else: + for ln in lanes: + print("\n***Slice %d Lane %s FW Config: selected mode is invalid => '%s'" %(gSlice,lane_name_list[ln],mode.upper())), + return + + ################ Destroy the target lanes before programming them to target mode + for ln in lanes: + off_cmd = 0x90D0 if(curr_fw_lane_mode[ln][1] == 'PAM4') else 0x90C0 + result=fw_config_cmd(config_cmd=off_cmd+ln,config_detail=0x0000) + #print("\n...Slice %d Lane %s FW freed up lane before reconfiguring it. (OffCode 0x%04X, Error Code 0x%04x)" %(gSlice,lane_name_list[ln],off_cmd+ln,result)), + if (result!=c.fw_config_lane_status): # fw_config_lane_status=0x800 + print("\n***Slice %d Lane %s: FW could not free up lane before reconfiguring it. (Error Code 0x%04x)" %(gSlice,lane_name_list[ln],result)), + + for ln in lanes: + wreg([0xa0,[15,11]],0x1d,ln) # '11101' Make sure TX output is not squelched + + ############# Now, configure the lane per user's target mode (either activate or deactivate) + for ln in lanes: + result=fw_config_cmd(config_cmd=mode_code_cmd+ln,config_detail=speed_code_cmd) + #print("\n...Slice %d Lane %s FW_CONFIG_LANE to Active Mode. (SpeedCode 0x9807=0x%04X, ActivateCode 0x9806=0x%04X, ExpectedStatus:0x%0X, ActualStatus=0x%04x)" %(gSlice,lane_name_list[ln],speed_code_cmd, mode_code_cmd+ln,c.fw_config_lane_status,result)), + if (result!=c.fw_config_lane_status): # fw_config_lane_status=0x800 + print("\n***Slice %d Lane %s FW_CONFIG_LANE to Active Mode Failed. (SpeedCode 0x9807=0x%04X, ActiveCode 0x9806=0x%04X, ExpectedStatus:0x%0X, ActualStatus=0x%04x)" %(gSlice,lane_name_list[ln],speed_code_cmd, mode_code_cmd+ln,c.fw_config_lane_status,result)), + + +#################################################################################################### +# FW to program Gearbox mode, A-side PAM4, B-side: NRZ +# +# +#################################################################################################### +def fw_config_gearbox_100G(A_lanes=[0,1], fec_b_byp=0): + + if not fw_loaded(print_en=0): + print("\n...FW Gearbox 100G-2 : FW not loaeded. Not executed!"), + return + + print_en=1 + #fec_reset() # reset all 8 FECs and clear their Align Markers + + # For 100G-2 Gearbox mode, 3 options supported for A-Lane groups + group0_100G=[0,1] # A_lanes group 1 -> [A0,A1] <-> [ 8, 9,10,11] + group1_100G=[2,3] # A_lanes group 2 -> [A2,A3] <-> [12,13,14,15] + group2_100G=[4,5] # A_lanes group 3 -> [A4,A5] <-> [12,13,14,15] + + #Determine the corresponding B-Lanes for each group of A-Lanes + B_lanes=[] + if all(elem in A_lanes for elem in group0_100G): # If A_lanes contains [0,1] + B_lanes+=[8,9,10,11] + if all(elem in A_lanes for elem in group1_100G): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + elif all(elem in A_lanes for elem in group2_100G): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + #else: + # print("\n*** 100G-2 Gearbox Setup: Invalid Target A-Lanes specified!\n") + # return + + lanes = sorted(list(set(A_lanes + B_lanes))) + prbs_mode_select(lane=lanes, prbs_mode='functional') + + if all(elem in A_lanes for elem in group0_100G): # If A_lanes contains [0,1] + fw_config_cmd(config_cmd=0x9090,config_detail=0x0000) # 0x9090 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group1_100G): # If A_lanes contains [2,3] + fw_config_cmd(config_cmd=0x9091,config_detail=0x0000) # 0x9091 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9092,config_detail=0x0000) # 0x9092 = First, FW destroy any instances of these lanes being already used + elif all(elem in A_lanes for elem in group2_100G): # If A_lanes contains [4,5] + fw_config_cmd(config_cmd=0x9092,config_detail=0x0000) # 0x9091 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9091,config_detail=0x0000) # 0x9092 = First, FW destroy any instances of these lanes being already used + + if all(elem in A_lanes for elem in group0_100G): # If A_lanes contains [0,1] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 100G-2: Lanes A0-A1 to B0-B3 with FEC_A0/FEC_B0..."), + fw_config_cmd(config_cmd=0x8090,config_detail=0x0000) # 0x8090 = FW Activate Gearbox 100G-2 for Lanes A0/A1 + else: + if print_en: print("\n...FW Gearbox 100G-2: Lanes A0-A1 to B0-B3 with FEC_A0 (FEC_B0 Bypassed)..."), + fw_config_cmd(config_cmd=0x8098,config_detail=0x0000) # no fec 0x8098 = FW Activate Gearbox 100G-2 for Lanes A0/A1 + if all(elem in A_lanes for elem in group1_100G): # If A_lanes contains [2,3] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 100G-2: Lanes A2-A3 to B4-B7 with FEC_A2/FEC_B2..."), + fw_config_cmd(config_cmd=0x8091,config_detail=0x0000) # 0x8091 = FW Activate Gearbox 100G-2 for Lanes A2/A3 + else: + if print_en: print("\n...FW Gearbox 100G-2: Lanes A2-A3 to B4-B7 with FEC_A2 (FEC_B2 Bypassed)..."), + fw_config_cmd(config_cmd=0x8099,config_detail=0x0000) # no fec 0x8099 = FW Activate Gearbox 100G-2 for Lanes A2/A3 + elif all(elem in A_lanes for elem in group2_100G): # If A_lanes contains [4,5] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 100G-2: Lanes A4-A5 to B4-B7 with FEC_A2/FEC_B2..."), + fw_config_cmd(config_cmd=0x8092,config_detail=0x0000)# 0x9092 = FW Activate Gearbox 100G-2 for Lanes A4/A5 + else: + if print_en: print("\n...FW Gearbox 100G-2: Lanes A4-A5 to B4-B7 with FEC_A2 (FEC_B2 Bypassed)..."), + fw_config_cmd(config_cmd=0x809A,config_detail=0x0000) # no fec 0x809A = FW Activate Gearbox 100G-2 for Lanes A4/A5 + + if print_en: print("Done!") + #fec_status() +############################################################################## +# FW to program Gearbox mode, A-side PAM4, B-side: NRZ +# +# +############################################################################## +def fw_config_gearbox_100G_LT(A_lanes=[0,1], fec_b_byp=0): + + if not fw_loaded(print_en=0): + print("\n...FW Gearbox 100G-2 to 25G NRZ_ANLT: FW not loaded. Not executed!"), + return + print_en=1 + #fec_reset() # reset all 8 FECs and clear their Align Markers + + # For 100G-2 Gearbox mode, 3 options supported for A-Lane groups + group0_100G=[0,1] # A_lanes group 1 -> [A0,A1] <-> [ 8, 9,10,11] + group1_100G=[2,3] # A_lanes group 2 -> [A2,A3] <-> [12,13,14,15] + group2_100G=[4,5] # A_lanes group 3 -> [A4,A5] <-> [12,13,14,15] + + #Determine the corresponding B-Lanes for each group of A-Lanes + B_lanes=[] + if all(elem in A_lanes for elem in group0_100G): # If A_lanes contains [0,1] + B_lanes+=[8,9,10,11] + if all(elem in A_lanes for elem in group1_100G): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + elif all(elem in A_lanes for elem in group2_100G): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + #else: + # print("\n*** 100G-2 Gearbox Setup: Invalid Target A-Lanes specified!\n") + # return + + lanes = sorted(list(set(A_lanes + B_lanes))) + prbs_mode_select(lane=lanes, prbs_mode='functional') + + if all(elem in A_lanes for elem in group0_100G): # If A_lanes contains [0,1] + fw_config_cmd(config_cmd=0x9090,config_detail=0x0000) # 0x9090 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group1_100G): # If A_lanes contains [2,3] + fw_config_cmd(config_cmd=0x9091,config_detail=0x0000) # 0x9091 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9092,config_detail=0x0000) # 0x9092 = First, FW destroy any instances of these lanes being already used + elif all(elem in A_lanes for elem in group2_100G): # If A_lanes contains [4,5] + fw_config_cmd(config_cmd=0x9092,config_detail=0x0000) # 0x9091 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9091,config_detail=0x0000) # 0x9092 = First, FW destroy any instances of these lanes being already used + + if all(elem in A_lanes for elem in group0_100G): # If A_lanes contains [0,1] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 100G-2 to 25G NRZ_ANLT: Lanes A0-A1 to B0-B3 with FEC_A0/FEC_B0..."), + fw_config_cmd(config_cmd=0x8090,config_detail=0x0200) # 0x8090 = FW Activate Gearbox 100G-2 for Lanes A0/A1 + else: + if print_en: print("\n...FW Gearbox 100G-2 to 25G NRZ_ANLT: Lanes A0-A1 to B0-B3 with FEC_A0 (FEC_B0 Bypassed)..."), + fw_config_cmd(config_cmd=0x8098,config_detail=0x0200) # no fec 0x8098 = FW Activate Gearbox 100G-2 for Lanes A0/A1 + if all(elem in A_lanes for elem in group1_100G): # If A_lanes contains [2,3] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 100G-2 to 25G NRZ_ANLT: Lanes A2-A3 to B4-B7 with FEC_A2/FEC_B2..."), + fw_config_cmd(config_cmd=0x8091,config_detail=0x0200) # 0x8091 = FW Activate Gearbox 100G-2 for Lanes A2/A3 + else: + if print_en: print("\n...FW Gearbox 100G-2 to 25G NRZ_ANLT: Lanes A2-A3 to B4-B7 with FEC_A2 (FEC_B2 Bypassed)..."), + fw_config_cmd(config_cmd=0x8099,config_detail=0x0200) # no fec 0x8099 = FW Activate Gearbox 100G-2 for Lanes A2/A3 + elif all(elem in A_lanes for elem in group2_100G): # If A_lanes contains [4,5] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 100G-2 to 25G NRZ_ANLT: Lanes A4-A5 to B4-B7 with FEC_A2/FEC_B2..."), + fw_config_cmd(config_cmd=0x8092,config_detail=0x0200)# 0x9092 = FW Activate Gearbox 100G-2 for Lanes A4/A5 + else: + if print_en: print("\n...FW Gearbox 100G-2 to 25G NRZ_ANLT: Lanes A4-A5 to B4-B7 with FEC_A2 (FEC_B2 Bypassed)..."), + fw_config_cmd(config_cmd=0x809A,config_detail=0x0200) # no fec 0x809A = FW Activate Gearbox 100G-2 for Lanes A4/A5 + + if print_en: print("Done!") + #fec_status() +def fw_config_gearbox_50G(A_lanes=[0,1,2,3], fec_b_byp=False): + + if not fw_loaded(print_en=0): + print("\n...FW Gearbox 50G-1 : FW is not loaded. Not executed!"), + return + + print_en=1 + + # For 50G-2 Gearbox mode, 3 options supported for A-Lane groups + group0_50G=[0] # A_lanes group 1 -> [A0] <-> [ 8, 9] + group1_50G=[1] # A_lanes group 2 -> [A1] <-> {10,11] + group2_50G=[2] # A_lanes group 3 -> [A2] <-> [12,13] + group3_50G=[3] # A_lanes group 4 -> [A3] <-> [14,15] + group4_50G=[4] # A_lanes group 4 -> [A4] <-> [12,13] + group5_50G=[5] # A_lanes group 5 -> [A5] <-> [14,15] + + #Determine the corresponding B-Lanes for each group of A-Lanes + B_lanes=[] + if all(elem in A_lanes for elem in group0_50G): # If A_lanes contains [0] + B_lanes+=[ 8, 9] + if all(elem in A_lanes for elem in group1_50G): # If A_lanes contains [1] + B_lanes+=[10,11] + if all(elem in A_lanes for elem in group2_50G): # If A_lanes contains [2] + B_lanes+=[12,13] + if all(elem in A_lanes for elem in group3_50G): # If A_lanes contains [3] + B_lanes+=[14,15] + if all(elem in A_lanes for elem in group4_50G): # If A_lanes contains [2] + B_lanes+=[12,13] + if all(elem in A_lanes for elem in group5_50G): # If A_lanes contains [3] + B_lanes+=[14,15] + #else: + # print("\n*** 50G-1 Gearbox Setup: Invalid Target A-Lanes specified!\n") + # return + + lanes = sorted(list(set(A_lanes + B_lanes))) + prbs_mode_select(lane=lanes, prbs_mode='functional') + + if all(elem in A_lanes for elem in group0_50G): # If A_lanes contains [0] + fw_config_cmd(config_cmd=0x90b0,config_detail=0x0000) # 0x90b0 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group1_50G): # If A_lanes contains [1] + fw_config_cmd(config_cmd=0x90b1,config_detail=0x0000) # 0x90b1 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group2_50G): # If A_lanes contains [2] + fw_config_cmd(config_cmd=0x90b2,config_detail=0x0000) # 0x90b2 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group3_50G): # If A_lanes contains [3] + fw_config_cmd(config_cmd=0x90b3,config_detail=0x0000) # 0x90b3 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group4_50G): # If A_lanes contains [4] + fw_config_cmd(config_cmd=0x90b4,config_detail=0x0000) # 0x90b4 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group5_50G): # If A_lanes contains [5] + fw_config_cmd(config_cmd=0x90b5,config_detail=0x0000) # 0x90b5 = First, FW destroy any instances of these lanes being already used + + if all(elem in A_lanes for elem in group0_50G): # If A_lanes contains [0] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A0 to B0-B1 with FEC_A0/FEC_B0..."), + fw_config_cmd(config_cmd=0x80b0,config_detail=0x0000) # 0x80b0 = FW Activate Gearbox 50G-1 for Lane A0 + else: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A0 to B0-B1 with FEC_A0 (FEC_B0 Bypassed)..."), + fw_config_cmd(config_cmd=0x80b8,config_detail=0x0000) # no fec 0x80b8 = FW Activate Gearbox 50G-1 for Lane A0 + + if all(elem in A_lanes for elem in group1_50G): # If A_lanes contains [1] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A1 to B2-B3 with FEC_A1/FEC_B1..."), + fw_config_cmd(config_cmd=0x80b1,config_detail=0x0000) # 0x80b1 = FW Activate Gearbox 50G-1 for Lane A1 + else: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A1 to B2-B3 with FEC_A1 (FEC_B1 Bypassed)..."), + fw_config_cmd(config_cmd=0x80b9,config_detail=0x0000) # no fec 0x80b9 = FW Activate Gearbox 50G-1 for Lane A1 + + if all(elem in A_lanes for elem in group2_50G): # If A_lanes contains [2] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A2 to B4-B5 with FEC_A0/FEC_B0..."), + fw_config_cmd(config_cmd=0x80b2,config_detail=0x0000) # 0x80b0 = FW Activate Gearbox 50G-1 for Lane A2 + else: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A2 to B4-B5 with FEC_A2 (FEC_B2 Bypassed)..."), + fw_config_cmd(config_cmd=0x80ba,config_detail=0x0000) # no fec 0x80ba = FW Activate Gearbox 50G-1 for Lane A2 + + if all(elem in A_lanes for elem in group3_50G): # If A_lanes contains [3] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A3 to B6-B7 with FEC_A3/FEC_B3..."), + fw_config_cmd(config_cmd=0x80b3,config_detail=0x0000) # 0x80b0 = FW Activate Gearbox 50G-1 for Lane A3 + else: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A3 to B6-B7 with FEC_A3 (FEC_B3 Bypassed)..."), + fw_config_cmd(config_cmd=0x80bb,config_detail=0x0000) # no fec 0x80bb = FW Activate Gearbox 50G-1 for Lane A3 + + if all(elem in A_lanes for elem in group4_50G): # If A_lanes contains [4] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A4 to B4-B5 with FEC_A0/FEC_B0..."), + fw_config_cmd(config_cmd=0x80b4,config_detail=0x0000) # 0x80b0 = FW Activate Gearbox 50G-1 for Lane A4 + else: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A4 to B4-B5 with FEC_A2 (FEC_B2 Bypassed)..."), + fw_config_cmd(config_cmd=0x80bc,config_detail=0x0000) # no fec 0x80bc = FW Activate Gearbox 50G-1 for Lane A4 + + if all(elem in A_lanes for elem in group5_50G): # If A_lanes contains [5] + if fec_b_byp==False: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A5 to B6-B7 with FEC_A3/FEC_B3..."), + fw_config_cmd(config_cmd=0x80b5,config_detail=0x0000) # 0x80b0 = FW Activate Gearbox 50G-1 for Lane A5 + else: + if print_en: print("\n...FW Gearbox 50G-1: Lanes A5 to B6-B7 with FEC_A3 (FEC_B3 Bypassed)..."), + fw_config_cmd(config_cmd=0x80bd,config_detail=0x0000) # no fec 0x80bd = FW Activate Gearbox 50G-1 for Lane A5 + + if print_en: print("Done!") + #fec_status() +#################################################################################################### +def watch(function,*args): + #import os + os.system('cls' if os.name == 'nt' else 'clear') + try: + while True: + print('\033[0;0H') # go to top left corner of screen + print('\033[f') # go to top left corner of screen + function(*args) + time.sleep(1) + except KeyboardInterrupt: + pass +#################################################################################################### +def twos_to_int(twos_val, bitWidth): + ''' + return a signed decimal number + ''' + mask = 1<<(bitWidth - 1) + return -(twos_val & mask) + (twos_val & ~mask) + +#################################################################################################### +def int_to_twos(value, bitWidth): + ''' + return a twos complement number + ''' + return (2**bitWidth)+value if value < 0 else value +#################################################################################################### +def dec2bin(x): + x -= int(x) + bins = [] + for i in range(8): + x *= 2 + bins.append(1 if x>=1. else 0) + x -= int(x) + #print bins + value = 0 + for a in range(8): + value = value+ bins[7-a]*pow(2,a) + + return value +#################################################################################################### +# +# Gray Code to Binary Conversion +#################################################################################################### +def Bin_Gray(bb=0): + gg=bb^(bb>>1) + return gg + +#################################################################################################### +def Gray_Bin(gg=0): # up to 7-bit Gray Number + bb1=(gg&0x40) + bb2=(gg^(bb1>>1))&(0x20) + bb3=(gg^(bb2>>1))&(0x10) + bb4=(gg^(bb3>>1))&(0x8) + bb5=(gg^(bb4>>1))&(0x4) + bb6=(gg^(bb5>>1))&(0x2) + bb7=(gg^(bb6>>1))&(0x1) + bb=bb1+bb2+bb3+bb4+bb5+bb6+bb7 + return bb +#################################################################################################### +def pol (tx_pol=None, rx_pol=None, lane=None, print_en=1): + + lanes = get_lane_list(lane) + #Slice=gSlice + #get_lane_mode('all') + result={} + + for ln in lanes: + get_lane_mode(ln) + c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + if (tx_pol!=None): + wreg(c.tx_pol_addr, tx_pol,ln) + if (rx_pol!=None): + wreg(c.rx_pol_addr, rx_pol,ln) + + tx_pol_this_lane= rreg(c.tx_pol_addr,ln) + rx_pol_this_lane= rreg(c.rx_pol_addr,ln) + result[ln] = tx_pol_this_lane, rx_pol_this_lane + #if(print_en): print("\nSlice %d Lane %s (%4s) Polarity: TX: %d -- RX: %d"%(Slice,lane_name_list[ln],gEncodingMode[gSlice][ln][0].upper(),tx_pol_this_lane, rx_pol_this_lane)), + + if print_en: # Print Status + get_lane_mode('all') + print("\nSlice %d, Lane:"%(sel_slice())), + for ln in range(len(lane_name_list)): + print(" %2s" %(lane_name_list[ln])), + print("\n TX Polarity:"), + for ln in range(len(lane_name_list)): + c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + print(" %2d" %(rreg(c.tx_pol_addr,ln))), + print("\n RX Polarity:"), + for ln in range(len(lane_name_list)): + c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + print(" %2d" %(rreg(c.rx_pol_addr,ln))), + else: + return tx_pol_this_lane, rx_pol_this_lane +#################################################################################################### +def gc (tx_gc=None, rx_gc=None, lane=None, print_en=None): + + lanes = get_lane_list(lane) + + Slice=gSlice + #get_lane_mode('all') + + for ln in lanes: + get_lane_mode(ln) + if gEncodingMode[gSlice][ln][0] == 'nrz': c=NrzReg + else: c=Pam4Reg + + if (tx_gc!=None and rx_gc is None): + wreg(c.tx_gray_en_addr, tx_gc,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': wreg(c.rx_gray_en_addr, tx_gc,ln) + elif (tx_gc!=None and rx_gc!=None): + wreg(c.tx_gray_en_addr, tx_gc,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': wreg(c.rx_gray_en_addr, rx_gc,ln) + else: + if print_en is None: print_en=1 # if no arguments, readout the current polarity settings + + tx_gc_this_lane= rreg(c.tx_gray_en_addr,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': rx_gc_this_lane= rreg(c.rx_gray_en_addr,ln) + else: rx_gc_this_lane=0 + + if(print_en): print("\nSlice %d Lane %s (%4s) GrayCode: TX: %d -- RX: %d"%(Slice,lane_name_list[ln],gEncodingMode[gSlice][ln][0].upper(),tx_gc_this_lane, rx_gc_this_lane)), + if(print_en==0): return tx_gc_this_lane, rx_gc_this_lane +#################################################################################################### +def pc (tx_pc=None, rx_pc=None, lane=None, print_en=None): + + lanes = get_lane_list(lane) + + Slice=gSlice + #get_lane_mode('all') + + for ln in lanes: + get_lane_mode(ln) + if gEncodingMode[gSlice][ln][0] == 'nrz': c=NrzReg + else: c=Pam4Reg + + if (tx_pc!=None and rx_pc is None): + wreg(c.tx_precoder_en_addr, tx_pc,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': wreg(c.rx_precoder_en_addr, tx_pc,ln) + elif (tx_pc!=None and rx_pc!=None): + wreg(c.tx_precoder_en_addr, tx_pc,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': wreg(c.rx_precoder_en_addr, rx_pc,ln) + else: + if print_en is None: print_en=1 # if no arguments, readout the current polarity settings + + tx_pc_this_lane= rreg(c.tx_precoder_en_addr,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': rx_pc_this_lane= rreg(c.rx_precoder_en_addr,ln) + else: rx_pc_this_lane= 0 + + if(print_en): print("\nSlice %d Lane %s (%4s) Precoder: TX: %d -- RX: %d"%(Slice,lane_name_list[ln],gEncodingMode[gSlice][ln][0].upper(),tx_pc_this_lane, rx_pc_this_lane)), + if(print_en==0): return tx_pc_this_lane, rx_pc_this_lane +#################################################################################################### +def msblsb (tx_msblsb=None, rx_msblsb=None, lane=None, print_en=None): + + lanes = get_lane_list(lane) + + #Slice=gSlice + #get_lane_mode('all') + + for ln in lanes: + get_lane_mode(ln) + if gEncodingMode[gSlice][ln][0] == 'nrz': c=NrzReg + else: c=Pam4Reg + + if (tx_msblsb!=None and rx_msblsb is None): + wreg(c.tx_msb_swap_addr, tx_msblsb,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': wreg(c.rx_msb_swap_addr, tx_msblsb,ln) + elif (tx_msblsb!=None and rx_msblsb!=None): + wreg(c.tx_msb_swap_addr, tx_msblsb,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': wreg(c.rx_msb_swap_addr, rx_msblsb,ln) + else: + if print_en is None: print_en=1 # if no arguments, readout the current polarity settings + + tx_msblsb_this_lane= rreg(c.tx_msb_swap_addr,ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': rx_msblsb_this_lane= rreg(c.rx_msb_swap_addr,ln) + else: rx_msblsb_this_lane =0 + + if(print_en): print("\nSlice %d Lane %s (%4s) MSB-LSB Swap: TX: %d -- RX: %d"%(gSlice,lane_name_list[ln],gEncodingMode[gSlice][ln][0].upper(),tx_msblsb_this_lane, rx_msblsb_this_lane)), + + if(print_en==0): return tx_msblsb_this_lane, rx_msblsb_this_lane + +#################################################################################################### +# reset_lane_pll () +# +# Power Down/Up (Toggle PU bits of) TXPLL or RXPLL +# Meanwhile, toggle FRAC_EN of each PLL +# +#################################################################################################### +def reset_lane_pll (tgt_pll='both', lane=None): + + lanes = get_lane_list(lane) # determine lanes to work on + #get_lane_mode(lanes) # Get current PAM4/NRZ modes settings of the specified lane(s) + + + for ln in lanes: + get_lane_mode(ln) + c = Pam4Reg if lane_mode_list[ln].lower() == 'pam4' else NrzReg + + tx_frac_en = rreg(c.tx_pll_frac_en_addr, ln)# save, 0x0D7 [13] TX PLL FRAC_EN=x + rx_frac_en = rreg(c.rx_pll_frac_en_addr, ln)# save, 0x1F0 [13] RX PLL FRAC_EN=y + + wreg(c.rx_pll_pu_addr, 0, ln) # Power down RX PLL while prgramming PLL + wreg(c.tx_pll_pu_addr, 0, ln) # Power down RX PLL while prgramming PLL + + wreg(c.tx_pll_frac_en_addr, 0, ln) # 0x0D7 [13] TX PLL FRAC_EN=0 + wreg(c.rx_pll_frac_en_addr, 0, ln) # 0x1F0 [13] RX PLL FRAC_EN=0 + + wreg(c.tx_pll_frac_en_addr, 1, ln) # 0x0D7 [13] TX PLL FRAC_EN=1 + wreg(c.rx_pll_frac_en_addr, 1, ln) # 0x1F0 [13] RX PLL FRAC_EN=1 + + wreg(c.tx_pll_frac_en_addr, 0, ln) # 0x0D7 [13] TX PLL FRAC_EN=0 + wreg(c.rx_pll_frac_en_addr, 0, ln) # 0x1F0 [13] RX PLL FRAC_EN=0 + + wreg(c.rx_pll_pu_addr, 1, ln) # Power up RX PLL after toggling FRAC_EN + wreg(c.tx_pll_pu_addr, 1, ln) # Power up TX PLL after toggling FRAC_EN + + #### Enable Fractional PLLs after programming PLLs, if needed + wreg(c.tx_pll_frac_en_addr, tx_frac_en, ln) # restore 0x0D7 [13] TX PLL FRAC_EN=x + wreg(c.rx_pll_frac_en_addr, rx_frac_en, ln) # restore 0x1F0 [13] RX PLL FRAC_EN=y + +#################################################################################################### +# set/get pll caps +# +# +#################################################################################################### +def pll_cap (tx_cap=None, rx_cap=None, lane=None, print_en=1): + + lanes = get_lane_list(lane) # determine lanes to work on + result = {} + + if(print_en): print("\n+-------------------------------------------------------------------+"), + top_pll_A_cap = rreg([0x9501,[12,6]]) + top_pll_B_cap = rreg([0x9601,[12,6]]) + if(print_en): print("\n| Dev%d TopPLL A/B | | A-cap: %3d | B-cap: %3d |"%(gSlice, top_pll_A_cap, top_pll_B_cap)), + if(print_en): print("\n+-------------------------------------------------------------------+"), + if(print_en): print("\n| | | Cal | TX PLL Cal | RX PLL Cal |"), + if(print_en): print("\n| Lane | DataRate | Done| Min Wr/Rd/Curr Max | Min Wr/Rd/Curr Max |"), + if(print_en): print("\n+-------------------------------------------------------------------+"), + + pll_params = get_lane_pll(lanes) + + for ln in lanes: + pll_cal_done= (fw_debug_cmd(0,5,ln)>>ln)&1 + + tx_cap_min = fw_debug_cmd(0,10,ln) + tx_cap_max = fw_debug_cmd(0,11,ln) + rx_cap_min = fw_debug_cmd(0,12,ln) + rx_cap_max = fw_debug_cmd(0,13,ln) + tx_cap_write = fw_debug_cmd(0,14,ln) + tx_cap_read = fw_debug_cmd(0,15,ln) + rx_cap_write = fw_debug_cmd(0,16,ln) + rx_cap_read = fw_debug_cmd(0,17,ln) + + if(tx_cap!=None): wreg(c.tx_pll_lvcocap_addr, tx_cap,ln) + if(rx_cap!=None): wreg(c.rx_pll_lvcocap_addr, rx_cap,ln) + tx_cap_this_lane= rreg(c.tx_pll_lvcocap_addr,ln) + rx_cap_this_lane= rreg(c.rx_pll_lvcocap_addr,ln) + result[ln] = [tx_cap_min,tx_cap_this_lane,tx_cap_max, rx_cap_min, rx_cap_this_lane,rx_cap_max] + pll_params = get_lane_pll(lanes) + fvco=pll_params[ln][0][0] + if(print_en): print("\n| %2s | %8.5f | %2d | %3d %2d/%2d/%2d %2d | %3d %2d/%2d/%2d %2d |"%(lane_name_list[ln],fvco,pll_cal_done,tx_cap_min,tx_cap_write, tx_cap_read,tx_cap_this_lane,tx_cap_max, rx_cap_min, rx_cap_write, rx_cap_read,rx_cap_this_lane,rx_cap_max)), + if(print_en) and (ln==lanes[-1] or ln==7): + print("\n+-------------------------------------------------------------------+"), + + if(print_en==0): return result + +#################################################################### +# pll cal for TOP PLL (REFCLK Source) +# +# sweeps pll cap and checks pll lock +#################################################################### +def pll_cal_top0( side = 'A'): + window=0x3fff + #toppll_lock = 0 + if side.upper() == 'A': + Base_addr = 0x9500 + else: + Base_addr = 0x9600 + # out = 0 + # inside = 0 + f2 = open('pll_cal_top_log.txt','w') + wregBits(Base_addr + 0x01,[12,6],0,16) + wregBits(Base_addr + 0x0D,[14,0],window,16) + setting = rregBits(Base_addr + 0x0D,[14,0],16) # set counter to the reference frequency + while 1: + wregBits(Base_addr + 0x12, [3], 0,16) # PD_CAL_FCAL = 0 + wregBits(Base_addr + 0x10, [7], 0,16) # LO_OPEN = 0 + wregBits(Base_addr + 0x0D, [15], 0,16) # fcal_start = 0 + wregBits(Base_addr + 0x0D, [15], 1,16) # fcal_start = 1 + while(rregBits(Base_addr + 0x0F, [15],16) == 0): #check fcal_done. If it's done, continue to the next + pass + readout = rregBits(Base_addr + 0x0E,[15,0],16) # read out the counter value(fcal_cnt_op[15:0]). + vcocap = rregBits(Base_addr + 0x01,[12,6],16) + if(abs(readout-setting) > 2): + if (vcocap == 0x7f): + vcocap_min = 0 + #toppll_lock = 1 + print >> f2, "The frequency setting is out of pll list(range(min))" + break + else: + vcocap = rregBits(Base_addr + 0x01,[12,6],16) + 0x1 + wregBits(Base_addr + 0x01, [12,6], vcocap,16) + else: + vcocap_min = rregBits(Base_addr + 0x01,[12,6],16) + print >> f2, "Min vcocap = %s" % (bin(vcocap_min)) + break + + wregBits(Base_addr + 0x01,[12,6],0x7f,16) + wregBits(Base_addr + 0x0D,[14,0],window,16) + while 1: + wregBits(Base_addr + 0x12, [3], 0,16) + wregBits(Base_addr + 0x10, [7], 0,16) + wregBits(Base_addr + 0x0D, [15], 0,16) + wregBits(Base_addr + 0x0D, [15], 1,16) + while(rregBits(Base_addr + 0x0F, [15],16) == 0): + pass + + readout = rregBits(Base_addr + 0x0E,[15,0],16) + vcocap = rregBits(Base_addr + 0x01,[12,6],16) + if(abs(readout-window) > 2): + if (vcocap == 0x0): + vcocap_max = 0 + #toppll_lock = 1 + print >> f2, "The frequency setting is out of pll list(range(max))" + break + else: + vcocap = rregBits(Base_addr + 0x01,[12,6],16) - 0x1 + wregBits(Base_addr + 0x01, [12,6], vcocap,16) + else: + vcocap_max = rregBits(Base_addr + 0x01,[12,6],16) + print >> f2, "Max vcocap = %s" % (bin(vcocap_max)) + break + + new_vcocap = int((vcocap_max + vcocap_min)/2) + if ((vcocap_max == 0x7f) & ((vcocap_max-vcocap_min)<4)): + new_vcocap = vcocap_max + else: + pass + if ((vcocap_min == 0x00) & ((vcocap_max-vcocap_min)<4)): + new_vcocap = vcocap_min + else: + pass + + print >> f2, "new_vcocap = %s" % (new_vcocap) + print >> f2, "Min CAP value : %s" % (vcocap_min) + print >> f2, "Max CAP value : %s" % (vcocap_max) + wregBits(Base_addr + 0x01, [12,6], new_vcocap,16) + print("CAP value : %s" % (hex(rregBits(Base_addr + 0x01, [12,6])))) + f2.close() + return new_vcocap +#################################################################### +# pll cal for TOP PLL (REFCLK Source) +# +# sweeps pll cap and checks pll lock +#################################################################### +def pll_cal_top1(tgt_pll=None, lane=None, print_en=1): + + if tgt_pll is None: tgt_pll='both' # set both top PLLs, A and B + pll_list=['A','B'] if tgt_pll=='both' else tgt_pll.upper() + + result = {} + pll_cal_result=[[1,2,3],[4,5,6]] # TX_PLL[vcocap_min,new_vcocap,vcocap_max], RX_PLL[vcocap_min,new_vcocap,vcocap_max], + log_en=1 + window=0x2000 + # out = 0 + # inside = 0 + + if(log_en): f2 = open('pll_cal_TOP_log.txt','w') + if print_en: print("\n -- Top PLL Cap --",) + if print_en: print("\nPLL, Min, Old/New, Max,",) + + for top_pll_side in pll_list: + if print_en: print("\n%3s,"%top_pll_side,) + if top_pll_side == 'A': + Base_addr = 0x9500 + top_pll_index=0 + else: + Base_addr = 0x9600 + top_pll_index=1 + + toppll_lock = 0 + + if(log_en): print >> f2, "TopPLL ,Dir, Cap, Target, ReadOut, Delta" + orig_vcocap = rregBits(Base_addr + 0x01,[12,6],16) # original cap value + + ### Sweep upward and find min vcocap + wregBits(Base_addr + 0x01,[12,6],0,16) + wregBits(Base_addr + 0x0D,[14,0],window,16) + target_cnt = rregBits(Base_addr + 0x0D,[14,0],16) # set counter to the reference frequency + while 1: + wregBits(Base_addr + 0x12, [3], 0,16) # PD_CAL_FCAL = 0 + wregBits(Base_addr + 0x10, [7], 0,16) # LO_OPEN = 0 + wregBits(Base_addr + 0x0D, [15], 0,16) # fcal_start = 0 + wregBits(Base_addr + 0x0D, [15], 1,16) # fcal_start = 1 + while(rregBits(Base_addr + 0x0F, [15],16) == 0): #check fcal_done. If it's done, continue to the next + pass + readout = rregBits(Base_addr + 0x0E,[15,0],16) # read out the counter value(fcal_cnt_op[15:0]). + vcocap = rregBits(Base_addr + 0x01,[12,6],16) + if(log_en): print >> f2, "TopPLL-%s, Up, %3d, %04X, %04X, %04X"%(top_pll_side, vcocap,target_cnt,readout, target_cnt-readout) + if(abs(readout-target_cnt) > 2): + if (vcocap == 0x7f): + vcocap_min = 0 + toppll_lock = 1 + if(log_en): print >> f2, "Top PLL Side %s, UP: The frequency target_cnt is out of pll list(range(min))"%top_pll_side + break + else: + vcocap = rregBits(Base_addr + 0x01,[12,6],16) + 0x1 + wregBits(Base_addr + 0x01, [12,6], vcocap,16) + else: + vcocap_min = rregBits(Base_addr + 0x01,[12,6],16) + #if(log_en): print >> f2, "Min vcocap = %d" % (vcocap_min) + break + + ### Sweep downward and find max vcocap + wregBits(Base_addr + 0x01,[12,6],0x7f,16) + wregBits(Base_addr + 0x0D,[14,0],window,16) + while 1: + wregBits(Base_addr + 0x12, [3], 0,16) + wregBits(Base_addr + 0x10, [7], 0,16) + wregBits(Base_addr + 0x0D, [15], 0,16) + # fcal start pulse delay + wregBits(Base_addr + 0x0D, [15], 1,16) + # fcal done check delay + while(rregBits(Base_addr + 0x0F, [15],16) == 0): + pass + + readout = rregBits(Base_addr + 0x0E,[15,0],16) + vcocap = rregBits(Base_addr + 0x01,[12,6],16) + if(log_en): print >> f2, "TopPLL-%s, Dn, %3d, %04X, %04X, %04X"%(top_pll_side, vcocap,target_cnt,readout, target_cnt-readout) + if(abs(readout-target_cnt) > 2): + if (vcocap == 0x0): + vcocap_max = 0 + toppll_lock = 1 + if(log_en): print >> f2, "Top PLL Side %s, DN: The frequency target_cnt is out of pll list(range(min))"%top_pll_side + break + else: + vcocap = rregBits(Base_addr + 0x01,[12,6],16) - 0x1 + wregBits(Base_addr + 0x01, [12,6], vcocap,16) + else: + vcocap_max = rregBits(Base_addr + 0x01,[12,6],16) + #if(log_en): print >> f2, "Max vcocap = %d" % (vcocap_max) + break + + ### Find the optimum cap from min and max + if (vcocap_max == 0x7f) and (vcocap_min == 0x00): # Search FAILED + new_vcocap = orig_vcocap + else: # Search SUCCESSFUL + new_vcocap = int((vcocap_max + vcocap_min)/2) + if ((vcocap_max == 0x7f) and ((vcocap_max-vcocap_min)<4)): + new_vcocap = vcocap_max + elif ((vcocap_min == 0x00) and ((vcocap_max-vcocap_min)<4)): + new_vcocap = vcocap_min + + wregBits(Base_addr + 0x01, [12,6], new_vcocap,16) + pll_cal_result[top_pll_index]=[vcocap_min,new_vcocap,vcocap_max] + flag= '>' if orig_vcocap!=new_vcocap else ',' + if print_en: print("%3d, %3d%s%3d, %3d, " % (vcocap_min,orig_vcocap,flag,new_vcocap,vcocap_max),) + if(log_en): print >> f2, "\nTop PLL %s VCOCAPS: Min/Center(Orig)/Max: %2d / %2d(%2d) / %2d\n" % (top_pll_side,vcocap_min,new_vcocap,orig_vcocap,vcocap_max) + + wregBits(Base_addr + 0x10, [7], 0,16) # LO_OPEN = 0 + wregBits(Base_addr + 0x0D, [15], 0,16) # fcal_start = 0 + wregBits(Base_addr + 0x0D,[14,0], 0,16) # facl window=0 + wregBits(Base_addr + 0x12, [3], 1,16) # PD_CAL_FCAL = 1 + #### End of this Top PLL + + #### End of both Top PLL + result=[pll_cal_result[0],pll_cal_result[1]] # [0]=A and [1]=B + if print_en: print("\n") + if(log_en): f2.close() + if print_en==0: return result + +#################################################################### +def pll_cal_top(side ='both'): + #print ("\npll_cal_top\n") + + if side.upper() == 'A' or side.upper() == 'BOTH': + Base_addr = 0x9500 + capA = pll_cal_top3(base=Base_addr) + if side.upper() == 'B' or side.upper() == 'BOTH': + Base_addr = 0x9600 + capB = pll_cal_top3(base=Base_addr) + + if side.upper() == 'A': + return capA + if side.upper() == 'B': + return capB + if side.upper() == 'BOTH': + return [capA,capB] + +#################################################################### +# pll cal for TOP PLL (REFCLK Source) +# +# sweeps pll cap and checks pll lock +#################################################################### +def pll_cal_top3(window=0x3fff, base=0x9500): + wregBits(base+0x10, [6, 4], 4) + wregBits(base+0x10, [7], 1) + wregBits(base+0xd, [14, 0], window) + wregBits(base+0x12, [3], 0) + wregBits(base+0x0d, [15], 0) + vco_min = 0 + vco_max = 0 + no_cross = True + for vco in list(range(0, 128, 2)): + wregBits(base+1, [12, 6], vco) + wregBits(base+0x0d, [15], 1) + count=0 + while rregBits(base+0xf, [15])==0 and count<1000: count+=1 + readout = rregBits(base+0xe, [15, 0]) + wregBits(base+0xd, [15], 0) + if (count>=1000): + print("cal_done timeout at %d", vco) + continue + else: + if readout > window : + vco_min = vco + elif no_cross : + vco_max = vco + no_cross = False + #print("scan, %3d, %04x, %04x" % (vco, window, readout)) + vco = int((vco_min+vco_max)/2) + wregBits(base+1, [12, 6], vco) + wregBits(base+0x10, [7], 0) + wregBits(base+0xd, [14, 0], 0) + wregBits(base+0x12, [3], 1) + #print("Top PLL %04X final vco = %3d" % (base,vco) ) + + return vco + +#################################################################### +# pll cal for TOP PLL (REFCLK Source) +# +# sweeps pll cap and checks pll lock +#################################################################### +def pll_cal_top2(lane=0, window=0x3fff, openLoop=False, scanAll=None, dir_down=False): + # Prolog + base=0x9500+lane*0x100 + + if openLoop: + wregBits(base+0x10, [6, 4], 4) + wregBits(base+0x10, [7], 1) + else: + wregBits(base+0x10, [7], 0) + + wregBits(base+0xd, [14, 0], window) + wregBits(base+0x12, [3], 0) + wregBits(base+0x0d, [15], 0) + vco_max = 128 + if scanAll is not None: + if not isinstance(scanAll, list): + scanAll=range(vco_max) + for vco in scanAll: + if dir_down : + wregBits(base+1, [12, 6], vco) + else : + wregBits(base+1, [12, 6], vco_max-vco) + wregBits(base+0x0d, [15], 1) + count=0 + while rregBits(base+0xf, [15])==0 and count<1000: count+=1 + readout = rregBits(base+0xe, [15, 0]) + wregBits(base+0xd, [15], 0) + if (count>=1000): + print("cal_done timeout at %d", vco) + else: + print("lane %d, scan, %3d, %04x, %04x" % (lane, vco, window, readout)) + return + vco=0 + while vco<0x80: + wregBits(base+1, [12, 6], vco) + wregBits(base+0x0d, [15], 1) + count=0 + while rregBits(base+0xf, [15])==0 and count<1000: count+=1 + readout = rregBits(base+0xe, [15, 0]) + wregBits(base+0x0d, [15], 0) + if (count>=1000): + print("cal_done timeout at %d", vco) + return + print("lane %d, up, %3d, %04x, %04x" % (lane, vco, window, readout)) + if abs(readout-window)>2: + if (vco==0x7f): + # vco_min = 0 + print("top pll scan up no lock") + return + else: + vco+=1 + continue + else: + vcomin = vco + print("lane %d vcomin = %3d" % (lane, vcomin)) + break + vco=0x7f + while vco>=0: + wregBits(base+1, [12, 6], vco) + wregBits(base+0xd, [15], 1) + count=0 + while rregBits(base+0xf, [15])==0 and count<1000: count+=1 + readout = rregBits(base+0xe, [15, 0]) + wregBits(base+0xd, [15], 0) + if (count>=1000): + print("cal_done timeout at %d", vco) + return + print("lane %d, down, %3d, %04x, %04x" % (lane, vco, window, readout)) + if abs(readout-window)>2: + if (vco==0): + print("top pll scan down no lock") + return + else: + vco-=1 + continue + else: + vcomax = vco + print("lane %d vcomax = %3d" % (lane, vcomax)) + break + vco = int((vcomin+vcomax)/2) + wregBits(base+1, [12, 6], vco) + # Epilog + wregBits(base+0x10, [7], 0) + wregBits(base+0xd, [14, 0], 0) + wregBits(base+0x12, [3], 1) + print("lane %d final vco = %3d" % (lane, vco)) + +#################################################################################################### +# pll cal for RX PLL, TX PLL, or both +# +# sweeps pll cap and checks pll lock +#################################################################################################### +def pll_cal(tgt_pll=None, lane=None, print_en=1): + + if tgt_pll is None: tgt_pll='both' # set both PLLs with datarate passed + pll_list=['tx','rx'] if tgt_pll=='both' else tgt_pll + + lanes = get_lane_list(lane) + result = {} + pll_cal_result=[[1,2,3],[4,5,6]] # TX_PLL[vcocap_min,new_vcocap,vcocap_max], RX_PLL[vcocap_min,new_vcocap,vcocap_max], + #log_en=0 + window=0x2000 + # out = 0 + # inside = 0 + rx_lock = 0 + + #if(log_en): f2 = open('pll_cal_log.txt','w') + if print_en: print ("\n --- TX PLL Cap --- --- RX PLL Cap ---") + if print_en: print ("\nLn, Min, Old/New, Max, Min, Old/New, Max") + + for ln in lanes: + if print_en: print ("\n%s,"%lane_name_list[ln]) + for lane_pll in pll_list: + index=-1 + if 'tx' in lane_pll: # TX PLL CAL + index=0 + vcocap_addr = [0xDB, [14,8]] + fcal_window_addr = [0xD1, [14,0]] + fcal_cnt_op_addr = [0xD0, [15,0]] + fcal_pd_cal_addr = [0xDB, [6]] + fcal_lo_open_addr= [0xD9, [11]] + fcal_start_addr = [0xD1, [15]] + fcal_done_addr = [0xCF, [15]] + else: # RX PLL CAL + index=1 + vcocap_addr = [0x1F5,[15,9]] + fcal_window_addr = [0x1EA,[14,0]] + fcal_cnt_op_addr = [0x1E9,[15,0]] + fcal_pd_cal_addr = [0x1F5, [6]] + fcal_lo_open_addr= [0x1F3, [11]] + fcal_start_addr = [0x1EA, [15]] + fcal_done_addr = [0x1E8, [15]] + + + #if(log_en): print >> f2, "Lane,Dir, Cap, Target, ReadOut" + orig_vcocap = rreg(vcocap_addr,ln) # original cap value + + ### Sweep upward and find min vcocap + wreg(vcocap_addr,0x0,ln) + wreg(fcal_window_addr,window,ln) + target_cnt = rreg(fcal_window_addr,ln) # set counter to the reference frequency + while 1: + wreg(fcal_pd_cal_addr, 0,ln) # PD_CAL_FCAL = 0 + wreg(fcal_lo_open_addr, 0,ln) # LO_OPEN = 0 + wreg(fcal_start_addr, 0,ln) # fcal_start = 0 + wreg(fcal_start_addr, 1,ln) # fcal_start = 1 + + while(rreg(fcal_done_addr,ln) == 0): #check fcal_done. If it's done, continue to the next + pass + readout = rreg(fcal_cnt_op_addr,ln) # read out the counter value(fcal_cnt_op[15:0]). + vcocap = rreg(vcocap_addr,ln) + #if(log_en): print >> f2, "%4d, Up, %3d, %04X, %04X"%(ln, vcocap,target_cnt,readout) + if(abs(readout-target_cnt) > 2): + if (vcocap == 0x7f): + vcocap_min = 0 + rx_lock = 1 + #if(log_en): print >> f2, "Lane %d, UP: The frequency target_cnt is out of pll range(min)"%ln + break + else: + vcocap = rreg(vcocap_addr,ln) + 0x1 + wreg(vcocap_addr, vcocap,ln) + else: + vcocap_min = rreg(vcocap_addr,ln) + #if(log_en): print >> f2, "Min vcocap = %d" % (vcocap_min) + break + + ### Sweep downward and find max vcocap + wreg(vcocap_addr,0x7f,ln) + wreg(fcal_window_addr,window,ln) + while 1: + wreg(fcal_pd_cal_addr, 0,ln) + wreg(fcal_lo_open_addr, 0,ln) + wreg(fcal_start_addr, 0,ln) + # fcal start pulse delay + wreg(fcal_start_addr, 1,ln) + # fcal done check delay + while(rreg(fcal_done_addr,ln) == 0): + pass + + readout = rreg(fcal_cnt_op_addr,ln) + vcocap = rreg(vcocap_addr,ln) + #if(log_en): print >> f2, "%4d, Dn, %3d, %04X, %04X"%(ln, vcocap,target_cnt,readout) + + if(abs(readout-target_cnt) > 2): + if (vcocap == 0x0): + vcocap_max = 0 + rx_lock = 1 + #if(log_en): print >> f2, "Lane %d,Down: The frequency target_cnt is out of pll range(max)"%ln + break + else: + vcocap = rreg(vcocap_addr,ln) - 0x1 + wreg(vcocap_addr, vcocap,ln) + else: + vcocap_max = rreg(vcocap_addr,ln) + #if(log_en): print >> f2, "Max vcocap = %d" % (vcocap_max) + break + + ### Find the optimum cap from min and max + if (vcocap_max == 0x7f) and (vcocap_min == 0x00): # Search FAILED + new_vcocap = orig_vcocap + else: # Search SUCCESSFUL + new_vcocap = int((vcocap_max + vcocap_min)/2) + if ((vcocap_max == 0x7f) and ((vcocap_max-vcocap_min)<4)): + new_vcocap = vcocap_max + elif ((vcocap_min == 0x00) and ((vcocap_max-vcocap_min)<4)): + new_vcocap = vcocap_min + + wreg(vcocap_addr, new_vcocap,ln) + pll_cal_result[index]=[vcocap_min,new_vcocap,vcocap_max] + flag= '>' if orig_vcocap!=new_vcocap else ',' + if print_en: print ("%3d, %3d%s%3d, %3d, " % (vcocap_min,orig_vcocap,flag,new_vcocap,vcocap_max)) + #if(log_en): print ("\nLane %2d %s VCOCAPS: Min/Center(Orig)/Max: %2d / %2d(%2d) / %2d\n" % (ln,lane_pll,vcocap_min,new_vcocap,orig_vcocap,vcocap_max),file=f2) + + ### Disable TX or RX PLL CAL circuit after done with this Lane's PLL + wreg(fcal_lo_open_addr, 0,ln) + wreg(fcal_start_addr, 0,ln) + wreg(fcal_window_addr, 0,ln) + wreg(fcal_pd_cal_addr, 1,ln) + ### end of this PLL, TX or RX + + result[ln]=[pll_cal_result[0],pll_cal_result[1]] + #### End of this lane + + if print_en: print ("\n") + #if(log_en): f2.close() + if print_en==0: return result + +#################################################################################################### +# set_lane_pll () +# +# Programs TXPLL or RXPLL according to PLL parameter(s) passed +# +# returns status of PLL programming (success/fail) +# +#################################################################################################### +def set_lane_pll (tgt_pll=None, datarate=None, fvco=None, cap=None, n=None, div4=None, div2=None, refclk=None, frac_en=None, frac_n=None, lane=None): + + if tgt_pll is None: + if datarate is None: + print(" \tEnter one or more of the following arguments:") + print(" \tset_lane_pll(tgt_pll='both'/'rx'/'tx', datarate, fvco, cap, n, div4, div2, refclk, lane)") + rn + else: + tgt_pll='both' # set both PLLs with datarate passed + + fvco_max = 33.0 + fvco_min = 15.0 + pll_n_max = 511 # (0x1FF) + + lanes = get_lane_list(lane) # determine lanes to work on + #get_lane_mode(lanes) # Get current PAM4/NRZ modes settings of the specified lane(s) + pll_params = get_lane_pll(lanes) # Get current PLL settings of the specified lane(s) + + #pll_params = [list(x) for x in pll_params_curr] + if 'tx' in tgt_pll: + desired_pll = [0] + elif 'rx' in tgt_pll: + desired_pll = [1] + else: #if tgt_pll=='both': + desired_pll = [0,1] + + # Temporary holders for each lane/pll + # lane_datarate=[0,1] + # lane_fvco =[0,1] + lane_cap =[0,1] + lane_n =[0,1] + lane_div4 =[0,1] + lane_div2 =[0,1] + lane_refclk =[0,1] + lane_frac_n =[0,1] + lane_frac_en =[0,1] + + ####### determine desired PLL parameters if passed, otherwise re-use current values from chip + for ln in lanes: + get_lane_mode(ln) + #### Do this per PLL (TXPLL and/or RXPLL) of each lane + for pll in desired_pll: + lane_cap [pll] = pll_params[ln][pll][2] if cap is None else cap + lane_n [pll] = pll_params[ln][pll][3] if n is None else n + lane_div4 [pll] = pll_params[ln][pll][4] if div4 is None else div4 + lane_div2 [pll] = pll_params[ln][pll][5] if div2 is None else div2 + lane_refclk[pll] = pll_params[ln][pll][6] if refclk is None else refclk + lane_frac_n[pll] = pll_params[ln][pll][7] if frac_n is None else frac_n + lane_frac_en[pll]= pll_params[ln][pll][8] if frac_en is None else frac_en + + ####### Calculate 'desired_n' per lane per pll (only if Data Rate or Fvco is passed) + if datarate != None or fvco != None: + if datarate != None: + desired_data_rate = float(datarate) + if desired_data_rate > fvco_max: + data_rate_to_fvco_ratio = 2.0 ##### PAM4 Data Rate, > 33 Gbps + wreg(c.rx_pam4_en_addr, 1,ln) # RX_PAM4_EN=1 + wreg(c.tx_nrz_mode_addr, 0,ln) # TX_NRZ_EN=0 + wreg(c.tx_mode10g_en_addr, 0,ln) # TX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + wreg(c.rx_mode10g_addr, 0,ln) # RX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + elif desired_data_rate < fvco_min: + data_rate_to_fvco_ratio = 0.5 ##### NRZ Half-Rate Data Rate, < 15 Gbps + wreg(c.rx_pam4_en_addr, 0,ln) # RX_PAM4_EN=0 + wreg(c.tx_nrz_mode_addr, 1,ln) # TX_NRZ_EN=1 + wreg(c.tx_mode10g_en_addr, 1,ln) # TX_NRZ_10G_EN=1 (or Enable NRZ Half-Rate Mode) + wreg(c.rx_mode10g_addr, 1,ln) # RX_NRZ_10G_EN=1 (or Enable NRZ Half-Rate Mode) + else: + data_rate_to_fvco_ratio = 1.0 ##### NRZ Full-Rate Data Rate, 15 Gbps to 33 Gbps + wreg(c.rx_pam4_en_addr, 0,ln) # RX_PAM4_EN=0 + wreg(c.tx_nrz_mode_addr, 1,ln) # TX_NRZ_EN=1 + wreg(c.tx_mode10g_en_addr, 0,ln) # TX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + wreg(c.rx_mode10g_addr, 0,ln) # RX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + + desired_fvco = desired_data_rate / data_rate_to_fvco_ratio + else: + desired_fvco = float(fvco) + + if desired_fvco >fvco_max: desired_fvco=fvco_max + if desired_fvco pll_n_max: desired_n = pll_n_max + lane_n[pll]=desired_n + + #update this lane's TXPLL and RXPLL params + pll_params[ln] = [(0,0,lane_cap[0],lane_n[0],lane_div4[0],lane_div2[0],lane_refclk[0],lane_frac_n[0],lane_frac_en[0]),(0,0,lane_cap[1],lane_n[1],lane_div4[1],lane_div2[1],lane_refclk[1],lane_frac_n[1],lane_frac_en[1])] + + ###### Now program both PLLs of the specified lane(s) + for ln in lanes: + wreg(c.rx_pll_pu_addr, 0, ln) # Power down RX PLL while prgramming PLL + wreg(c.tx_pll_pu_addr, 0, ln) # Power down TX PLL while prgramming PLL + + if 'tx' in tgt_pll or tgt_pll=='both': + wreg(c.tx_pll_lvcocap_addr, pll_params[ln][0][2], ln) + wreg(c.tx_pll_n_addr, int(pll_params[ln][0][3]), ln) + wreg(c.tx_pll_div4_addr, pll_params[ln][0][4], ln) + wreg(c.tx_pll_div2_addr, pll_params[ln][0][5], ln) + wreg(c.tx_pll_frac_n_addr, pll_params[ln][0][7], ln) + wreg(c.tx_pll_frac_en_addr, pll_params[ln][0][8], ln) + + if 'rx' in tgt_pll or tgt_pll=='both': + wreg(c.rx_pll_lvcocap_addr, pll_params[ln][1][2], ln) + wreg(c.rx_pll_n_addr, int(pll_params[ln][1][3]), ln) + wreg(c.rx_pll_div4_addr, pll_params[ln][1][4], ln) + wreg(c.rx_pll_div2_addr, pll_params[ln][1][5], ln) + wreg(c.rx_pll_frac_n_addr, pll_params[ln][1][7], ln) + wreg(c.rx_pll_frac_en_addr, pll_params[ln][1][8], ln) + + wreg(c.rx_pll_pu_addr, 1, ln) # Power up RX PLL after prgramming PLL + wreg(c.tx_pll_pu_addr, 1, ln) # Power up TX PLL after prgramming PLL + + +#################################################################################################### +# get_lane_pll () +# +# reads all PLL related registers and computes PLL Frequencies and Data Rates +# +# returns all TXPLL and RXPLL parameters for the specified lane(s) +# +#################################################################################################### +def get_lane_pll (lane=None): + + lanes = get_lane_list(lane) + #get_lane_mode(lanes) + + pll_params = {} + + #ref_clk=195.3125 + #ref_clk=156.25 + ref_clk = gRefClkFreq + + + for ln in lanes: + tx_div4_en = rreg(c.tx_pll_div4_addr, ln) + tx_div2_bypass = rreg(c.tx_pll_div2_addr, ln) + tx_pll_n = rreg(c.tx_pll_n_addr, ln) + tx_pll_cap = rreg(c.tx_pll_lvcocap_addr, ln) + tx_10g_mode_en = rreg(c.tx_mode10g_en_addr, ln) # NRZ 10G (or NRZ Half-Rate Mode) + tx_pll_frac_n = rreg(c.tx_pll_frac_n_addr, ln) # Fractional_PLL_N + if chip_rev()==2.0: # For R2.0, TX Frac-N is 20 bits + tx_pll_frac_n_hi = rreg([0x0d9,[3,0]], ln) # Fractional_PLL_N[19:16] + tx_pll_frac_n_lo = rreg(c.tx_pll_frac_n_addr, ln) # Fractional_PLL_N[15:0] + tx_pll_frac_n = (tx_pll_frac_n_hi << 16) + tx_pll_frac_n_lo + #tx_pll_frac_order = rreg(c.tx_pll_frac_order_addr, ln) # Fractional_PLL_ORDER + tx_pll_frac_en = rreg(c.tx_pll_frac_en_addr, ln) # Fractional_PLL_EN + + rx_div4_en = rreg(c.rx_pll_div4_addr, ln) + rx_div2_bypass = rreg(c.rx_pll_div2_addr, ln) + rx_pll_n = rreg(c.rx_pll_n_addr, ln) + rx_pll_cap = rreg(c.rx_pll_lvcocap_addr, ln) + #rx_10g_mode_en = rreg(c.rx_mode10g_addr, ln) # checking TX 10G is enough + rx_pll_frac_n = rreg(c.rx_pll_frac_n_addr, ln) # Fractional_PLL_N + #rx_pll_frac_order = rreg(c.rx_pll_frac_order_addr, ln) # Fractional_PLL_ORDER + rx_pll_frac_en = rreg(c.rx_pll_frac_en_addr, ln) # Fractional_PLL_EN + + tx_div_by_4 = 1.0 if tx_div4_en==0 else 4.0 + rx_div_by_4 = 1.0 if rx_div4_en==0 else 4.0 + tx_mul_by_2 = 1.0 if tx_div2_bypass==1 else 2.0 + rx_mul_by_2 = 1.0 if rx_div2_bypass==1 else 2.0 + + pam4_mode_en = 1 if (rreg(c.tx_nrz_mode_addr,ln) == 0 and rreg(c.rx_pam4_en_addr,ln) == 1) else 0 + if pam4_mode_en: ########## Lane is in PAM4 mode (i.e. 33G =< data rate < 63G) + data_rate_to_fvco_ratio = 2.0 + else: ##################### Lane is in NRZ mode + if tx_10g_mode_en==0: # Lane is in NRZ Full Rate mode (i.e. 15G < data rate < 33G) + data_rate_to_fvco_ratio = 1.0 + else: # Lane is in NRZ Half Rate mode (i.e. data rate =< 15G) + data_rate_to_fvco_ratio = 0.5 + + if chip_rev() == 2.0: + tx_pll_n_float = float(tx_pll_n) + float(tx_pll_frac_n/1048575.0) if tx_pll_frac_en else float(tx_pll_n) + else: + tx_pll_n_float = float(tx_pll_n) + float(tx_pll_frac_n/65535.0) if tx_pll_frac_en else float(tx_pll_n) + + rx_pll_n_float = float(rx_pll_n) + float(rx_pll_frac_n/65535.0) if rx_pll_frac_en else float(rx_pll_n) + + tx_fvco = (ref_clk * tx_pll_n_float * 2.0 * tx_mul_by_2) / tx_div_by_4 / 1000.0 # in GHz + rx_fvco = (ref_clk * rx_pll_n_float * 2.0 * rx_mul_by_2) / rx_div_by_4 / 1000.0 # in GHz + + tx_data_rate = tx_fvco * data_rate_to_fvco_ratio + rx_data_rate = rx_fvco * data_rate_to_fvco_ratio + + tx_pll_params = tx_data_rate, tx_fvco, tx_pll_cap, tx_pll_n_float, tx_div4_en, tx_div2_bypass, ref_clk, tx_pll_frac_en, tx_pll_frac_n + rx_pll_params = rx_data_rate, rx_fvco, rx_pll_cap, rx_pll_n_float, rx_div4_en, rx_div2_bypass, ref_clk, rx_pll_frac_en, rx_pll_frac_n + + pll_params[ln] = [tx_pll_params,rx_pll_params] + + return pll_params #data_rate, fvco, pll_cap, pll_n, div4, div2, ref_clk +#################################################################################################### +# pll() +# +# This is intended for python command line usage, to get or set PLL +# +# See get_lane_pll() and set_lane_pll() for actual PLL functions +# +#################################################################################################### +def pll (tgt_pll=None, datarate=None, fvco=None, cap=None, n=None, div4=None, div2=None, refclk=None, frac_en=None, frac_n=None, lane=None): + + lanes = get_lane_list(lane) + + if datarate!=None or fvco!=None or cap!=None or n!=None or div4!=None or div2!=None or refclk!=None or frac_en!=None or frac_n!=None: # desired_pll_n or desired_data_rate, then program PLL registers + set_lane_pll(tgt_pll, datarate, fvco, cap, n, div4, div2, refclk, frac_en, frac_n, lane) + + #get_lane_mode(lanes) # Now update the lanes' modes (PAM4 or NRZ) before printing them out + pll_params = get_lane_pll(lanes) + + ##### Print Headers + print("\n PLL Parameters for Slice %d with RefClk: %8.4f MHz\n"%(gSlice,pll_params[lanes[0]][0][6])), + print("\n+------------+------------- T X P L L --------------------+------------- R X P L L --------------------+"), + print("\n|Lane | mode | DataRate, Fvco, CAP, N, DIV4, DIV2| DataRate, Fvco, CAP, N, DIV4, DIV2|"), + print("\n+------------+---------------------------------------------+---------------------------------------------+"), + + for ln in lanes: + get_lane_mode(ln) + print("\n|S%d_%2s| %4s |"%(gSlice,lane_name_list[ln],gEncodingMode[gSlice][ln][0].upper())), + for pll in [0,1]: + print("%8.5f, %8.5f, %3d, %7.3f, %3d , %3d |" %(pll_params[ln][pll][0], pll_params[ln][pll][1], pll_params[ln][pll][2], pll_params[ln][pll][3], pll_params[ln][pll][4], pll_params[ln][pll][5])), + if ln==lanes[-1] or ln==7: + print("\n+------------+---------------------------------------------+---------------------------------------------+"), +#################################################################################################### +## EYE Margin, by Python directly accessing the HW registers +#################################################################################################### +def eye(lane = None): + lanes = get_lane_list(lane) + result = {} + fw_eye_en = fw_loaded(print_en=0) and fw_date(print_en=0)>=18015 and fw_reg_rd(128)!=0 # FW Date 20190429 and later + for ln in lanes: + get_lane_mode(ln) + line_encoding = lane_mode_list[ln].lower() + c = Pam4Reg if line_encoding == 'pam4' else NrzReg + x = 100 if line_encoding == 'pam4' else 200 + rdy = sum(ready(ln)[ln]) + em=[-1,-1,-1] + ##### PAM4 EYE + if line_encoding == 'pam4' and rdy == 3: + ####### FW-based Eye margin + # if FW is loaded and the Background FW is not paused + # if fw_loaded and fw_pause(print_en=0)[0][2] == 1: + if fw_eye_en == True: + fw_debug_cmd(section=10, index=5, lane=ln) + em = [rreg(0x9f00+eye_index) for eye_index in range(3)] + ####### SW-based Eye margin. Direct access to HW registers + else: + eye_margin = [] + dac_val = dac(lane=ln)[ln] + for eye_index in range (0,3): + result1 = 0xffff + for y in range (0,4): + sel = 3 * y + eye_index + wreg(c.rx_plus_margin_sel_addr, sel, ln) + plus_margin = rreg(c.rx_plus_margin_addr, ln) + if (plus_margin > 0x7ff): + plus_margin = plus_margin - 0x1000 + wreg(c.rx_minus_margin_sel_addr, sel, ln) + minus_margin = (rreg(c.rx_minus_margin_addr, ln)) + if (minus_margin > 0x7ff): + minus_margin = minus_margin - 0x1000 + diff = plus_margin - minus_margin + if ( diff < result1): + result1 = diff + # else: + # result1 = result1 + eye_margin.append((result1)) + em[eye_index] = (float(eye_margin[eye_index])/2048.0) * (x + (50.0 * float(dac_val))) + ##### NRZ EYE + elif line_encoding == 'nrz' and rdy == 3: + dac_val = dac(lane=ln)[ln] + eye_reg_val = rreg(c.rx_em_addr, ln) + em[0] = (float(eye_reg_val) / 2048.0) * (x + (50.0 * float(dac_val))) + em[1]=0;em[2]=0 + + result[ln] = int(em[0]),int(em[1]),int(em[2]) + return result +#################################################################################################### +## EYE Margin, by Python directly accessing the HW registers +#################################################################################################### +def sw_eye(lane = None): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + get_lane_mode(ln) + line_encoding = lane_mode_list[ln].lower() + c = Pam4Reg if line_encoding == 'pam4' else NrzReg + x = 100 if line_encoding == 'pam4' else 200 + rdy = sum(ready(ln)[ln]) + em=[-1,-1,-1] + ##### PAM4 EYE + if line_encoding == 'pam4' and rdy == 3: + eye_margin = [] + ####### FW-based Eye margin + # if FW is loaded and the Background FW is not paused + # if fw_loaded and fw_pause(print_en=0)[0][2] == 1: + # if False:# fw_loaded and fw_reg_rd(128)!=0: + # print ("FW EYE MARGIN Lane %d"%ln) + # fw_debug_cmd(section=10, index=5, lane=ln) + # em = [rreg(0x9f00+eye_index) for eye_index in range(3)] + # ####### SW-based Eye margin. Direct access to HW registers + # else: + dac_val = dac(lane=ln)[ln] + for eye_index in range (0,3): + result1 = 0xffff + for y in range (0,4): + sel = 3 * y + eye_index + wreg(c.rx_plus_margin_sel_addr, sel, ln) + plus_margin = rreg(c.rx_plus_margin_addr, ln) + if (plus_margin > 0x7ff): + plus_margin = plus_margin - 0x1000 + wreg(c.rx_minus_margin_sel_addr, sel, ln) + minus_margin = (rreg(c.rx_minus_margin_addr, ln)) + if (minus_margin > 0x7ff): + minus_margin = minus_margin - 0x1000 + diff = plus_margin - minus_margin + if ( diff < result1): + result1 = diff + # else: + # result1 = result1 + eye_margin.append((result1)) + em[eye_index] = (float(eye_margin[eye_index])/2048.0) * (x + (50.0 * float(dac_val))) + ##### NRZ EYE + elif line_encoding == 'nrz' and rdy == 3: + dac_val = dac(lane=ln)[ln] + eye_reg_val = rreg(c.rx_em_addr, ln) + em[0] = (float(eye_reg_val) / 2048.0) * (x + (50.0 * float(dac_val))) + em[1]=0;em[2]=0 + + result[ln] = int(em[0]),int(em[1]),int(em[2]) + return result +#################################################################################################### +## EYE Margin, by Firmware +#################################################################################################### +def fw_eye(lane = None): + + #fw_eye_en = fw_loaded(print_en=0) and fw_date(print_en=0)>=18015 and fw_reg_rd(128)!=0 # FW Date 20190429 or later + fw_eye_en = fw_loaded(print_en=0) and fw_ver(print_en=0)>=0x20900 and fw_reg_rd(128)!=0 # FW 2.09.00 and later + if fw_eye_en == False: + print("\n*** FW Not Loaded, or "), + print("\n*** FW Eye Margin function Not Available In This Release (Need DateCode 20190429 or later), or"), + print("\n*** FW Background Functions are Disabled (FW REG 128 = 0 instead of 0xFFFF)\n"), + return -1, -1, -1 + + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + get_lane_mode(ln) + line_encoding = lane_mode_list[ln].lower() + c = Pam4Reg if line_encoding == 'pam4' else NrzReg + x = 100 if line_encoding == 'pam4' else 200 + rdy = sum(ready(ln)[ln]) + em=[-1,-1,-1] + ##### PAM4 EYE + if line_encoding == 'pam4' and rdy == 3: + fw_debug_cmd(section=10, index=5, lane=ln) + em = [rreg(0x9f00+eye_index) for eye_index in range(3)] + ##### NRZ EYE + elif line_encoding == 'nrz' and rdy == 3: # NRZ EYE + dac_val = dac(lane=ln)[ln] + eye_reg_val = rreg(c.rx_em_addr, ln) + em[0] = (float(eye_reg_val) / 2048.0) * (x + (50.0 * float(dac_val))) + em[1] = 0 + em[2] = 0 + result[ln] = int(em[0]),int(em[1]),int(em[2]) + return result + +#################################################################################################### +## PAM4 EYE Margin, by FW or by Python directly accessing HW registers +#################################################################################################### +def eye_pam4(lane=None): + #c = Pam4Reg + #c.rx_plus_margin_sel_addr = [0x88,[15,12]] + #c.rx_minus_margin_sel_addr = [0x88,[11,8]] + #c.rx_plus_margin_addr = [0x32,[15,4]] + #c.rx_minus_margin_addr = [0x32, [3,0], 0x33, [15,8]] + #c.rx_minus_margin_upper_addr = [0x32,[3,0]] + #c.rx_minus_margin_lower_addr = [0x33,[15,8]] + + fw_eye_en = fw_loaded(print_en=0) and fw_date(print_en=0)>=18015 and fw_reg_rd(128)!=0 # FW Date 20190429 and later + + lanes = get_lane_list(lane) + eyes = {} + for ln in lanes: + get_lane_mode(ln) + line_encoding = lane_mode_list[ln].lower() + c = Pam4Reg if line_encoding == 'pam4' else NrzReg + x = 100 if line_encoding == 'pam4' else 200 + rdy = sum(ready(ln)[ln]) + em=[-1,-1,-1] + if line_encoding == 'pam4' and rdy == 3: + ####### FW-based PAM4 Eye margin + # if FW is loaded and the Background FW is not paused + # if fw_loaded and fw_pause(print_en=0)[0][2] == 1: + if fw_eye_en == True: + fw_debug_cmd(section=10, index=5, lane=ln) + em = [rreg(0x9f00+eye_index) for eye_index in range(3)] + eyes[ln] = em[0], em[1], em[2] + ####### SW-based PAM4 Eye margin. Direct access to HW registers + else: + eye_margin = [] + dac_val = dac(lane=ln)[ln] + for eye_index in range (3): + result1 = 0xffff + for y in range (4): + sel = 3 * y + eye_index + wreg(c.rx_minus_margin_sel_addr, sel, ln) + wreg(c.rx_plus_margin_sel_addr, sel, ln) + plus_margin = rreg(c.rx_plus_margin_addr, ln) + if (plus_margin > 0x7ff): + plus_margin = plus_margin - 0x1000 + minus_margin = (rreg(c.rx_minus_margin_addr, ln)) + if (minus_margin > 0x7ff): + minus_margin = minus_margin - 0x1000 + diff = plus_margin - minus_margin + if ( diff < result1): + result1 = diff + # else: + # result1 = result1 + #result1 = result1 + diff + eye_margin.append((result1)) + em0 = (float(eye_margin[0])/2048.0) * (x + (50.0 * float(dac_val))) + em1 = (float(eye_margin[1])/2048.0) * (x + (50.0 * float(dac_val))) + em2 = (float(eye_margin[2])/2048.0) * (x + (50.0 * float(dac_val))) + eyes[ln] = em0, em1, em2 + return eyes + #################################################################################################### +# Resets the PRBS Error Counter for the selected lane +# +#################################################################################################### +def prbs_rst(lane = None): + lanes = get_lane_list(lane) + for lane in lanes: + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + wreg(c.rx_err_cntr_rst_addr, 0, lane) + time.sleep(0.001) + wreg(c.rx_err_cntr_rst_addr, 1, lane) + time.sleep(0.001) + wreg(c.rx_err_cntr_rst_addr, 0, lane) + + +#################################################################################################### +# Collects the PRBS Error Counter for the selected lane +# +# It resets the counter first if rst=1 +#################################################################################################### +def get_prbs(lane = None, rst=0, print_en=1): + lanes = get_lane_list(lane) + + ###### 1. Clear Rx PRBS Counter for these lanes, if requested + if (rst==1): + prbs_rst(lane=lanes) + + result = {} + ###### 2. Capture PRBS Counter for this lane + for ln in lanes: + c = Pam4Reg if lane_mode_list[ln].lower() == 'pam4' else NrzReg + result[ln] = long(rreg(c.rx_err_cntr_msb_addr, ln)<<16) + rreg(c.rx_err_cntr_lsb_addr, ln) + + return result + +#################################################################################################### +# +# flips the RX polarity, but user can ask to flip the TX polarity instead +# +#################################################################################################### +def flip_pol(lane=None, port='rx', print_en=1): + + if lane is None and (type(lane)!=int or type(lane)!=list): + print("\n ...Usage.................................................................") + print("\n flip_pol (lane=0) # flip RX polarity of lane 0"), + print("\n flip_pol (lane=0, port='rx') # flip RX polarity of lane 0"), + print("\n flip_pol (lane=0, port='TX') # flip TX polarity of lane 0"), + print("\n flip_pol (lane=[0,3,5]) # flip RX polarities of lanes 0, 3 and 5"), + print("\n .........................................................................") + return + + lanes = get_lane_list(lane) + result={} + for ln in lanes: + orig_tx_pol,orig_rx_pol = pol(lane=ln, print_en=0) + print("\nLane %d, TX Pol: (%d -> %d), RX Pol: (%d -> %d)"%(ln,orig_tx_pol,int(not orig_tx_pol),orig_rx_pol,int( not orig_rx_pol))), + if port.upper() != 'TX': # if asked to reverse RX Polarity (default selection) + new_tx_pol= orig_tx_pol + new_rx_pol= int(not orig_rx_pol) + else: # if asked to reverse TX Polarity + new_tx_pol= int(not orig_tx_pol) + new_rx_pol= orig_rx_pol + + pol(tx_pol=new_tx_pol, rx_pol= new_rx_pol, lane=ln, print_en=0) + + result[ln] = pol(lane=ln, print_en=0) + #print result[ln] + + if print_en: + pol(lane=range(len(lane_name_list)), print_en=1) + + if print_en==0: return result +#################################################################################################### +# +#################################################################################################### +def scan_lane_partner(slice=[0,1], lane='all', print_en=True): + + global gLanePartnerMap + + TX_lanes = get_lane_list(lane) + TX_slices = get_slice_list(slice) + rx_slices=[0,1] + rx_lanes=range(16) + rx_partner=[-1,-1] + + ### Create List for gLanePartnerMap + # tx_map_slice_lane=[] + # for slc in range(2): + # tx_map_slice_lane.append([]) + # for ln in range(16): + # tx_map_slice_lane[slc].append([]) + + ### Turn all target lanes' TX output + for TX_slc in TX_slices: + sel_slice(TX_slc) + tx_output(mode='on', lane=TX_lanes, print_en=0) + + if print_en: + print("\n Scanning for Lane Partners...\n"), + print("\n Slice_Lane Slice_Lane"), + print("\n TX <-----------> RX "), + + ### Loop through all target slices/lanes (and find each one's RX partner) + for TX_slc in TX_slices: + for TX_ln in TX_lanes: + if print_en: + if TX_ln%4==0: print ("") + print("\n [S%d_%s]"%(TX_slc,lane_name_list[TX_ln])), + num_lanes_checked=0 + lane_not_rdy_cnt=0 + ### Turn off this lane's TX + sel_slice(TX_slc) + tx_output(mode='off', lane=TX_ln, print_en=0) + + ### Search for RX partner of this TX + for rx_slc in rx_slices: + sel_slice(rx_slc) + rdy_rx_ln = {} + for rx_ln in rx_lanes: + rdy_rx_ln[rx_ln] = phy_rdy(rx_ln)[rx_ln] + #print("\n RX Slice %d Lane %d RDY = %d"%(rx_slc,rx_ln,rdy_rx_ln[rx_ln])), + if rdy_rx_ln[rx_ln]==0:# and lane_not_rdy_cnt==0: + rx_partner=[rx_slc,rx_ln] + conn = '<-LoopBack-->' if [rx_slc,rx_ln] == [TX_slc, TX_ln] else '<---Cable--->' + print ("%s [S%d_%s]" % (conn, rx_slc,lane_name_list[rx_ln])) + gLanePartnerMap[TX_slc][TX_ln] = [rx_slc,rx_ln] + lane_not_rdy_cnt+=1 + # else: + # print "\nSlice %d Lane %d" % (rx_slc,rx_ln), + num_lanes_checked+=1 + + ### Found this lane's partner. Turn its TX back on. Wait for its partner's RX to come ready before moving on to next TX_lane + sel_slice(TX_slc) + tx_output(mode='on', lane=TX_ln, print_en=0) + start=time.time() + wait_time=time.time()-start + sel_slice(rx_partner[0]) + while phy_rdy(rx_partner[1])[rx_partner[1]] == 0: + wait_time=time.time()-start + if wait_time>2.0: + break + if print_en and lane_not_rdy_cnt!=1: + print(" (%d found for this lane, wait time = %2.1f)"%(lane_not_rdy_cnt, wait_time)), + if print_en==0: + return gLanePartnerMap +#################################################################################################### +# Automatically determines the correct polarity of the RX input, based on PRBS Error Counter +# +# By default flips the RX polarity if detects a wrong polarity, but user can ask to flip the TX polarity instead +# +#################################################################################################### +def auto_pol(port='rx', tx_prbs='en', print_en=1): + #print'here' + lanes = range(0,16) #get_lane_list(lane) + #get_lane_mode(lanes) + + result={} + + if print_en: + tx_gen = 'TX PRBS Gen Forced Enabled' if 'en' in tx_prbs else 'TX PRBS Gen NOT Forced Enabled' + print("\n\n...Slice %d Lanes %d-%d Auto Polarity with %s..."%(gSlice,lanes[0],lanes[-1], tx_gen)), + print("\n # Lane No: [A0.A1.A2.A3.A4.A5.A6.A7,B0.B1.B2.B3.B4.B5.B6.B7 ]"), + if port.upper() != 'TX': + print("\nRxPolarityMap.append([]); RxPolarityMap[%d]=["%(gSlice) ), + else: + print("\nTxPolarityMap.append([]); TxPolarityMap[%d]=["%(gSlice) ), + + # Make sure both PRBS TX Generator and RX Checker are enabled and both are set to PRBS31 + for ln in lanes: + get_lane_mode(ln) + #c = Pam4Reg if lane_mode_list[ln].lower() == 'pam4' else NrzReg + + tx_prbs_gen_en = rreg([0x0a0,[14]],ln) # NRZ/PAM4 mode, PRBS Gen clock en + #rx_prbs_checker_en = rreg([0x043, [3]],ln) if c==Pam4Reg else rreg([0x161,[10]],ln) # PAM4 or NRZ mode, PRBS Sync Checker powered up + if (tx_prbs =='en' and tx_prbs_gen_en==0): # or rx_prbs_checker_en==0: + prbs_mode_select(lane=ln, prbs_mode='prbs') + + for ln in lanes: + #c = Pam4Reg if lane_mode_list[ln].lower() == 'pam4' else NrzReg + + if (tx_prbs =='en'): + prbs_mode_select(lane=ln, prbs_mode='prbs') + + ##Clear and read Rx PRBS Counter for this lane + prbs_cnt_before = get_prbs(lane = ln, rst=1, print_en=0)[ln] + + orig_tx_pol,orig_rx_pol = pol(tx_pol=None, rx_pol=None, lane=ln, print_en=0) + + if port.upper() != 'TX': # if asked to reverse RX Polarity (default selection) + pol(tx_pol= orig_tx_pol, rx_pol=(int(not orig_rx_pol)), lane=ln, print_en=0) + else: # if asked to reverse TX Polarity + pol(tx_pol=(int(not orig_tx_pol)), rx_pol= orig_rx_pol, lane=ln, print_en=0) + + prbs_cnt_after = get_prbs(lane = ln, rst=1, print_en=0)[ln] + + if (prbs_cnt_before==0) or (prbs_cnt_before * 10 <= prbs_cnt_after): # if at least one order not improved, keep the orginal polarity + pol(tx_pol= orig_tx_pol, rx_pol=orig_rx_pol, lane=ln, print_en=0) + + result[ln] = pol(tx_pol=None, rx_pol=None, lane=ln, print_en=0) + + #print prbs_cnt_before, prbs_cnt_after + if print_en: + if port.upper() != 'TX': + if ln != lanes[-1]: print('%d,'%(result[ln][1])), + else: print('%d' %(result[ln][1])), + else: + if ln != lanes[-1]: print('%d,'%(result[ln][0])), + else: print('%d' %(result[ln][0])), + + #### Update the global polarity array for this Slice, os it can be used next time init() is called + for ln in lanes: + if port.upper() != 'TX': + RxPolarityMap[gSlice][ln]=result[ln][1] # gSlice lanes, RX Polarity + else: + TxPolarityMap[gSlice][ln]=result[ln][0] # gSlice lanes, TX Polarity + + if print_en: + print("] # Slice %d lanes, %s Polarity"%(gSlice,port.upper()) ) + else: + return result + +#################################################################################################### +# flips RX or TX polarities until fec_status is clean +# +# call this only when set up in Gearbox mode +# +#################################################################################################### +def auto_pol_fec(port='rx',lanes=range(0,16),print_en=1): + #get_lane_list(lane) + #get_lane_mode(lanes) + + result={} + + if print_en: + print("\n # Lane No: [A0.A1.A2.A3.A4.A5.A6.A7,B0.B1.B2.B3.B4.B5.B6.B7 ]"), + if port.upper() != 'TX': + print("\nRxPolarityMap.append([]); RxPolarityMap[%d]=["%(gSlice) ), + else: + print("\nTxPolarityMap.append([]); TxPolarityMap[%d]=["%(gSlice) ), + + + for ln in lanes: + get_lane_mode(ln) + #c = Pam4Reg if lane_mode_list[ln].lower() == 'pam4' else NrzReg + if port.upper() != 'TX': + ##read FEC Status and FIFO Counters for this gearbox + overall_fec_stat, fec_statistics = fec_status(print_en=0) + + # if FEC Status is clean, done + if not (-1 in overall_fec_stat): + break + + fw_reg_wr(9,0x0000) # disable gearbox FW top control + fw_reg_wr(8,0x0000) # disable FW PHY adaptation control + #### 1 #### start with set all polarities to default pol(1,0) + #### if all B-side adapt-done=1, flip RX pol until all FEC AMlock bits are '1' + #### if all A-side adapt-done=1, flip RX pol until all FEC AMlock bits are '1' + #### if any of A-side or B-side adapt-done=0, go to next and set FW-reg8=0xFFFF + + fw_reg_wr(9,0x0000) # disable gearbox FW top control + fw_reg_wr(8,0xffff) # enable FW PHY adaptation control + #### 2 #### flip RX polarities until all lanes' RX adapt-done. If A-side adapt-done=0, wait long enough for it + + fw_reg_wr(9,0xffff) # enable back gearbox FW top control + fw_reg_wr(8,0x0000) # disable FW PHY adaptation control + #### 3 #### flip RX polarities until all remaining FEC AMlock bits are '1' + + fw_reg_wr(9,0xffff) # enable back gearbox FW top control + fw_reg_wr(8,0xffff) # enable FW PHY adaptation control + #### 4 #### wait until all remaining FEC FIFO pointers fall into place + #else: + #### 5 #### flip TX polarities if partner FEC is not locked + + #orig_tx_pol,orig_rx_pol = pol(tx_pol=None, rx_pol=None, lane=ln, print_en=0) + + if port.upper() != 'TX': # if asked to reverse RX Polarity (default selection) + #pol(tx_pol= orig_tx_pol, rx_pol=~orig_rx_pol, lane=ln, print_en=0) + flip_pol(lane=ln, port='rx', print_en=1) + else: # if asked to reverse TX Polarity + #pol(tx_pol=~orig_tx_pol, rx_pol= orig_rx_pol, lane=ln, print_en=0) + flip_pol(lane=ln, port='tx', print_en=1) + + #prbs_cnt_after = get_prbs(lane = ln, rst=1, print_en=0)[ln] + + #if (prbs_cnt_before==0) or (prbs_cnt_before * 10 <= prbs_cnt_after): # if at least one order not improved, keep the orginal polarity + # pol(tx_pol= orig_tx_pol, rx_pol=orig_rx_pol, lane=ln, print_en=0) + + result[ln] = pol(tx_pol=None, rx_pol=None, lane=ln, print_en=0) + + #print prbs_cnt_before, prbs_cnt_after + if print_en: + if port.upper() != 'TX': + if ln != lanes[-1]: print('%d,'%(result[ln][1])), + else: print('%d' %(result[ln][1])), + else: + if ln != lanes[-1]: print('%d,'%(result[ln][0])), + else: print('%d' %(result[ln][0])), + + #### Update the global polarity array for this Slice, os it can be used next time init() is called + for ln in lanes: + if port.upper() != 'TX': + RxPolarityMap[gSlice][ln]=result[ln][1] # gSlice lanes, RX Polarity + else: + TxPolarityMap[gSlice][ln]=result[ln][0] # gSlice lanes, TX Polarity + + if print_en: + print("] # Slice %d lanes, %s Polarity"%(gSlice,port.upper()) ) + else: + return result + +#################################################################################################### +def rx_prbs_mode(patt = None, lane = None): + lanes = get_lane_list(lane) + nrz_prbs_pat = ['PRBS9', 'PRBS15', 'PRBS23', 'PRBS31'] + pam4_prbs_pat = ['PRBS9', 'PRBS13', 'PRBS15', 'PRBS31'] + result = {} + for lane in lanes: + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + if patt is None: + checker = rx_checker(lane=lane)[lane] + patt_v = rreg(c.rx_prbs_mode_addr, lane) + if lane_mode_list[lane].lower() == 'pam4': + pat_sel = pam4_prbs_pat[patt_v] + else: + pat_sel = nrz_prbs_pat[patt_v] + result[lane] = checker, pat_sel + elif type(patt) == int: + rx_checker(1,lane) + wreg(c.rx_prbs_mode_addr, patt, lane) + elif type(patt) == str: + val = pam4_prbs_pat.index(patt) if gPam4_En else nrz_prbs_pat.index(patt) + rx_checker(1,lane) + wreg(c.rx_prbs_mode_addr, val, lane) + # else: + if result != {}: return result +def rx_checker(status = None, lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + if status is None: + result[lane] = rreg(c.rx_prbs_checker_pu_addr, lane) + else: + wreg(c.rx_prbs_checker_pu_addr, status, lane) + # else: + if result != {}: return result + +##################################################################################################### +# Command to Disable (Squelch) or Enable (Unsquelch) TX output +# +# 'Disable' means put TX output in electrical idle mode +# +#################################################################################################### +def tx_output(mode=None,lane=None, print_en=1): + + hw_tx_control_addr = 0xA0 + + output_en_list = ['ON','EN','UNSQ','UNSQUELCH'] + output_dis_list = ['OFF','DIS','SQ','SQUELCH'] + mode_list= ['EN','dis'] + + lanes = get_lane_list(lane) + result = {} + + if print_en: print("\n------------------------------"), + if print_en: print(" Slice %d TX Output En or Dis Status Per Lane"%gSlice), + if print_en: print(" ------------------------------"), + if print_en: print("\n Lane:"), + if print_en: + for ln in range(16): + print(" %4s" %(lane_name_list[ln])), + + if mode!=None: # Command to dis/en certain lanes' TX output + for ln in lanes: + if any(i in mode.upper() for i in output_en_list): + wreg([hw_tx_control_addr,[15]],1, ln) # stop using test pattern 0x0000 + wreg([hw_tx_control_addr,[14]],1, ln) # stop using test pattern 0x0000 + wreg([hw_tx_control_addr,[13]],1, ln) # stop using test pattern 0x0000 + if any(i in mode.upper() for i in output_dis_list): + wreg(c.tx_test_patt4_addr, 0x0000, ln) + wreg(c.tx_test_patt3_addr, 0x0000, ln) + wreg(c.tx_test_patt2_addr, 0x0000, ln) + wreg(c.tx_test_patt1_addr, 0x0000, ln) + wreg([hw_tx_control_addr,[15]],0, ln) # use test pattern = 0x0000 to output electrical idle pattern + wreg([hw_tx_control_addr,[14]],0, ln) # use test pattern = 0x0000 to output electrical idle pattern + wreg([hw_tx_control_addr,[13]],1, ln) # use test pattern = 0x0000 to output electrical idle pattern + + + for ln in range(16): # Read TX Output On/Off HW Register bit + status2=rreg(hw_tx_control_addr,ln) + status1=rreg([hw_tx_control_addr,[13]],ln) + result[ln]=status1,status2 + + if print_en: # Print Status + print("\n TX Output :"), + for ln in range(16): + print(" %4s" %(mode_list[result[ln][0]])), + print("\n TX Reg 0xA0:"), + for ln in range(16): + print(" %04X" %(result[ln][1])), + else: + return result + +#################################################################################################### +def tx_status(mode='func', lane = None): # mode= (1) 'off' or 'idle', (2) 'on' or 'func' or 'functional', (3) 'prbs' + lanes = get_lane_list(lane) + c = Pam4Reg + for lane in lanes: + #### OFF + if mode.upper() == 'OFF' or mode.upper() == 'IDLE': # test pattern mode =0000 + wreg(c.tx_test_patt4_addr, 0x0000, lane) + wreg(c.tx_test_patt3_addr, 0x0000, lane) + wreg(c.tx_test_patt2_addr, 0x0000, lane) + wreg(c.tx_test_patt1_addr, 0x0000, lane) + wreg(c.tx_test_patt_sc_addr, 0, lane) # 0xA0[15]=0, TX test signal source = Test pattern memory, not PRBS generator + wreg(c.tx_test_patt_en_addr, 1, lane) # 0xA0[13]=1, TX data = test data, not traffic data + wreg(c.tx_prbs_clk_en_addr, 0, lane) # 0xA0[14]=0, TX PAM4 PRBS Gen Clock disabled + wreg(c.tx_prbs_en_addr, 0, lane) # 0xA0[11]=0, TX PAM4 PRBS Gen disabled + wreg(c.tx_prbs_clk_en_nrz_addr,0, lane) # 0xb0[14]=0, TX NRZ PRBS gen clock disabled + wreg(c.tx_prbs_en_nrz_addr, 0, lane) # 0xb0[11]=0, TX NRZ PRBS gen disabled + #### PRBS + elif 'PRBS' in mode.upper(): + wreg(c.tx_test_patt_sc_addr, 1, lane) # 0xA0[15]=1, TX test signal source = Test pattern memory, not PRBS generator + wreg(c.tx_test_patt_en_addr, 1, lane) # 0xA0[13]=1, TX data = test data, not functional/traffic mode + wreg(c.tx_prbs_clk_en_addr, 1, lane) # 0xA0[14]=1, TX PAM4 PRBS GEN Clock enabled + wreg(c.tx_prbs_en_addr, 1, lane) # 0xA0[11]=1, TX PAM4 PRBS Gen enabled + wreg(c.tx_prbs_clk_en_nrz_addr,1, lane) # 0xb0[14]=0, TX NRZ PRBS gen clock disabled + wreg(c.tx_prbs_en_nrz_addr, 1, lane) # 0xb0[11]=1, TX NRZ PRBS gen enabled + #### FUNCTIONAL (normal traffic mode) + else: + wreg(c.tx_test_patt_sc_addr, 0, lane) # 0xA0[15]=0, TX test signal source = not PRBS generator + wreg(c.tx_test_patt_en_addr, 0, lane) # 0xA0[13]=0, TX data = functional mode, not test data + wreg(c.tx_prbs_clk_en_addr, 0, lane) # 0xA0[14]=0, TX PAM4 PRBS Gen CLock disabled + wreg(c.tx_prbs_en_addr, 0, lane) # 0xA0[11]=0, TX PAM4 PRBS Gen disabled + wreg(c.tx_prbs_clk_en_nrz_addr,0, lane) # 0xb0[14]=0, TX NRZ PRBS gen clock disabled + wreg(c.tx_prbs_en_nrz_addr, 0, lane) # 0xb0[11]=0, TX NRZ PRBS gen disabled + +#################################################################################################### +def tx_test_patt(en=None, lane = None, tx_test_patt4_val=0x0000,tx_test_patt3_val=0x0000,tx_test_patt2_val=0x0000,tx_test_patt1_val=0x0000): + lanes = get_lane_list(lane) + c = Pam4Reg + result = {} + for lane in lanes: + if en is None: + prbs_en = rreg(c.tx_prbs_en_addr, lane) + test_patt_en = rreg(c.tx_test_patt_en_addr, lane) + prbs_clk_en = rreg(c.tx_prbs_clk_en_addr, lane) + test_patt_sc = rreg(c.tx_test_patt_sc_addr, lane) + val = prbs_en & test_patt_en & prbs_clk_en & (1-test_patt_sc) + result[lane] = val + elif en == 1: + # test pattern mode + wreg(c.tx_test_patt_en_addr, en, lane) + wreg(c.tx_test_patt_sc_addr, 1-en, lane) + wreg(c.tx_test_patt4_addr, tx_test_patt4_val, lane) + wreg(c.tx_test_patt3_addr, tx_test_patt3_val, lane) + wreg(c.tx_test_patt2_addr, tx_test_patt2_val, lane) + wreg(c.tx_test_patt1_addr, tx_test_patt1_val, lane) + else: + # normal traffic mode + wreg(c.tx_test_patt_en_addr, 0x0, lane) + # else: + if result != {}: return result + +#################################################################################################### +def tx_prbs_en(en = None, lane = None): + lanes = get_lane_list(lane) + c = Pam4Reg + result = {} + for lane in lanes: + if en is None: + prbs_en = rreg(c.tx_prbs_en_addr, lane) + test_patt_en = rreg(c.tx_test_patt_en_addr, lane) + prbs_clk_en = rreg(c.tx_prbs_clk_en_addr, lane) + test_patt_sc = rreg(c.tx_test_patt_sc_addr, lane) + val = prbs_en & test_patt_en & prbs_clk_en & test_patt_sc + result[lane] = val + else: + wreg(c.tx_prbs_en_addr, en, lane) + wreg(c.tx_test_patt_en_addr, en, lane) + wreg(c.tx_prbs_clk_en_addr, en, lane) + wreg(c.tx_test_patt_sc_addr, en, lane) + +#################################################################################################### +def tx_prbs_mode(patt = None, lane = None): + lanes = get_lane_list(lane) + c = Pam4Reg + result = {} + nrz_prbs_pat = ['PRBS9', 'PRBS15', 'PRBS23', 'PRBS31'] + pam4_prbs_pat = ['PRBS9', 'PRBS13', 'PRBS15', 'PRBS31'] + for lane in lanes: + if patt is None: + prbs_en = rreg(c.tx_prbs_en_addr, lane) + test_patt_en = rreg(c.tx_test_patt_en_addr, lane) + prbs_clk_en = rreg(c.tx_prbs_clk_en_addr, lane) + test_patt_sc = rreg(c.tx_test_patt_sc_addr, lane) + patt_v = rreg(c.tx_prbs_patt_sel_addr, lane) + if lane_mode_list[lane].lower() == 'pam4': + pat_sel = pam4_prbs_pat[patt_v] + else: + pat_sel = nrz_prbs_pat[patt_v] + result[lane] = (prbs_en & test_patt_en & prbs_clk_en & test_patt_sc, pat_sel) + elif type(patt) == int: + tx_prbs_en(0, lane) + wreg(c.tx_prbs_patt_sel_addr, patt, lane) + tx_prbs_en(1, lane) + elif type(patt) == str: + tx_prbs_en(0, lane) + val = pam4_prbs_pat.index(patt) if lane_mode_list[lane].lower() == 'pam4' else nrz_prbs_pat.index(patt) + wreg(c.tx_prbs_patt_sel_addr, val, lane) + tx_prbs_en(1, lane) + #else: + if result != {}: return result + +#################################################################################################### +def err_inject(lane = None): + lanes = get_lane_list(lane) + c = Pam4Reg + for lane in lanes: + wreg(c.tx_prbs_1b_err_addr, 0x0, lane) + time.sleep(0.001) + wreg(c.tx_prbs_1b_err_addr, 0x1, lane) + time.sleep(0.001) + wreg(c.tx_prbs_1b_err_addr, 0x0, lane) + +#################################################################################################### +def tx_taps(tap1 = None,tap2 = None,tap3 = None, tap4 = None, tap5 = None, tap6 = None, tap7 = None, tap8 = None, tap9 = None, tap10 = None, tap11 = None, lane = None): + lanes = get_lane_list(lane) + c = Pam4Reg + result = {} + for lane in lanes: + if tap1 is tap2 is tap3 is tap4 is tap5 is tap6 is tap7 is tap8 is tap9 is tap10 is tap11 is None: + tap1_v = twos_to_int(rreg(c.tx_tap1_addr, lane), 8) + tap2_v = twos_to_int(rreg(c.tx_tap2_addr, lane), 8) + tap3_v = twos_to_int(rreg(c.tx_tap3_addr, lane), 8) + tap4_v = twos_to_int(rreg(c.tx_tap4_addr, lane), 8) + tap5_v = twos_to_int(rreg(c.tx_tap5_addr, lane), 8) + tap6_v = twos_to_int(rreg(c.tx_tap6_addr, lane), 4) + tap7_v = twos_to_int(rreg(c.tx_tap7_addr, lane), 4) + tap8_v = twos_to_int(rreg(c.tx_tap8_addr, lane), 4) + tap9_v = twos_to_int(rreg(c.tx_tap9_addr, lane), 4) + tap10_v = twos_to_int(rreg(c.tx_tap10_addr, lane), 4) + tap11_v = twos_to_int(rreg(c.tx_tap11_addr, lane), 4) + result[lane] = tap1_v, tap2_v, tap3_v, tap4_v, tap5_v, tap6_v, tap7_v, tap8_v, tap9_v, tap10_v, tap11_v + else: + if tap1 != None: wreg(c.tx_tap1_addr, int_to_twos(tap1,8), lane) + if tap2 != None: wreg(c.tx_tap2_addr, int_to_twos(tap2,8), lane) + if tap3 != None: wreg(c.tx_tap3_addr, int_to_twos(tap3,8), lane) + if tap4 != None: wreg(c.tx_tap4_addr, int_to_twos(tap4,8), lane) + if tap5 != None: wreg(c.tx_tap5_addr, int_to_twos(tap5,8), lane) + if tap6 != None: wreg(c.tx_tap6_addr, int_to_twos(tap6,4), lane) + if tap7 != None: wreg(c.tx_tap7_addr, int_to_twos(tap7,4), lane) + if tap8 != None: wreg(c.tx_tap8_addr, int_to_twos(tap8,4), lane) + if tap9 != None: wreg(c.tx_tap9_addr, int_to_twos(tap9,4), lane) + if tap10 != None: wreg(c.tx_tap10_addr, int_to_twos(tap10,4), lane) + if tap11 != None: wreg(c.tx_tap11_addr, int_to_twos(tap11,4), lane) + #else: + if result != {}: return result + +#################################################################################################### +def tx_taps_rule_check(lane = None): + lanes = get_lane_list(lane) + c = Pam4Reg + result = {} + for lane in lanes: + taps = tx_taps(lane = lane)[lane] + taps = [abs(taps[i]) for i in range(len(taps))] + hf = rreg(c.tx_taps_hf_addr, lane) + tx_taps_sum = sum(taps)/2.0 + sum([taps[i]*((hf>>i)&1) for i in range(5)])/2.0 + result[lane] = (tx_taps_sum <= c.tx_taps_sum_limit), tx_taps_sum + #else: + if result != {}: return result +#################################################################################################### +def tx(lane = None): + lanes = get_lane_list(lane) + for lane in lanes: + test_patt_en = tx_test_patt(lane = lane)[lane] + prbs_en, prbs_sel = tx_prbs_mode(lane = lane)[lane] + taps = tx_taps(lane = lane)[lane] + sum = tx_taps_rule_check(lane = lane)[lane][-1] + print ("%s, PRBS enable: %s %s, test pattern enable: %s, taps: %s, %d"%(lane_name_list[lane], bool(prbs_en), prbs_sel, bool(test_patt_en), ','.join((map(str,taps))), sum)) + +#################################################################################################### +# +# tx_sj( A = 6 ,f = 20, lane = 0 ) +# +#################################################################################################### +def tx_sj( A = 0.3, f = 2500, lane = None): + lanes = get_lane_list(lane) + result = {} + + if (A!=None and A>0.0): + sj_en = 1 + elif (A!=None): + sj_en = 0 + + + if A!=None: + for ln in lanes: + if sj_en: + tx_sj_en(en=1,lane=ln) + tx_sj_ampl(A,ln) + tx_sj_freq(f,ln) + else: # Disable SJ + tx_sj_en(en=0,lane=ln) + + for ln in lanes: + sj_en_status = 'dis' if rregBits(0xf3,[5],ln)==1 else 'en' + sj_amp =float(rregBits(0xf9,[15,13],ln))+ (float(rregBits(0xf9,[12,5],ln))/256.0) + sj_freq=int(float(rregBits(0xf5,[15,2],ln)) * 3.2) + result[ln]=sj_en_status,sj_amp,sj_freq + + return result +#################################################################################################### +def tx_sj_range( A = 3, lane = 0): + tx_sj_en(en=1,lane=lane) + tx_sj_ampl(A,lane) + wregBits(0xf5,[15,2],0x3fff,lane) # sj_freq = max + +#################################################################################################### +def tx_sj_en( en=1,lane=0): + if en: + wregBits(0xf4,[0],0,lane) # disable TRF before enabling injecting SJ + wregBits(0xf3,[5],0,lane) # enable tx_rotator to inject SJ + else: # Disable SJ + wregBits(0xf3,[5],1,lane) # disable tx_rotator + tx_sj_ampl(A=0,lane=lane) # sj_ampl_0123 = 0 + tx_sj_freq(f=0,lane=lane) # sj_freq = 0 + + return en +#################################################################################################### +def tx_sj_ampl( A = 3, lane = 0 ): + addr = [0xf9,0xf8,0xf7,0xf6] # sj_ampl_0/1/2/3 + # sj_ampl_cos_0, sj_ampl_cos_1, sj_ampl_cos_2, sj_ampl_cos_3 + phase_value =[math.cos(0), math.cos((math.pi)/8), math.cos((math.pi)/4), math.cos(3*(math.pi)/8)] + for i in range(4): + value = A*phase_value[i] + int_A = int(value) + float_A = dec2bin(value - int_A) + wregBits(addr[i],[15,13], int_A,lane) + wregBits(addr[i],[12,5],float_A,lane) + +#################################################################################################### +def tx_sj_freq( f = 250, lane = 0): + data_f = int(round((f/3.2),0)) + wregBits(0xf5,[15,2],data_f,lane) # sj_freq value + + +def wait_rdy(lane = None, t = 1): + lanes = get_lane_list(lane) + i = 0 + while(i7: + ctle1_w = ctle1 - 8 + wreg([0x1d7,[3]],1,ln) + else: + ctle1_w = ctle1 + wreg([0x1d7,[3]],0,ln) + + if ctle2>7: + ctle2_w = ctle2 - 8 + wreg([0x1d7,[2]],1,ln) + else: + ctle2_w = ctle2 + wreg([0x1d7,[2]],0,ln) + ctle_map(ctle, ctle1_w, ctle2_w, lane=ln) + + #else: + if result != {}: return result + +def skef(en = None, val = None, lane = None): + lanes = get_lane_list(lane) + result = {} + c = Pam4Reg + for lane in lanes: + if en is None: + en_v = rreg(c.rx_skef_en_addr, lane) + v = rreg(c.rx_skef_degen_addr, lane) + result[lane] = en_v, v + else: + wreg(c.rx_skef_degen_addr, val, lane) + wreg(c.rx_skef_en_addr, en, lane) + #else: + if result != {}: return result + +def agcgain(agcgain1 = None, agcgain2 = None, lane = None): + lanes = get_lane_list(lane) + result = {} + c = Pam4Reg + for lane in lanes: + if agcgain1 is agcgain2 is None: + agcgain1_v = Gray_Bin(rreg(c.rx_agcgain1_addr, lane)) + agcgain2_v = Gray_Bin(rreg(c.rx_agcgain2_addr, lane)) + result[lane] = agcgain1_v, agcgain2_v + else: + if agcgain1 != None: + wreg(c.rx_agcgain1_addr, Bin_Gray(agcgain1), lane) + if agcgain2 != None: + wreg(c.rx_agcgain2_addr, Bin_Gray(agcgain2), lane) + #else: + if result != {}: return result + +def ffegain(ffegain1 = None, ffegain2 = None, lane = None): + lanes = get_lane_list(lane) + result = {} + c = Pam4Reg + for lane in lanes: + if ffegain1 is ffegain2 is None: + ffegain1_v = Gray_Bin(rreg(c.rx_ffe_sf_msb_addr, lane)) + ffegain2_v = Gray_Bin(rreg(c.rx_ffe_sf_lsb_addr, lane)) + result[lane] = ffegain1_v, ffegain2_v + else: + if ffegain1 != None: + wreg(c.rx_ffe_sf_msb_addr, Bin_Gray(ffegain1), lane) + if ffegain2 != None: + wreg(c.rx_ffe_sf_lsb_addr, Bin_Gray(ffegain2), lane) + #else: + if result != {}: return result + +def dc_gain(agcgain1=None, agcgain2=None, ffegain1=None, ffegain2=None, lane=None): + if agcgain1 is agcgain2 is ffegain1 is ffegain2 is None: + agcgain_val = agcgain(lane=lane) + ffegain_val = ffegain(lane=lane) + result = {} + for i in agcgain_val.keys(): + result[i] = agcgain_val[i][0], agcgain_val[i][1], ffegain_val[i][0], ffegain_val[i][1] + #else: + if result != {}: return result + else: + if agcgain1 != None or agcgain2 != None: + agcgain(agcgain1, agcgain2, lane) + if ffegain1 != None or ffegain2 != None: + ffegain(ffegain1, ffegain2, lane) + +def ctle_map(sel = None, val1 = None, val2 = None, lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + if None in (sel, val1, val2): + map0 = rreg(c.rx_agc_map0_addr, lane) + map1 = rreg(c.rx_agc_map1_addr, lane) + map2 = rreg(c.rx_agc_map2_addr, lane) + agc = { 0: [map0>>13, (map0>>10) & 0x7], + 1: [(map0>>7) & 0x7, (map0>>4) & 0x7], + 2: [(map0>>1) & 0x7, ((map0 & 0x1)<<2) + (map1>>14)], + 3: [(map1>>11) & 0x7, (map1>>8) & 0x7], + 4: [(map1>>5) & 0x7, (map1>>2) & 0x7], + 5: [((map1 & 0x3)<<1) + (map2>>15), (map2>>12) & 0x7], + 6: [(map2>>9) & 0x7, (map2>>6) & 0x7], + 7: [(map2>>3) & 0x7, map2 & 0x7] + } + if sel is None: + result[lane] = agc + else: + result[lane] = agc[sel] + else: + if sel != 2 and sel != 5: + val = (val1<<3) + val2 + if sel == 0: + map0 = (rreg(c.rx_agc_map0_addr, lane) | 0xfc00) & (val<<10 | 0x3ff) + wreg(c.rx_agc_map0_addr, map0, lane) + elif sel == 1: + map0 = (rreg(c.rx_agc_map0_addr, lane) | 0x03f0) & (val<<4 | 0xfc0f) + wreg(c.rx_agc_map0_addr, map0, lane) + elif sel == 3: + map1 = (rreg(c.rx_agc_map1_addr, lane) | 0x3f00) & (val<<8 | 0xc0ff) + wreg(c.rx_agc_map1_addr, map1, lane) + elif sel == 4: + map1 = (rreg(c.rx_agc_map1_addr, lane) | 0x00fc) & (val<<2 | 0xff03) + wreg(c.rx_agc_map1_addr, map1, lane) + elif sel == 6: + map2 = (rreg(c.rx_agc_map2_addr, lane) | 0x0fc0) & (val<<6 | 0xf03f) + wreg(c.rx_agc_map2_addr, map2, lane) + elif sel == 7: + map2 = (rreg(c.rx_agc_map2_addr, lane) | 0x003f) & (val | 0xffc0) + wreg(c.rx_agc_map2_addr, map2, lane) + elif sel == 2: + val = (val1<<1) + ((val2 & 0x4)>>2) + map0 = (rreg(c.rx_agc_map0_addr, lane) | 0x000f) & (val | 0xfff0) + wreg(c.rx_agc_map0_addr, map0, lane) + val = val2 & 0x3 + map1 = (rreg(c.rx_agc_map1_addr, lane) | 0xc000) & ((val<<14) | 0x3fff) + wreg(c.rx_agc_map1_addr, map1, lane) + else:# sel == 5: + val = (val1 >>1 & 0x3) + map1 = (rreg(c.rx_agc_map1_addr, lane) & 0xfffc) | (val & 0x0003) + wreg(c.rx_agc_map1_addr, map1, lane) + val = ((val1 & 0x1)<<3) + val2 + #map2 = (rreg(c.rx_agc_map2_addr, lane) | 0xf) & ((val<<12) | 0x0fff) + map2 = (rreg(c.rx_agc_map2_addr, lane) & 0x0fff) | ((val<<12) & 0xf000) + wreg(c.rx_agc_map2_addr, map2, lane) + #else: + if result != {}: + if sel is None: + for key in range(8): + print (key) + for lane in lanes: + print (result[lane][key]) + print (' ') + else: + return result + + +def delta(val = None, lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + if val is None: + result[lane] = twos_to_int(rreg(c.rx_delta_addr, lane), 7) + else: + wreg(c.rx_delta_ow_addr, int_to_twos(val, 7), lane) + wreg(c.rx_delta_owen_addr, 0x1, lane) + #else: + if result != {}: return result + +def dac(val = None, lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + get_lane_mode(lane) + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + if val != None: + wreg(c.rx_dac_ow_addr, val, lane) + wreg(c.rx_dac_owen_addr, 1, lane) + + dac_v = rreg(c.rx_dac_addr, lane) + result[lane] = dac_v + #else: + if result != {}: return result +def kp(val = None, lane = None, print_en=1): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + get_lane_mode(ln) + c = Pam4Reg if lane_mode_list[ln].lower() == 'pam4' else NrzReg + if val != None: + wreg(c.rx_kp_ow_addr, val, ln) + wreg(c.rx_kp_owen_addr, 1, ln) + + ted_v = rreg(c.rx_ted_en_addr, ln) + kp_v = rreg(c.rx_kp_ow_addr, ln) + result[ln] = ted_v, kp_v + + if print_en: # Print Status + print("\nSlice %d, Lane:"%(sel_slice())), + for ln in range(len(lane_name_list)): + print(" %2s" %(lane_name_list[ln])), + get_lane_mode('all') + print("\n CDR TED:"), + for ln in range(len(lane_name_list)): + c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + ted_v = rreg(c.rx_ted_en_addr, ln) + if lane_mode_list[ln] == 'pam4': + print(" %2d" %(ted_v)), + else: + print(" -"), + + print("\n CDR Kp :"), + for ln in range(len(lane_name_list)): + c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + kp_v = rreg(c.rx_kp_ow_addr, ln) + print(" %2d" %(kp_v)), + else: + if result != {}: return result + +def ted(val = None, lane = None, print_en=1): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + #get_lane_mode(ln) + c = Pam4Reg + if val != None: + wreg(c.rx_ted_en_addr, val, ln) + + ted_v = rreg(c.rx_ted_en_addr, ln) + kp_v = rreg(c.rx_kp_ow_addr, ln) + result[ln] = ted_v, kp_v + + if print_en: # Print Status + get_lane_mode('all') + print("\nSlice %d, Lane:"%(sel_slice())), + for ln in range(len(lane_name_list)): + print(" %2s" %(lane_name_list[ln])), + print("\n CDR TED:"), + for ln in range(len(lane_name_list)): + c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + ted_v = rreg(c.rx_ted_en_addr, ln) + if lane_mode_list[ln] == 'pam4': + print(" %2d" %(ted_v)), + else: + print(" -"), + print("\n CDR Kp :"), + for ln in range(len(lane_name_list)): + c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + kp_v = rreg(c.rx_kp_ow_addr, ln) + print(" %2d" %(kp_v)), + else: + if result != {}: return result + +def trf(val = None, lane = None, print_en=1): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + #get_lane_mode(ln) + #c = Pam4Reg + if val != None: + wreg([0xf4,[0]], val, ln) + + trf_v = rreg([0xf4,[0]], ln) + result[ln] = trf_v + + if print_en: # Print Status + get_lane_mode('all') + print("\nSlice %d, Lane:"%(sel_slice())), + for ln in range(len(lane_name_list)): + print(" %2s" %(lane_name_list[ln])), + print("\n TRF En:"), + for ln in range(len(lane_name_list)): + trf_v = rreg([0xf4,[0]], ln) + print(" %2d" %(trf_v)), + else: + if result != {}: return result + +def ready(lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + get_lane_mode(lane) + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + sd = rreg(c.rx_sd_addr, lane) + rdy = rreg(c.rx_rdy_addr, lane) + adapt_done=1 + if fw_loaded(print_en=0): + adapt_done = (rreg(c.fw_opt_done_addr) >> lane) & 1 + result[lane] = sd, rdy, adapt_done + return result +def sig_det(lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + get_lane_mode(lane) + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + sd_bit = rreg(c.rx_sd_addr, lane) + #rdy = rreg(c.rx_rdy_addr, lane) + result[lane] = sd_bit + return result +def phy_rdy(lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + get_lane_mode(lane) + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + #sd = rreg(c.rx_sd_addr, lane) + rdy = rreg(c.rx_rdy_addr, lane) + result[lane] = rdy + return result +def adapt_done(lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + get_lane_mode(lane) + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + adapt_done=1 + if fw_loaded(print_en=0): + adapt_done = (rreg(c.fw_opt_done_addr) >> lane) & 1 + result[lane] = adapt_done + return result +def ppm(lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + get_lane_mode(lane) + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + ppm = twos_to_int(rreg(c.rx_freq_accum_addr, lane), 11) + result[lane] = ppm + return result + +def state(lane = None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + get_lane_mode(lane) + c = Pam4Reg if lane_mode_list[lane].lower() == 'pam4' else NrzReg + result[lane] = rreg(c.rx_state_addr, lane) + return result + +def edge(edge1 = None, edge2 = None, edge3 = None, edge4 = None, lane = None): + lanes = get_lane_list(lane) + result = {} + c = Pam4Reg + for lane in lanes: + if edge1 is edge2 is edge3 is edge4 is None: + edge1_v = rreg(c.rx_edge1_addr, lane) + edge2_v = rreg(c.rx_edge2_addr, lane) + edge3_v = rreg(c.rx_edge3_addr, lane) + edge4_v = rreg(c.rx_edge4_addr, lane) + result[lane] = edge1_v, edge2_v, edge3_v, edge4_v + else: + if edge1 != None: + wreg(c.rx_edge1_addr, edge1, lane) + if edge2 != None: + wreg(c.rx_edge2_addr, edge2, lane) + if edge3 != None: + wreg(c.rx_edge3_addr, edge3, lane) + if edge4 != None: + wreg(c.rx_edge4_addr, edge4, lane) + #else: + if result != {}: return result + +def get_err(lane = None): + + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + c = NrzReg if lane_mode_list[lane].lower() == 'nrz' else Pam4Reg + # check if prbs checker is on + checker = rreg(c.rx_prbs_checker_pu_addr, lane) + #rdy = sum(ready(lane)[lane]) + if checker == 0: + print("\n***Lane %s PRBS checker is off***"%lane_name_list[lane]) + result[lane] = -1 + else: + err = long(rreg(c.rx_err_cntr_msb_addr, lane)<<16) + rreg(c.rx_err_cntr_lsb_addr, lane) + result[lane] = err + #else: + if result != {}: return result +#################################################################################################### +# +# GET ISI Residual Taps +#################################################################################################### +def sw_pam4_isi(b0=None, dir=0, isi_tap_range=range(0,9), lane=None, print_en=0): + if lane is None: lane=gLane[0] + result={} + if fw_loaded(print_en=0): + #print("\n...sw_nrz_isi: Slice %d Lane %2d has FW Loaded. Exiting!"%(gSlice,lane)) + result[lane] = [-1]*len(isi_tap_range) + return result + if type(lane) != int: + print ("\n...sw_pam4_isi: This is a single-lane function") + result[lane] = [-1]*len(isi_tap_range) + return result + + + #print_en2=0 + + if b0 is None: + print_en=1 + b0=2 + else: + print_en=0 + + org1 = rreg(c.rx_margin_patt_dis_owen_addr, lane) + org2 = rreg(c.rx_margin_patt_dis_ow_addr , lane) + org3 = rreg(c.rx_mu_ow_addr , lane) + org4 = rreg(c.rx_iter_s6_addr , lane) + org5 = rreg(c.rx_timer_meas_s6_addr , lane) + org6 = rreg(c.rx_bp1_en_addr , lane) + org7 = rreg(c.rx_bp1_st_addr , lane) + org8 = rreg(c.rx_bp2_en_addr , lane) + org9 = rreg(c.rx_bp2_st_addr , lane) + org10= rreg(c.rx_sm_cont_addr , lane) + #bp1_org = bp1(lane=lane)[lane][0:2] + + # program registers for , b0, dir, pattern_p and pattern_n + isi_tap_list = [] + #tap_saturated = [] + ffe_index_list = [' ','Del','k1','k2','k3','k4',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '] + #ffe_index_list = [' ','k-1','k12','k3','k4',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '] + tap_index_list = ['f-2','f-1','f2' ,'f3','f4','f5','f6','f7','f8','f9','f10','f11','f12','f13','f14','f15','f16','f17','f18','f19','f20'] + wreg(c.rx_fixed_patt_b0_addr, b0, lane) + wreg(c.rx_fixed_patt_dir_addr, dir, lane) + wreg(c.rx_timer_meas_s6_addr, 8, lane) + + #### Clear BP2, Toggle BP1 and Continue to BP1 at state 0x12 + bp2(0,0x12,lane=lane) + bp1(0,0x12,lane=lane) + sm_cont_01(lane=lane) + bp1(1,0x12,lane=lane) + + wait_for_bp1_timeout = 0 + while True: + if bp1(lane=lane)[lane][-1]: + #ma = rreg(c.rx_state_cntr_addr, lane) # wait for the whole 32-bit counter to be '0x00000000', not good + ma = rreg(c.rx_mj_addr,lane) # wait for the lowest 2 bits to become '00' + if ma == 0: + break + else: + #print("0x%x,"%ma), + bp1(0,0x12,lane) + sm_cont_01(lane=lane) + bp1(1,0x12,lane) + else: + wait_for_bp1_timeout += 1 + if wait_for_bp1_timeout > 5000: + print("\nGet Tap Value FULL (1)***>> Timed out waiting for read_state_counter=0, before starting Getting Taps") + #if print_en2: print (bp1(lane=lane)[lane][-1]) + bp2(0,0x12,lane=lane) + bp1(0,0x12,lane=lane) + break + + + wreg(c.rx_margin_patt_dis_owen_addr, 1, lane) + wreg(c.rx_margin_patt_dis_ow_addr, 0, lane) + wreg(c.rx_mu_ow_addr, 0, lane) + wreg(c.rx_iter_s6_addr, 1, lane) + bp1(0,0x12,lane=lane) + sm_cont_01(lane=lane) + + for i in isi_tap_range: + wreg(c.rx_fixed_patt_mode_addr, i, lane) + time.sleep(0.2) + bp1(1,0x12,lane=lane) + wait_for_bp1_timeout = 0 + while True: + if bp1(lane=lane)[lane][-1]: break + else: + wait_for_bp1_timeout += 1 + if wait_for_bp1_timeout > 5000: + print("\nGet Tap Value FULL (2) ***>> Timed out waiting to reach BP1 for tap %d"%i) + bp2(0,0x12,lane=lane) + bp1(0,0x12,lane=lane) + break + # read back fixed pattern margins (plus margin and minus margin)reg_addr1 = 0x36 + plus = rreg(c.rx_fixed_patt_plus_margin_addr, lane) + minus = rreg(c.rx_fixed_patt_minus_margin_addr, lane) + + if (plus>2047): plus = plus - 4096 + if (minus>2047): minus = minus - 4096 + diff_margin = plus - minus + #diff_margin_f = ((float(diff_margin & 0x0fff)/2048)+1)%2-1 + #if print_en2: print ("%3d,%2d,%2d,%5d,%5d,%5d,%8.4f " % (i, b0, dir, plus, minus, diff_margin, diff_margin_f)) + + if abs(plus) == 2048 or abs(minus) == 2048: + print("\nGet Tap Value FULL ***>> Margin saturated to +/-2048 for tap %d"%i) + diff_margin = 2222 + + isi_tap_list.append(diff_margin) + bp1(0,0x12,lane=lane) + sm_cont_01(lane=lane) + + bp1(1,0x12,lane=lane) + wait_for_bp1_timeout = 0 + while True: + if bp1(lane=lane)[lane][-1]: break + else: + wait_for_bp1_timeout += 1 + if wait_for_bp1_timeout > 5000: + print("\nGet Tap Value FULL (3) ***>> Timed out waiting to reach BP1") + break + bp1(0,0x12,lane=lane)#debug + sm_cont_01(lane=lane)#debug + wreg(c.rx_margin_patt_dis_owen_addr, org1 ,lane) + wreg(c.rx_margin_patt_dis_ow_addr , org2 ,lane) + wreg(c.rx_mu_ow_addr , org3 ,lane) + wreg(c.rx_iter_s6_addr , org4 ,lane) + wreg(c.rx_timer_meas_s6_addr , org5 ,lane) + wreg(c.rx_bp1_en_addr , org6 ,lane) + wreg(c.rx_bp1_st_addr , org7 ,lane) + wreg(c.rx_bp2_en_addr , org8 ,lane) + wreg(c.rx_bp2_st_addr , org9 ,lane) + wreg(c.rx_sm_cont_addr , org10,lane) + sm_cont_01(lane=lane) + + #print + #rregBits(0x28,[13,9],1) + if print_en: + print("\n...SW Residual ISI Taps: Lane %s\n\n|"%lane_name_list[lane]), + + for i in isi_tap_range: + print("%4s |"%ffe_index_list[i]), + print("\n|"), + [ffe_k1_bin,ffe_k2_bin,ffe_k3_bin,ffe_k4_bin,ffe_s1_bin,ffe_s2_bin,ffe_sf_bin] = ffe_taps(lane=lane)[lane] + delta_val = delta(lane=lane)[lane] + print(' | %3d | %4d | %4d | %4d | %4d | | | |\n|' %(delta_val,ffe_k1_bin,ffe_k2_bin,ffe_k3_bin,ffe_k4_bin)), + + for i in isi_tap_range: + print("%4s |"%tap_index_list[i]), + print("\n|"), + for i in range(len(isi_tap_list)): + print("%4s |"%isi_tap_list[i]), + print("\n") + else: + return isi_tap_list + +Gettapvalue_full = sw_pam4_isi +#################################################################################################### +# +# GET Residual ISI by the FW +#################################################################################################### +def fw_pam4_isi(lane=None, print_en=0): + isi_tap_range=range(0,16) + lanes = get_lane_list(lane) + result = {} + + for ln in lanes: + get_lane_mode(ln) + # Lane is in PAM4 mode, get the ISI taps + if lane_mode_list[ln] == 'pam4' and phy_rdy(ln)[ln] == 1: + readout = BE_info_signed(ln, 10, 0, len(isi_tap_range)) + # Lane is in NRZ mode, or phy not ready, Skip + else: + readout = [-1*ln]*len(isi_tap_range) + result[ln] = readout + + return result +#################################################################################################### +# ISI Residual Taps for NRZ +# +# For Chip Rev 2.0 only +# Does not require a FW pause because it is using BP 5, not used by FW +#################################################################################################### +def sw_nrz_isi(lane=None,print_en=0): + isi_tap_range=range(0,16) + lanes = get_lane_list(lane) + result={} + + for ln in lanes: + isi_tap_list = []; + for unused in isi_tap_range: isi_tap_list.append(-1) + if lane_mode_list[ln].upper() != 'NRZ' or phy_rdy(ln)[ln]==0: + result[ln] = isi_tap_list + continue + bp1_state_orig = rregBits(0x17d, [12, 8],ln) + bp1_en_orig = rregBits(0x17d, [15],ln) + wregBits(0x17d, [12, 8], 24,ln) + wregBits(0x17d, [15], 0, ln) + wregBits(0x10c, [15], 0, ln) + wregBits(0x10c, [15], 1, ln) + + for i in isi_tap_range: + wregBits(0x165, [4,1],i,ln) + time.sleep(0.01) + wregBits(0x17d, [15], 1, ln) + wait_for_bp1_timeout=0 + while True: + if rregBits(0x18f, [15],ln): + break + else: + wait_for_bp1_timeout+=1 + if wait_for_bp1_timeout>500: + if print_en>2:print (" Get Tap Value >>>>> Timed out 2 waiting for BP1") + break + plus = (rregBits(0x127, [3,0],ln)<<8) + rregBits(0x128, [15,8],ln) + minus = (rregBits(0x128, [7,0],ln)<<4) + rregBits(0x129, [15,12],ln) + + if (plus>2047): plus = plus - 4096 + if (minus>2047): minus = minus - 4096 + diff_margin = plus - minus + diff_margin_f = ((float(diff_margin & 0x0fff)/2048)+1)%2-1 + + if print_en>2: print ("\n%8d, %8d, %8d, %11d, %11.4f " % (i, plus, minus, diff_margin, diff_margin_f)) + isi_tap_list[i] = diff_margin + + wregBits(0x17d, [15], 0, ln) + wregBits(0x10c, [15], 0, ln) + wregBits(0x10c, [15], 1, ln) + + wregBits(0x17d, [12, 8], bp1_state_orig, ln) + wregBits(0x17d, [15], bp1_en_orig, ln) + result[ln] = isi_tap_list + + return result +#################################################################################################### +# +# GET Residual ISI by the FW if loaded, or by software +#################################################################################################### +def pam4_isi(lane=None,print_en=0): + result = {} + if fw_loaded(print_en=0): + result = fw_pam4_isi(lane,print_en) + else: + result = sw_pam4_isi(lane,print_en) + return result +#################################################################################################### +# +# GET Residual ISI by the FW if loaded, or by software +#################################################################################################### +def nrz_isi(lane=None,print_en=0): + result = {} + if (chip_rev() == 1.0): + result = sw_nrz_isi_BE1(lane,print_en) + else: + result = sw_nrz_isi(lane,print_en) + return result +#################################################################################################### +# +# GET Residual ISI in NRZ or PAM4 +#################################################################################################### +def isi(lane=None,print_en=1): + lanes = get_lane_list(lane) + result = {} + nrz_lane=False + pam4_lane=False + for ln in lanes: + get_lane_mode(ln) + if lane_mode_list[ln] == 'pam4': + result[ln] = pam4_isi(ln,print_en) + pam4_lane=True + else: # NRZ + result[ln] = nrz_isi(ln,print_en) + nrz_lane=True + + if print_en: + isi_tap_range=range(16) + line_separator= "\n+--------------------------------------------------------------------------------------------------------------+" + ffe_index_list = [' ','Del','k1','k2','k3','k4',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '] + tap_index_list = ['f-2','f-1','f2','f3','f4','f5','f6','f7','f8','f9','f10','f11','f12','f13','f14','f15','f16'] + tap_index_list_nrz = ['f-1','f4','f5','f6','f7','f8','f9','f10','f11','f12','f13','f14','f15','f16','f16','f17','f17'] + print (line_separator) + if print_en==2 and lane_mode_list[ln] == 'pam4': + print("\n| "), + for i in isi_tap_range: + print("|%4s"%ffe_index_list[i]) + print("|") + if pam4_lane==True: + print("\n| PAM4 ISI ->") + for i in isi_tap_range: + print("|%4s"%tap_index_list[i]) + print("|") + if nrz_lane==True: + print("\n| NRZ ISI ->") + for i in isi_tap_range: + print("|%4s"%tap_index_list_nrz[i]) + print("|") + print (line_separator) + + for ln in lanes: + if print_en==2 and lane_mode_list[ln] == 'pam4': + # if lane_mode_list[ln] == 'pam4': + [ffe_k1_bin,ffe_k2_bin,ffe_k3_bin,ffe_k4_bin,ffe_s1_bin,ffe_s2_bin,ffe_sf_bin] = ffe_taps(lane=ln)[ln] + # else: + # [ffe_k1_bin,ffe_k2_bin,ffe_k3_bin,ffe_k4_bin,ffe_s1_bin,ffe_s2_bin,ffe_sf_bin] = [0,0,0,0,0,0,0] + delta_val = delta(lane=ln)[ln] + print("\n %3d %4d %4d %4d %4d |" %(delta_val,ffe_k1_bin,ffe_k2_bin,ffe_k3_bin,ffe_k4_bin)), + print("\n| S%d_%2s -"%(gSlice,lane_name_list[ln])), + if lane_mode_list[ln] == 'pam4': + print("PAM4"), + else: + print("NRZ "), + for i in isi_tap_range: + print(" %4d"%(result[ln][ln][i])), + print("|"), + print (line_separator) + else: + return result + +#################################################################################################### +## NRZ specific functions +#################################################################################################### +def nrz_dfe(lane = None): + lanes = get_lane_list(lane) + + c = NrzReg + result = {} + for lane in lanes: + f1 = twos_to_int(rreg(c.rx_f1_addr, lane),7) + f2 = twos_to_int(rreg(c.rx_f2_addr, lane),7) + f3 = twos_to_int(rreg(c.rx_f3_addr, lane),7) + result[lane] = f1, f2, f3 + return result + +def bb_nrz(en = None, lane = None): + lanes = get_lane_list(lane) + c = NrzReg + result = {} + for lane in lanes: + if en != None: + wreg(c.rx_bb_en_addr, en, lane) # bb_en + wreg(c.rx_delta_adapt_en_addr, 1-en, lane) # delta_adapt_en + else: + bb = rreg(c.rx_bb_en_addr, lane) + delta_en = rreg(c.rx_delta_adapt_en_addr, lane) + result[lane] = bb, delta_en + #else: + if result != {}: return result + +def ffe_pu(en = None, lane = None): + lanes = get_lane_list(lane) + c = Pam4Reg + result = {} + for lane in lanes: + if en is None: + pu1 = rreg(c.rx_ffe_k1_pu_addr, lane) + pu2 = rreg(c.rx_ffe_k2_pu_addr, lane) + pu3 = rreg(c.rx_ffe_k3_pu_addr, lane) + pu4 = rreg(c.rx_ffe_k4_pu_addr, lane) + result[lane] = pu1 & pu2 & pu3 & pu4 + else: + wreg(c.rx_ffe_k1_pu_addr, en, lane) + wreg(c.rx_ffe_k2_pu_addr, en, lane) + wreg(c.rx_ffe_k3_pu_addr, en, lane) + wreg(c.rx_ffe_k4_pu_addr, en, lane) + #else: + if result != {}: return result + +def ffe_taps (k1=None, k2=None, k3=None, k4=None, s1=None, s2=None, sf=None, lane=None): + + lanes = get_lane_list(lane) + c = Pam4Reg + result = {} + for lane in lanes: + if k1!=None: + pol1 = 1 if k1<0 else 0 + k11 = abs(k1) + rx_ffe_k1_gray_msb = Bin_Gray(k11 >> 4) + rx_ffe_k1_gray_lsb = Bin_Gray(k11&0xf) + #rx_ffe_k1_gray = ((rx_ffe_k1_gray_msb << 4) + rx_ffe_k1_gray_lsb)&0xFF + wreg(c.rx_ffe_k1_msb_addr, rx_ffe_k1_gray_msb, lane) + wreg(c.rx_ffe_k1_lsb_addr, rx_ffe_k1_gray_lsb, lane) + wreg(c.rx_ffe_pol1_addr, pol1, lane) + if k2!=None: + pol2 = 1 if k2<0 else 0 + k22 = abs(k2) + rx_ffe_k2_gray_msb = Bin_Gray(k22 >> 4) + rx_ffe_k2_gray_lsb = Bin_Gray(k22&0xf) + rx_ffe_k2_gray = ((rx_ffe_k2_gray_msb << 4) + rx_ffe_k2_gray_lsb)&0xFF + wreg(c.rx_ffe_k2_msb_addr, rx_ffe_k2_gray_msb, lane) + wreg(c.rx_ffe_k2_lsb_addr, rx_ffe_k2_gray_lsb, lane) + wreg(c.rx_ffe_pol2_addr, pol2, lane) + if k3!=None: + pol3 = 1 if k3<0 else 0 + k33 = abs(k3) + rx_ffe_k3_gray_lsb = Bin_Gray(k33&0xf) + rx_ffe_k3_gray_msb = Bin_Gray(k33 >> 4) + rx_ffe_k3_gray = ((rx_ffe_k3_gray_msb << 4) + rx_ffe_k3_gray_lsb)&0xFF + wreg(c.rx_ffe_k3_msb_addr, rx_ffe_k3_gray_msb, lane) + wreg(c.rx_ffe_k3_lsb_addr, rx_ffe_k3_gray_lsb, lane) + wreg(c.rx_ffe_pol3_addr, pol3, lane) + if k4!=None: + pol4 = 1 if k4<0 else 0 + k44 = abs(k4) + rx_ffe_k4_gray_lsb = Bin_Gray(k44&0xf) + rx_ffe_k4_gray_msb = Bin_Gray(k44 >> 4) + rx_ffe_k4_gray = ((rx_ffe_k4_gray_msb << 4) + rx_ffe_k4_gray_lsb)&0xFF + wreg(c.rx_ffe_k4_msb_addr, rx_ffe_k4_gray_msb, lane) + wreg(c.rx_ffe_k4_lsb_addr, rx_ffe_k4_gray_lsb, lane) + wreg(c.rx_ffe_pol4_addr, pol4, lane) + if s2!=None: + rx_ffe_s2_gray_lsb = Bin_Gray(s2&0x0f) + rx_ffe_s2_gray_msb = Bin_Gray((s2 >> 4)&0x0f) + rx_ffe_s2_gray = ((rx_ffe_s2_gray_msb << 4) + rx_ffe_s2_gray_lsb)&0xFF + wreg(c.rx_ffe_s2_msb_addr, rx_ffe_s2_gray_msb, lane) + wreg(c.rx_ffe_s2_lsb_addr, rx_ffe_s2_gray_lsb, lane) + if s1!=None: + rx_ffe_s1_gray_lsb = Bin_Gray(s1&0x0f) + rx_ffe_s1_gray_msb = Bin_Gray((s1 >> 4)&0x0f) + rx_ffe_s1_gray = ((rx_ffe_s1_gray_msb << 4) + rx_ffe_s1_gray_lsb)&0xFF + wreg(c.rx_ffe_s1_msb_addr, rx_ffe_s1_gray_msb, lane) + wreg(c.rx_ffe_s1_lsb_addr, rx_ffe_s1_gray_lsb, lane) + + if sf!=None: + rx_ffe_sf_gray_lsb = Bin_Gray(sf&0x0f) + rx_ffe_sf_gray_msb = Bin_Gray((sf >> 4)&0x0f) + rx_ffe_sf_gray = ((rx_ffe_sf_gray_msb << 4) + rx_ffe_sf_gray_lsb)&0xFF + wreg(c.rx_ffe_sf_msb_addr, rx_ffe_sf_gray_msb, lane) + wreg(c.rx_ffe_sf_lsb_addr, rx_ffe_sf_gray_lsb, lane) + + if k1 is None and k2 is None and k3 is None and k4 is None and s1 is None and s2 is None and sf is None: + pol1 = rreg(c.rx_ffe_pol1_addr, lane) + rx_ffe_k1_msb = Gray_Bin(rreg(c.rx_ffe_k1_msb_addr, lane)) + rx_ffe_k1_lsb = Gray_Bin(rreg(c.rx_ffe_k1_lsb_addr, lane)) + rx_ffe_k1_bin = (1-2*pol1)*(((rx_ffe_k1_msb << 4) + rx_ffe_k1_lsb)&0xFF) + + pol2 = rreg(c.rx_ffe_pol2_addr, lane) + rx_ffe_k2_msb = Gray_Bin(rreg(c.rx_ffe_k2_msb_addr, lane)) + rx_ffe_k2_lsb = Gray_Bin(rreg(c.rx_ffe_k2_lsb_addr, lane)) + rx_ffe_k2_bin = (1-2*pol2)*(((rx_ffe_k2_msb << 4) + rx_ffe_k2_lsb)&0xFF) + + pol3 = rreg(c.rx_ffe_pol3_addr, lane) + rx_ffe_k3_msb = Gray_Bin(rreg(c.rx_ffe_k3_msb_addr, lane)) + rx_ffe_k3_lsb = Gray_Bin(rreg(c.rx_ffe_k3_lsb_addr, lane)) + rx_ffe_k3_bin = (1-2*pol3)*(((rx_ffe_k3_msb << 4) + rx_ffe_k3_lsb)&0xFF) + + pol4 = rreg(c.rx_ffe_pol4_addr, lane) + rx_ffe_k4_msb = Gray_Bin(rreg(c.rx_ffe_k4_msb_addr, lane)) + rx_ffe_k4_lsb = Gray_Bin(rreg(c.rx_ffe_k4_lsb_addr, lane)) + rx_ffe_k4_bin = (1-2*pol4)*(((rx_ffe_k4_msb << 4) + rx_ffe_k4_lsb)&0xFF) + + rx_ffe_s1_msb = Gray_Bin(rreg(c.rx_ffe_s1_msb_addr, lane)) + rx_ffe_s1_lsb = Gray_Bin(rreg(c.rx_ffe_s1_lsb_addr, lane)) + rx_ffe_s1_bin = ((rx_ffe_s1_msb << 4) + rx_ffe_s1_lsb)&0xFF + + rx_ffe_s2_msb = Gray_Bin(rreg(c.rx_ffe_s2_msb_addr, lane)) + rx_ffe_s2_lsb = Gray_Bin(rreg(c.rx_ffe_s2_lsb_addr, lane)) + rx_ffe_s2_bin = ((rx_ffe_s2_msb << 4) + rx_ffe_s2_lsb)&0xFF + + rx_ffe_sf_msb = Gray_Bin(rreg(c.rx_ffe_sf_msb_addr, lane)) + rx_ffe_sf_lsb = Gray_Bin(rreg(c.rx_ffe_sf_lsb_addr, lane)) + rx_ffe_sf_bin = ((rx_ffe_sf_msb << 4) + rx_ffe_sf_lsb)&0xFF + + result[lane] = rx_ffe_k1_bin, rx_ffe_k2_bin, rx_ffe_k3_bin, rx_ffe_k4_bin, rx_ffe_s1_bin, rx_ffe_s2_bin, rx_ffe_sf_bin + + #else: + if result != {}: return result + + +#################################################################################################### +# FEC Parameters Readback functions +#################################################################################################### +# [FEC_A0,FEC_A1,FEC_A2,FEC_A2, FEC_B0,FEC_B1,FEC_B2,FEC_B3] +fec_class = [0x4000,0x4100,0x4200,0x4300, 0x5000,0x5100,0x5200,0x5300] +fec_class2= [0x4400,0x4500,0x4600,0x4700, 0x5400,0x5500,0x5600,0x5700] +fec_class3= [0x4800,0x4900,0x4a00,0x4b00, 0x5800,0x5900,0x5a00,0x5b00] + +#################################################################################################### + +def fec_status_en(index): + counter = rregBits(0x9857, [index]) + return counter + +def fec_status_traffic_gen_en(index): #wreg(0x48f0,0x1095) + status = rregBits(fec_class3[index]+0xF0,[7]) + return status + +def fec_status_aligned_rx(index): + status = rregBits(fec_class[index]+0xc9,[14]) + return status + +def fec_status_ampsLock(index): + status = rregBits(fec_class[index]+0xc9,[11,8]) + return status + +def fec_status_uncorrected(index): + counter_lower = rregBits(fec_class[index]+0xcc,[15,0]) + counter_upper = rregBits(fec_class[index]+0xcd,[15,0]) + counter = (counter_upper<<16)+counter_lower + return counter + +def fec_status_corrected(index): + counter_lower = rregBits(fec_class[index]+0xca,[15,0]) + counter_upper = rregBits(fec_class[index]+0xcb,[15,0]) + counter = (counter_upper<<16)+counter_lower + return counter + +def fec_status_rx_fifo_cnt(index): + counter = rregBits(fec_class3[index]+0x9f,[10,0]) + return counter +def fec_status_rx_fifo_min(index): + counter = rregBits(fec_class3[index]+0xa0,[10,0]) + return counter +def fec_status_rx_fifo_max(index): + counter = rregBits(fec_class3[index]+0xa1,[10,0]) + return counter +def fec_status_tx_fifo_cnt(index): + counter = rregBits(fec_class3[index]+0x9c,[10,0]) + return counter +def fec_status_tx_fifo_min(index): + counter = rregBits(fec_class3[index]+0x9d,[10,0]) + return counter +def fec_status_tx_fifo_max(index): + counter = rregBits(fec_class3[index]+0x9e,[10,0]) + return counter + +#################################################################################################### +# Checks the status of all 8 FECs +# +# Returns: A list of eight FEC Status flags, one for each FEC_IDX 0 to 7 +# +# FEC Status = [FECA0,FECA1,FECA2,FECA3, FECB0,FECB1,FECB2,FECB3] +# +# FEC Status[idx] = 0: If FEC is not powered up (unused or never configured) +# FEC Status[idx] = 1: If FEC was able to LOCK (pass) +# FEC Status[idx] = -1: If FEC was not able to lock (fail) +# +#################################################################################################### +def fec_status(print_en=True, fifo_check_en=False): + length_1 = 22 + length = 17 + + if fifo_check_en: # [Acceptable range for each FIFO counter] + rx_fec_fifo_min_limit = [354, 965] + rx_fec_fifo_max_limit = [354, 965] + rx_fec_fifo_del_limit = [ 0, 514] + + tx_fec_fifo_min_limit = [320, 931] + tx_fec_fifo_max_limit = [320, 931] + tx_fec_fifo_del_limit = [ 0, 514] + else: + rx_fec_fifo_min_limit = [ 1, 1279] + rx_fec_fifo_max_limit = [ 1, 1279] + rx_fec_fifo_del_limit = [ 1, 1279] + + tx_fec_fifo_min_limit = [ 1, 1279] + tx_fec_fifo_max_limit = [ 1, 1279] + tx_fec_fifo_del_limit = [ 1, 1279] + + + data={} + for index in range(8): + data[index]=[] + data[index].append(fec_status_aligned_rx(index)) + data[index].append(fec_status_ampsLock(index)) + data[index].append(fec_status_uncorrected(index)) + data[index].append(fec_status_corrected(index)) + data[index].append(fec_status_rx_fifo_min(index)) + data[index].append(fec_status_rx_fifo_cnt(index)) + data[index].append(fec_status_rx_fifo_max(index)) + data[index].append(fec_status_tx_fifo_min(index)) + data[index].append(fec_status_tx_fifo_cnt(index)) + data[index].append(fec_status_tx_fifo_max(index)) + data[index].append(fec_status_en(index)) + + global gFecStatusPrevTimeStamp + global gFecStatusCurrTimeStamp + gFecStatusPrevTimeStamp[gSlice] = gFecStatusCurrTimeStamp[gSlice] + gFecStatusCurrTimeStamp[gSlice] = time.time() + + rx_adapt_done=[] + + aligned=[] + ampslock=[] + uncorrected=[] + corrected=[] + + rx_fifo_min=[] + rx_fifo_cnt=[] + rx_fifo_max=[] + rx_fifo_del=[] + + tx_fifo_min=[] + tx_fifo_cnt=[] + tx_fifo_max=[] + tx_fifo_del=[] + + fec_en=[] + fec_status=[] + fec_statistics=[]; idx=0 + + # Check all lanes' RX Adaptation Status + rx_adapt_done_lane = [0]*(16+4) + for ln in range(16): + rx_adapt_done_lane[ln] = (rreg(c.fw_opt_done_addr) >> ln) & 1 + + for index in range(8): # 4 A-FECs and 4 B-FECs + # This FEC lanes' RX Adapt status + if index < 4: # Adapt status of the A side lanes, related to this FEC + rx_adapt_done.append([]) + if(rreg([0x9858, [5,4]])== 2): # Check FEC_A2 Lane Mapping. If [5:4]=2, it means FEC_A2 is connected to lanes A2/A3, else A4/A5 + rx_adapt_done[index].append(rx_adapt_done_lane[index]) # adapt flag for lane 0 or 2 + rx_adapt_done[index].append(rx_adapt_done_lane[index+1]) # adapt flag for lane 1 or 3 + else: + rx_adapt_done[index].append(rx_adapt_done_lane[index*2]) # adapt flag for lane 0 or 4 + rx_adapt_done[index].append(rx_adapt_done_lane[index*2+1]) # adapt flag for lane 1 or 5 + + else: # Adapt status of the B side lanes, related to this FEC + rx_adapt_done.append([]) + rx_adapt_done[index].append(rx_adapt_done_lane[index*2]) # adapt flag for lane 8 or 12 + rx_adapt_done[index].append(rx_adapt_done_lane[index*2+1]) # adapt flag for lane 9 or 13 + rx_adapt_done[index].append(rx_adapt_done_lane[index*2+2]) # adapt flag for lane 10 or 14 + rx_adapt_done[index].append(rx_adapt_done_lane[index*2+3]) # adapt flag for lane 11 or 15 + # This FEC status + aligned.append(data[index][0]) + ampslock.append(data[index][1]) + uncorrected.append(data[index][2]) + corrected.append(data[index][3]) + rx_fifo_min.append(data[index][4]) + rx_fifo_cnt.append(data[index][5]) + rx_fifo_max.append(data[index][6]) + rx_fifo_del.append(rx_fifo_max[index] - rx_fifo_min[index]) + tx_fifo_min.append(data[index][7]) + tx_fifo_cnt.append(data[index][8]) + tx_fifo_max.append(data[index][9]) + tx_fifo_del.append(tx_fifo_max[index] - tx_fifo_min[index]) + fec_en.append(data[index][10]) + fec_status.append(1) + + # Return values for this FEC + if fec_en[index]: + fec_statistics.append([]) + fec_statistics[idx].append(rx_adapt_done[index]) + fec_statistics[idx].append(format(ampslock[index],'04b')) + fec_statistics[idx].append(aligned[index]) + fec_statistics[idx].append(corrected[index]) + fec_statistics[idx].append(uncorrected[index]) + fec_statistics[idx].append(rx_fifo_min[index]) + fec_statistics[idx].append(rx_fifo_max[index]) + fec_statistics[idx].append(rx_fifo_del[index]) + fec_statistics[idx].append(tx_fifo_min[index]) + fec_statistics[idx].append(tx_fifo_max[index]) + fec_statistics[idx].append(tx_fifo_del[index]) + idx+=1 + + num_fec_en = fec_en.count(1) + #for testing + #num_fec_en=8# = fec_en.count(1) + #fec_en=[1,1,1,1,1,1,1,1] + + if print_en: + separator='\n |' + for i in range(length_1+(length)*num_fec_en): + separator+='-' + separator += '|' + + print ('\n\n | Gearbox FEC STATUS: Slice %d - Elapsed Time: %2.3f sec'%(gSlice, gFecStatusCurrTimeStamp[gSlice] - gFecStatusPrevTimeStamp[gSlice])), + print (separator) + + print ('\n | FEC Parameters |') + for index in range(8): + if fec_en[index]: + fec_type = 'PAM4 FEC A' if index<4 else ' NRZ FEC B' + macro = index if index<4 else index-4 + print(' %s[%d] |'%(fec_type,macro)), + + print (separator) + + print ('\n | RX Lanes Adapt Done |') + for index in range(8): + if fec_en[index]: + flag='<<' if (0 in rx_adapt_done[index]) else ' ' + if flag=='<<': fec_status[index]=-1 + if index < 4: print(" %d,%d %s |"%(rx_adapt_done[index][0],rx_adapt_done[index][1],flag)), + if index > 3: print(" %d,%d,%d,%d %s |"%(rx_adapt_done[index][0],rx_adapt_done[index][1],rx_adapt_done[index][2],rx_adapt_done[index][3],flag)), + + print ('\n | RX FEC AmLck 0,1,2,3 |') + for index in range(8): + if fec_en[index]: + flag='<<' if (ampslock[index] != 0xF) else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %d,%d,%d,%d %s |"%(ampslock[index]>>0&1,ampslock[index]>>1&1,ampslock[index]>>2&1,ampslock[index]>>3&1,flag)), + + print ('\n | RX FEC Aligned |') + for index in range(8): + if fec_en[index]: + flag='<<' if (aligned[index]) != 1 else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(aligned[index],flag)), + else: + fec_status[index]=0 + + print ('\n | RX FEC Corr (cw) |') + for index in range(8): + if fec_en[index]: + if index < 4: flag=' ' if corrected[index] == 0 else ' ' + if index >=4: flag='<<' if corrected[index] != 0 else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(corrected[index],flag)), + + print ('\n | RX FEC Uncorr (cw) |') + for index in range(8): + if fec_en[index]: + flag='<<' if uncorrected[index] != 0 else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(uncorrected[index],flag)), + + print (separator) + + print ('\n | RX FEC FIFO Min |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (rx_fec_fifo_min_limit[0] <= rx_fifo_min[index] <= rx_fec_fifo_min_limit[1]) else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(rx_fifo_min[index],flag)), + print ('\n | RX FEC FIFO Cnt |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (rx_fifo_min[index] <= rx_fifo_cnt[index] <= rx_fifo_max[index]) else ' ' + #if flag=='<<': fec_status[index]=-1 # do not fail for live count value + print(" %10d %s |"%(rx_fifo_cnt[index],flag)), + print ('\n | RX FEC FIFO Max |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (rx_fec_fifo_max_limit[0] <= rx_fifo_max[index] <= rx_fec_fifo_max_limit[1]) else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(rx_fifo_max[index],flag)), + print ('\n | RX FEC FIFO Delta |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (rx_fec_fifo_del_limit[0] <= rx_fifo_del[index] <= rx_fec_fifo_del_limit[1]) else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(rx_fifo_del[index],flag)), + + print (separator) + + print ('\n | TX FEC FIFO Min |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (tx_fec_fifo_min_limit[0] <= tx_fifo_min[index] <= tx_fec_fifo_min_limit[1]) else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(tx_fifo_min[index],flag)), + print ('\n | TX FEC FIFO Cnt |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (tx_fifo_min[index] <= tx_fifo_cnt[index] <= tx_fifo_max[index]) else ' ' + #if flag=='<<': fec_status[index]=-1 # do not fail for live count value + print(" %10d %s |"%(tx_fifo_cnt[index],flag)), + print ('\n | TX FEC FIFO Max |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (tx_fec_fifo_max_limit[0] <= tx_fifo_max[index] <= tx_fec_fifo_max_limit[1]) else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(tx_fifo_max[index],flag)), + print ('\n | TX FEC FIFO Delta |') + for index in range(8): + if fec_en[index]: + flag='<<' if not (tx_fec_fifo_del_limit[0] <= tx_fifo_del[index] <= tx_fec_fifo_del_limit[1]) else ' ' + if flag=='<<': fec_status[index]=-1 + print(" %10d %s |"%(tx_fifo_del[index],flag)), + + print (separator) + + print ('\n | Overall FEC STATUS |') + for index in range(8): + if fec_en[index]: + fec_overall_status=' LOCK ' if fec_status[index]==1 else '*** FAIL *** ' + print(" %12s |"%(fec_overall_status)) + + + print (separator) + else: + return fec_status, fec_statistics +################################################################################################## +# +# fec_hist(hist_time = 5, print_en=True, fecs = [0,2,4,6] ) +# +################################################################################################## +# Collects FEC Correctable Error Count Histogram over a period of time +# for each FEC block selected +# +# Returns tuple of all FECs statistical information (if print_en=False): +# +# {FEC_IDX:[DataRate,Time, AM Bits, TotalUncorrCnt, TotalCorrCnt, Bin0,...,Bin15] +# {0: [53.125, 10, 1111, 0, 157, 151, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +# 2: [53.125, 10, 1111, 0, 30, 24, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +# 4: [25.78125, 10, 1111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +# 6: [25.78125, 10, 1111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +# +# Prints out histogram per FEC (if print_en=True): +# +# FEC Histogram (100 sec) +# +------------------------------------------------------------------------------------------+ +# | Parameters | FEC_A[0] | FEC_A[2] | FEC_B[0] | FEC_B[2] | +# +------------------------------------------------------------------------------------------+ +# | RX FEC AmLck 0,1,2,3 | 1111 | 1111 | 1111 | 1111 | +# | RX FEC Corr (cw) | 1706 | 211 | 0 | 0 | +# | RX FEC Uncorr (cw) | 0 | 0 | 0 | 0 | +# +------------------------------------------------------------------------------------------+ +# | RX FEC Bin 1 | 1648 | 193 | 0 | 0 | +# | RX FEC Bin 2 | 37 | 14 | 0 | 0 | +# | RX FEC Bin 3 | 12 | 4 | 0 | 0 | +# | RX FEC Bin 4 | 6 | 0 | 0 | 0 | +# | RX FEC Bin 5 | 1 | 0 | 0 | 0 | +# | RX FEC Bin 6 | 1 | 0 | 0 | 0 | +# | RX FEC Bin 7 | 1 | 0 | 0 | 0 | +# | RX FEC Bin 8 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 9 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 10 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 11 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 12 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 13 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 14 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 15 | 0 | 0 | 0 | 0 | +# +------------------------------------------------------------------------------------------+ +# / dsh >>> fec_hist(3600) +# +# FEC Histogram (3600 sec) +# +------------------------------------------------------------------------------------------+ +# | Parameters | FEC_A[0] | FEC_A[2] | FEC_B[0] | FEC_B[2] | +# +------------------------------------------------------------------------------------------+ +# | RX FEC AmLck 0,1,2,3 | 1111 | 1111 | 1111 | 1111 | +# | RX FEC Corr (cw) | 60416 | 11302 | 0 | 0 | +# | RX FEC Uncorr (cw) | 0 | 0 | 0 | 0 | +# +------------------------------------------------------------------------------------------+ +# | RX FEC Bin 1 | 58821 | 10029 | 0 | 0 | +# | RX FEC Bin 2 | 986 | 836 | 0 | 0 | +# | RX FEC Bin 3 | 382 | 285 | 0 | 0 | +# | RX FEC Bin 4 | 197 | 141 | 0 | 0 | +# | RX FEC Bin 5 | 15 | 7 | 0 | 0 | +# | RX FEC Bin 6 | 13 | 4 | 0 | 0 | +# | RX FEC Bin 7 | 2 | 0 | 0 | 0 | +# | RX FEC Bin 8 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 9 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 10 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 11 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 12 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 13 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 14 | 0 | 0 | 0 | 0 | +# | RX FEC Bin 15 | 0 | 0 | 0 | 0 | +# +------------------------------------------------------------------------------------------+ +# +################################################################################################## +def fec_hist(hist_time = 5, print_en=True, fecs = [0,2,4,6] ): + if chip_rev == 1.0: + print ("\n*** fec_hist() function is not supported in Babbage A0 ***\n") + return + + fec_class1= [0x4000,0x4100,0x4200,0x4300, 0x5000,0x5100,0x5200,0x5300] + #fec_class2= [0x4400,0x4500,0x4600,0x4700, 0x5400,0x5500,0x5600,0x5700] + fec_class3= [0x4800,0x4900,0x4a00,0x4b00, 0x5800,0x5900,0x5a00,0x5b00] + + result={} + bins=range(0,17) + + #### Start the FEC Counters + for fec_idx in fecs: + wregBits(fec_class3[fec_idx]+0x63, [0], 1) # clear error counter + wregBits(fec_class3[fec_idx]+0x63, [0], 0) + wregBits(fec_class3[fec_idx]+0x63, [1], 0) # unfreeze the counter + + #### Wait for FEC Stat Collection Time + time.sleep(hist_time) + + #### Stop the FEC Counters and Histograms + for fec_idx in fecs: + wregBits(fec_class3[fec_idx]+0x63, [1], 1) # freeze the counter + + #### Now process the FEC Counters and Histograms + for fec_idx in fecs: + result[fec_idx]=[] + cw_size = 5440 if fec_idx < 4 else 5280 + data_rate = 53.125 if fec_idx < 4 else 25.78125 + bits_transferred = float((hist_time*data_rate*pow(10,9))) + + ampslock = fec_status_ampsLock(fec_idx) + total_uncorr_cnt= (rreg(fec_class1[fec_idx] +0xcd)<<16) + rreg(fec_class1[fec_idx] +0xcc) # read hist uncorr count + total_corr_cnt = (rreg(fec_class1[fec_idx] +0xcb)<<16) + rreg(fec_class1[fec_idx] +0xca) # read hist corr count + result[fec_idx].append(data_rate) # fec_idx][0] + result[fec_idx].append(hist_time) # fec_idx][1] + result[fec_idx].append((ampslock>>3&1)*1000 + (ampslock>>3&1)*100 + (ampslock>>1&1)*10 + (ampslock>>0&1) ) # fec_idx][2] + result[fec_idx].append(total_uncorr_cnt) # fec_idx][3] + result[fec_idx].append(total_corr_cnt) # fec_idx][4] + + corr_cnt_per_bin = [0]*17 + corr_ber_per_bin = [0]*17 + for bin in bins: # fec_idx][6++] + wregBits(fec_class3[fec_idx]+0x60, [4,0], bin) # select hist bin + corr_cnt_per_bin[bin] = (rreg(fec_class3[fec_idx]+0x62)<<16) + rreg(fec_class3[fec_idx]+0x61) # read hist corr count + if bin == 0: + wregBits(fec_class3[fec_idx]+0x60, [4,0], bin+17) + corr_cnt_per_bin[bin] += (rreg(fec_class3[fec_idx]+0x61)<<32) + total_cw_transferred = corr_cnt_per_bin[0] + total_corr_cnt + total_uncorr_cnt + result[fec_idx].append(total_cw_transferred) # fec_idx][5] + + result[fec_idx].append(corr_cnt_per_bin[bin]) # fec_idx][6++] + + #### Now turn off the FEC Counters and Histograms + for fec_idx in fecs: + wregBits(fec_class3[fec_idx]+0x63, [1], 0) # unfreeze the counter + + #### Print out Final results and Histograms + if print_en: + length_1 = 22 + length = 17 + + print("\n FEC Histogram (%d sec)"%(hist_time)), + num_fec_en=0 + fec_en=[0]*8 + for fec_idx in fecs: + if(fec_status_en(fec_idx)): + fec_en[fec_idx]=1 + num_fec_en+=1 + + separator='\n +' + for i in range(length_1): + separator+='-' + for i in range(length*num_fec_en): + separator+='-'*print_en + separator += '+' + + print (separator) + print ('\n | Parameters |') + for fec_idx in fecs: + if fec_en[fec_idx]: + fec_type = 'A' if fec_idx<4 else 'B' + macro = fec_idx if fec_idx<4 else fec_idx-4 + print(' FEC_%s[%d] |'%(fec_type,macro)), + if print_en==2: print(' FEC_%s[%d] |'%(fec_type,macro)), + + print (separator) + print ('\n | RX FEC AmLck 0,1,2,3 |') + for fec_idx in fecs: + if fec_en[fec_idx]: + print(" %04d |"%(result[fec_idx][2])), + if print_en==2: print(" %04d |"%(result[fec_idx][2])), + + print ('\n | RX FEC Uncorr (cw) |') + for fec_idx in fecs: + if fec_en[fec_idx]: + print(" %10d |"%(result[fec_idx][3])), + if print_en==2: print(" %10.1e |"%(float(result[fec_idx][3])/float(result[fec_idx][5]))), + print ('\n | RX FEC Corr (cw) |') + for fec_idx in fecs: + if fec_en[fec_idx]: + print(" %10d |"%(result[fec_idx][4])), + if print_en==2: print(" %10.1e |"%(float(result[fec_idx][4])/float(result[fec_idx][5]))), + print (separator) + for bin in bins: + print('\n | RX FEC Bin %2d |'%(bin )), + for fec_idx in fecs: + if fec_en[fec_idx]: + print(" %10d |"%(result[fec_idx][6+bin])), + if print_en==2: print(" %10.1e |"%(float(result[fec_idx][6+bin])/float(result[fec_idx][5]))), + print (separator) + + if not print_en: + return result +#################################################################################################### +def fec_ber(fecs=[0,2,4,6]): + # fec_class = [0x4000,0x4100,0x4200,0x4300, 0x5000,0x5100,0x5200,0x5300] + # fec_class2= [0x4400,0x4500,0x4600,0x4700, 0x5400,0x5500,0x5600,0x5700] + # fec_class3= [0x4800,0x4900,0x4a00,0x4b00, 0x5800,0x5900,0x5a00,0x5b00] + print_en=1 + if chip_rev == 1.0: + print ("\n*** fec_status_pre_fec_ber() This function is not supported in Babbage A0 ***\n") + return + fec_type=['A','A','A','A','B','B','B','B'] + if print_en: print('\n...Gearbox Pre-FEC BER') + for fec_idx in fecs: + if print_en: print('\n FEC_%s[%d] : '%(fec_type[fec_idx],fec_idx)), + fec_base_addr = fec_class3[fec_idx] + cw_size = 5440 if fec_idx < 4 else 5280 + + wreg(fec_base_addr+0x63,0x8000) # turn the clock on for reading counters bit[4]=0 + time.sleep(0.10) + wreg(fec_base_addr+0x63,0x8002) # freeze the counters bit[1]=1, turn the clock on for reading counters bit[4]=0 + time.sleep(0.010) + total_errors_hi = rreg(fec_base_addr+0x7f) + total_errors_mid = rreg(fec_base_addr+0x7e) + total_errors_lo = rreg(fec_base_addr+0x7d) + + total_cw_hi = rreg(fec_base_addr+0x5f) + total_cw_mid = rreg(fec_base_addr+0x5e) + total_cw_lo = rreg(fec_base_addr+0x5d) + + total_errors = long( (total_errors_hi << 32) + (total_errors_mid<<16) + (total_errors_lo) ) + total_cw = long( (total_cw_hi << 32) + (total_cw_mid <<16) + (total_cw_lo ) ) + + #if print_en: print ("\n...FEC %d , BaseAddr: 0x%04X, CW Size: %d, Pre-FEC BER"%(fec_idx,fec_base_addr,cw_size)) + #if print_en: print ("\n...Bits In Error : %04X_%04X_%04X = %11d bits"%(total_errors_hi,total_errors_mid,total_errors_lo,total_errors)) + #if print_en: print ("\n...Total CWs Received : %04X_%04X_%04X = %11d CWs"%(total_cw_hi,total_cw_mid,total_cw_lo, total_cw)) + #if print_en: print ("%04X_%04X_%04X (%11d bits),"%(total_errors_hi,total_errors_mid,total_errors_lo,total_errors)), + #if print_en: print ("%04X_%04X_%04X (%11d CWs),"%(total_cw_hi,total_cw_mid,total_cw_lo, total_cw)), + if total_errors == 0 and total_cw != 0: + #ber = 0.0 + if print_en: print ("0"), + elif total_cw == 0: + #ber = -1.0 + if print_en: print ("ERROR. CW Count =0 !!!"), + else: + ber = float(total_errors)/float(total_cw)/float(cw_size) + if print_en: print ("%2.2e"%(ber)), + + wreg(fec_base_addr+0x63,0x8000) # unfreeze the counters, bit[1]=0, + time.sleep(0.010) + wreg(fec_base_addr+0x63,0x8001) # clear the counters for next time, bit[0]=1 + time.sleep(0.010) + wreg(fec_base_addr+0x63,0x8000) # clear the counters for next time, bit[0]=0 + #time.sleep(0.010) + #wreg(fec_base_addr+0x63,0x8010) # turn the clock off to save power, bit[4]=1 + #return total_errors, total_cw, ber +#################################################################################################### +# Set any lane in "shallow loop-back mode internally": +# +# A0-RX looped back out to A0-TX +# A1-RX looped back out to A1-TX +# ... +# B6-RX looped back out to B6-TX +# B7-RX looped back out to B7-TX +# +#################################################################################################### +def sw_config_loopback_mode(lane=None, enable='en'): + + lanes = get_lane_list(lane) + + #### TOP PLL: need to set dvi2 mode + #wreg(0x9500,0x1a68) ## top pll + #wreg(0x9600,0x1a68) + + #get_lane_mode(lanes) # update current Encoding modes of all lanes for this Slice + loopback_bit = 1 if enable == 'en' else 0 + + if loopback_bit==1: # loopback_mode enabled, TX in functional mode + wreg(0x9857,0x0000,lane) # Disable FEC + wreg(0x9858,0x0000,lane) # Disable any lane mapping for Gearbox modes + wreg(0x9859,0x0000,lane) # Disable BM (BitMux) + wreg(0x9855,0x0000,lane) # Disable any lane mapping for Gearbox modes + wreg(0x985f,0x0000,lane) # Disable AN + + wreg(0x98d1,0x8888,lane) # [15:12]=8: B7RX->B7TX, [11:8]=8: B6RX->B6TX, [7:4]=8: B5RX->B5TX, [3:0]=8: B4RX->B4TX + wreg(0x98d2,0x8888,lane) # [15:12]=8: B3RX->B3TX, [11:8]=8: B2RX->B2TX, [7:4]=8: B1RX->B1TX, [3:0]=8: B0RX->B0TX + wreg(0x98d3,0x8888,lane) # [15:12]=8: A7RX->A7TX, [11:8]=8: A6RX->A6TX, [7:4]=8: A5RX->A5TX, [3:0]=8: A4RX->A4TX + wreg(0x98d4,0x8888,lane) # [15:12]=8: A3RX->A3TX, [11:8]=8: A2RX->A2TX, [7:4]=8: A1RX->A1TX, [3:0]=8: A0RX->A0TX + else: # loopback_mode disabled, TX in PRBS mode + wreg(0x98d1,0x0000,lane) # [15:12]=0: B7_RXPLL->B7TX, [11:8]=0: B6_RXPLL->B6TX, [7:4]=0: B5_RXPLL->B5TX, [3:0]=0: B4_RXPLL->B4TX + wreg(0x98d2,0x0000,lane) # [15:12]=0: B3_RXPLL->B3TX, [11:8]=0: B2_RXPLL->B2TX, [7:4]=0: B1_RXPLL->B1TX, [3:0]=0: B0_RXPLL->B0TX + wreg(0x98d3,0x0000,lane) # [15:12]=0: A7_RXPLL->A7TX, [11:8]=0: A6_RXPLL->A6TX, [7:4]=0: A5_RXPLL->A5TX, [3:0]=0: A4_RXPLL->A4TX + wreg(0x98d4,0x0000,lane) # [15:12]=0: A3_RXPLL->A3TX, [11:8]=0: A2_RXPLL->A2TX, [7:4]=0: A1_RXPLL->A1TX, [3:0]=0: A0_RXPLL->A0TX + + + for ln in lanes: + get_lane_mode(ln) + wreg(0x3000+(0x100*ln),0x0000,lane=0) ####disable link training of this lane + wreg(0xe000+(0x100*ln),0xc000,lane=0) ####disable AutoNeg of this lane + + #### TX rotator and pi enable + if loopback_bit==0: # Do this first thing if disabling loop-back mode + wreg([0x0f4, [0]], loopback_bit, ln) ## TX_PLL refclk Source 0: crystal 1:RX_PLL recovered clock + wreg([0x0f3,[14,8]], 0x00 , ln) ## [15]->1, TX phase rotator value + wreg([0x0f3, [15]], loopback_bit, ln) ## [15]->1, TX phase rotator enable + #wreg([0x0f3, [2]], loopback_bit, ln) # 0 or 1 for pam4 + wreg([0x0f3, [2]], 0, ln) # TRF pol is controlled by register 0x79 or 0x17a + + + if loopback_bit==1: # loopback_mode enabled, TX in functional mode + prbs_mode_select(lane=ln, prbs_mode='functional') # Put TX in Functional Mode + else: # loopback_mode disabled, TX in PRBS mode + prbs_mode_select(lane=ln, prbs_mode='prbs') # Put TX in PRBS Mode7 + + ##### Enable loop-back for this lane + if ln==0: #A0 + wreg([0x9811,[1]],loopback_bit,lane=0); wreg([0x9811,[3]],loopback_bit,lane=0); + elif ln==1: #A1 + wreg([0x9819,[1]],loopback_bit,lane=0); wreg([0x9819,[3]],loopback_bit,lane=0); + elif ln==2: #A2 + wreg([0x9821,[1]],loopback_bit,lane=0); wreg([0x9821,[3]],loopback_bit,lane=0); + elif ln==3: #A3 + wreg([0x9829,[1]],loopback_bit,lane=0); wreg([0x9829,[3]],loopback_bit,lane=0); + elif ln==4: #A4 + wreg([0x9831,[1]],loopback_bit,lane=0); wreg([0x9831,[3]],loopback_bit,lane=0); + elif ln==5: #A5 + wreg([0x9839,[1]],loopback_bit,lane=0); wreg([0x9839,[3]],loopback_bit,lane=0); + elif ln==6: #A6 + wreg([0x9841,[1]],loopback_bit,lane=0); wreg([0x9841,[3]],loopback_bit,lane=0); + elif ln==7: #A7 + wreg([0x9849,[1]],loopback_bit,lane=0); wreg([0x9849,[3]],loopback_bit,lane=0); + + elif ln==8: #B0 + wreg([0x9811,[0]],loopback_bit,lane=0); wreg([0x9811,[2]],loopback_bit,lane=0); + elif ln==9: #B1 + wreg([0x9819,[0]],loopback_bit,lane=0); wreg([0x9819,[2]],loopback_bit,lane=0); + elif ln==10: #B2 + wreg([0x9821,[0]],loopback_bit,lane=0); wreg([0x9821,[2]],loopback_bit,lane=0); + elif ln==11: #B3 + wreg([0x9829,[0]],loopback_bit,lane=0); wreg([0x9829,[2]],loopback_bit,lane=0); + elif ln==12: #B4 + wreg([0x9831,[0]],loopback_bit,lane=0); wreg([0x9831,[2]],loopback_bit,lane=0); + elif ln==13: #B5 + wreg([0x9839,[0]],loopback_bit,lane=0); wreg([0x9839,[2]],loopback_bit,lane=0); + elif ln==14: #B6 + wreg([0x9841,[0]],loopback_bit,lane=0); wreg([0x9841,[2]],loopback_bit,lane=0); + elif ln==15: #B7 + wreg([0x9849,[0]],loopback_bit,lane=0); wreg([0x9849,[2]],loopback_bit,lane=0); + else: + print("\nsw_config_loopback_mode: ***> Lane # must be between 0 to 15") + return + + + + ##### TX peer for this lane's RX is lane_name_list[gLanePartnerMap[gSlice][ln]] + # + + if gEncodingMode[gSlice][ln][0] == 'pam4': + if loopback_bit==1: # PAM4 53G PLL_N + #wreg(0x1fd,0x113f,ln) ## perlane RXPLL pll_n + #wreg([0x1f5,[8]],0,ln) ## perlane RXPLLpll[8]->0: div2 not bypassed + #wreg(0x079,0x20a4,ln) ## PAM4 TRF + wreg(0x079,0x3084,ln) ## PAM4 TRF + else: + #wreg(0x1fd,0x223f,ln) ## perlane RXPLLpll_n, same as in the init_pam4/init_nrz + #wreg([0x1f5,[8]],1,ln) ## perlane RXPLLpll[8]->1: div2 bypassed + wreg(0x079,0x00a4,ln) ## PAM4 TRF, set to the same value as in the init_pam4/init_nrz + + else: # NRZ mode (TBD, not completed yet) + if loopback_bit==1: # NRZ 25.78125G PLL_N + #wreg(0x1fd,0x113f,ln) ## perlane RXPLL pll_n??? + #wreg([0x1f6,[8]],0,ln) ## perlane RXPLL pll[8]->0: div2 not bypassed + #wreg(0x17a,0x116C,ln) ## NRZ TRF + wreg(0x17a,0x3084,ln) ## NRZ TRF + else: + #wreg(0x1FD,0x213f,ln) # NRZ mode, RX_PLLN= 33*2*195.3125 | [3:1] //vcoi=0x7 + #wreg(0x1f6,0x71b0,ln) # NRZ mode, vagcbufdac + wreg(0x17a,0x00a4,ln) ## NRZ TRF, set to the same value as in the init_pam4/init_nrz + + if loopback_bit==1: # Do this as the last thing when enabling loopback mode + wreg([0x0f4, [0]], loopback_bit, ln) ## TX_PLL refclk Source 0: crystal 1:RX_PLL recovered clock + +#################################################################################################### +# +# Processes the lane list passed +# Based on number of A-lanes in the list returns... +# ... all lanes connected from A side to B side in retimer mode +# +#################################################################################################### +def get_retimer_lane_list(lane=None, cross_mode=False): + + lanes=get_lane_list(lane) + A_lanes=[x for x in lanes if x < 8] + lanes=A_lanes[:] + for ln in A_lanes: + if cross_mode==False: + lanes.append(ln+8) # retimer straight mode lanes A0-A7 to B0-B7 + else: + if ln<4: + lanes.append(ln+12) # retimer cross mode lanes A0-A3 to B4-B7 + else:# ln>=4: + lanes.append(ln+4) # retimer cross mode lanes A4-A7 to B0-B3 + lanes.sort() + return lanes +#################################################################################################### +def retimer_status(lane=None,print_en=True): + retimer_status = True + lanes = get_lane_list(lane) + A_lanes=[x for x in lanes if x < 8] + if print_en: print("\n...Retimer FIFO Status") + for ln in A_lanes: + fifo_addr = 0x9813 + (ln%8)*8 + fifo_1 = Gray_Bin(rreg([fifo_addr,[15,13]],ln)); + fifo_2 = Gray_Bin(rreg([fifo_addr,[12,10]],ln)); + fifo_3 = Gray_Bin(rreg([fifo_addr,[ 9, 7]],ln)); + fifo_4 = Gray_Bin(rreg([fifo_addr,[ 6, 4]],ln)); + + if fifo_1 != 5 or fifo_2 != 5 or fifo_3 != 5 or fifo_4 != 5 : retimer_status = False + + if print_en: print("\n A%d Rx -->[%d,%d]--> Tx B%d %s"%(ln,fifo_1,fifo_2,ln,'<<' if fifo_1 !=5 or fifo_2 !=5 else '' )), + if print_en: print("\n Tx <--[%d,%d]<-- Rx %s"%(fifo_3,fifo_4,'<<' if fifo_3 !=5 or fifo_4 !=5 else '' )) + if print_en: print("\n") + return retimer_status +#################################################################################################### +# Instruct the FW to configure an A+B lane in retimer mode +# +# Options: +# mode = 'pam4', 'pam4-LT', 'nrz'/'nrz25'/'nrz-LT', 'nrz10', 'nrz20' +# lanes = any of the lanes, i.e. [0,1,2,3,4,5,6,7] or [8,9,10,11,12,13,14,15]"), +# +############################################################################## +def fw_config_retimer (mode=None, lane=range(8), cross_mode=False,print_en=0): + + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. Skipping fw_config_retimer().\n") + return + + retimer_en=1; + LT_en=1 if 'LT' in mode.upper() else 0 + + if mode is None: # or all(ln >= 8 for ln in A_lanes): # if any of the A-lanes > 8 + print("\n*** Instruct the FW to configure an A+B lane in retimer mode"), + print("\n*** Options: "), + print("\n*** mode = 'pam4', 'pam4-LT', 'nrz'/'nrz25'/'nrz-LT', 'nrz10', 'nrz20'"), + print("\n*** lane = any of the A lanes, i.e. [0,1,2,3,4,5,6,7]"), + return + + lanes = get_lane_list(lane) + A_lanes=[x for x in lanes if x < 8] + + speed_str_list =['10','20','25','26','28','51','50','53','56'] # speed as part of mode argument + speed_code_list=[0x11,0x22,0x33,0x44,0x55,0x88,0x99,0x99,0xAA] # speed codes to be written to 0x9807[7:0] + + if 'NRZ' in mode.upper(): + destroy_cmd = 0x9000 if cross_mode==False else 0x9020 # command to destroy a NRZ lane + config_cmd = 0x8000 if cross_mode==False else 0x8020 # command to activate lane in NRZ + speed_code_cmd = 0x33 # default NRZ speed is 25G + for i in range(len(speed_str_list)): # if NRZ speed is specified as part of the mode, take it + if speed_str_list[i] in mode: speed_code_cmd = speed_code_list[i] + if LT_en: + speed_code_cmd += 0x200 + + elif 'PAM4' in mode.upper(): + destroy_cmd = 0x9010 if cross_mode==False else 0x9030 # command to destroy a PAM4 lane + config_cmd = 0x8010 if cross_mode==False else 0x8030 # command to activate lane in PAM4 + speed_code_cmd = 0x66 # default PAM4 speed is 53G + for i in range(len(speed_str_list)): # if PAM4 speed is specified as part of the mode, take it + if speed_str_list[i] in mode: speed_code_cmd = speed_code_list[i] + if LT_en: + speed_code_cmd += 0x200 + + elif any(i in mode.upper() for i in ['OFF','DIS','DISABLE']): + destroy_cmd = 0x9010 if cross_mode==False else 0x9030 # command to destroy a retimer lane + retimer_en=0 + else: + for ln in A_lanes: + print("\n*** fw_config_retimer_mode: selected mode '%s' for lane A%d is invalid" %(mode.upper(), ln)), + return + + ######## First, do all the destroys ############# + for ln in A_lanes: + result = fw_config_cmd (config_cmd=destroy_cmd+ln,config_detail=0x0000) + if (result!=c.fw_config_lane_status): # fw_config_lane_status=0x800 + print("\n***Lane %s: FW could not free up lane before reconfiguring it as retimer. (Error Code 0x%04x)" %(lane_name_list[ln],result)), + #for ln in A_lanes: + # wreg([0xa0,[13]],0,ln) # Make sure TX output is not squelched on A-side + # if cross_mode==False: + # wreg([0xa0,[13]],0,ln+8) # Make sure TX output is not squelched on B-side + # else: + # wreg([0xa0,[13]],0,ln+12) # Make sure TX output is not squelched on B-side + + ######## Next, do all the activates if retimer_en=1 ############# + for ln in A_lanes: + if cross_mode==False: + b_ln = ln + tag = '<--->' + tag2 = 'Direct non-LT Mode' if LT_en==0 else 'Direct LT Mode' + elif ln<4: + b_ln = ln+4 + tag = '<-X->' + tag2 = 'Crossed non-LT Mode' if LT_en==0 else 'Crossed LT Mode' + elif ln>=4: + b_ln = ln-4 + tag = '<-X->' + tag2 = 'Crossed non-LT Mode' if LT_en==0 else 'Crossed LT Mode' + if retimer_en==1: + if print_en: print("\n...FW Retimer: Enabled Retimer in %s between Lanes A%d %s B%d"%(tag2,ln,tag,b_ln)), + result = fw_config_cmd (config_cmd=config_cmd+ln,config_detail=speed_code_cmd) + if (result!=c.fw_config_lane_status): # fw_config_lane_status=0x800 + print("\n***Slice %d Lane %s FW_CONFIG_RETIMER Failed. (SpeedCode 0x9807=0x%04X, ActiveCode 0x9806=0x%04X, ExpectedStatus:0x%0X, ActualStatus=0x%04x)" %(gSlice,lane_name_list[ln],speed_code_cmd, config_cmd+ln,c.fw_config_lane_status,result)), + else: # retimer disabled + if print_en: print("\n...FW Retimer: Disabled Retimer on Lane A%d"%(ln)), + #for ln in A_lanes: + # wreg([0xa0,[13]],0,ln) # Make sure TX output is not squelched on A-side + # if cross_mode==False: + # wreg([0xa0,[13]],0,ln+8) # Make sure TX output is not squelched on B-side + # else: + # wreg([0xa0,[13]],0,ln+12) # Make sure TX output is not squelched on B-side + +#################################################################################################### +# Instruct the FW to configure an A+B lane in Loopback mode +# +# Options: +# mode = 'pam4', 'pam4-LT', 'nrz'/'nrz25'/'nrz-LT', 'nrz10', 'nrz20' +# lanes = any of the lanes, i.e. [0,1,2,3,4,5,6,7] or [8,9,10,11,12,13,14,15]"), +# +############################################################################## +def fw_config_loopback (mode=None, lane=range(16), print_en=0): + + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. Skipping fw_config_loopback().\n") + return + + Loopback_en=1; + + if mode is None: + print("\n*** Instruct the FW to configure an A+B lane in Loopback mode"), + print("\n*** Options: "), + print("\n*** mode = 'pam4', 'nrz'/'nrz25'/'nrz10'/'nrz20'"), + print("\n*** lane = any of anes, i.e. [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]"), + return + + lanes = get_lane_list(lane) + + + speed_str_list =['10','20','25','26','28','51','50','53','56'] # speed as part of mode argument + speed_code_list=[0x11,0x22,0x33,0x44,0x55,0x88,0x99,0x99,0xAA] # speed codes to be written to 0x9807[7:0] + + if 'NRZ' in mode.upper(): + destroy_cmd = 0x90E0 # command to destroy a NRZ lane + config_cmd = 0x80E0 # command to activate lane in NRZ + speed_code_cmd = 0x33 # default NRZ speed is 25G + for i in range(len(speed_str_list)): # if NRZ speed is specified as part of the mode, take it + if speed_str_list[i] in mode: speed_code_cmd = speed_code_list[i] + + elif 'PAM4' in mode.upper(): + destroy_cmd = 0x90F0 # command to destroy a PAM4 lane + config_cmd = 0x80F0 # command to activate lane in PAM4 + speed_code_cmd = 0x66 # default PAM4 speed is 53G + for i in range(len(speed_str_list)): # if PAM4 speed is specified as part of the mode, take it + if speed_str_list[i] in mode: speed_code_cmd = speed_code_list[i] + + elif any(i in mode.upper() for i in ['OFF','DIS','DISABLE']): + destroy_cmd = 0x90F0 # command to destroy a Loopback lane + Loopback_en=0 + else: + for ln in lanes: + print("\n*** fw_config_retimer_mode: selected mode '%s' for lane A%d is invalid" %(mode.upper(), ln)), + return + + ######## First, do all the destroys ############# + for ln in lanes: + result = fw_config_cmd (config_cmd=destroy_cmd+ln,config_detail=0x0000) + if (result!=c.fw_config_lane_status): # fw_config_lane_status=0x800 + print("\n***Lane %s: FW could not free up lane before reconfiguring it as Loopback. (Error Code 0x%04x)" %(lane_name_list[ln],result)), + + for ln in lanes: + if Loopback_en==1: + if print_en: print("\n...FW Loopback: Enabled Loopback on Lane %d"%(ln)), + result = fw_config_cmd (config_cmd=config_cmd+ln,config_detail=speed_code_cmd) + if (result!=c.fw_config_lane_status): # fw_config_lane_status=0x800 + print("\n***Slice %d Lane %s FW_CONFIG_LOOPBACK Failed. (SpeedCode 0x9807=0x%04X, ActiveCode 0x9806=0x%04X, ExpectedStatus:0x%0X, ActualStatus=0x%04x)" %(gSlice,lane_name_list[ln],speed_code_cmd, config_cmd+ln,c.fw_config_lane_status,result)), + else: # Loopback disabled + if print_en: print("\n...FW Loopback: Disabled Loopback on Lane %d"%(ln)), + +#################################################################################################### +# FW to Configure lanes in Bitmux A1:B2 NRZ-NRZ mode +# +# A-side NRZ 2x20G to B-side: NRZ 4x10G +# A-lanes are running exactly at 2X the data rate of the B-lanes +# Must initialize and optimize the lanes in at proper data rate before calling this routine +# +# Options: A_lanes=[0,1] +# A_lanes=[2,3] +# A_lanes=[4,5] +# A_lanes=[0,1,2,3] +# A_lanes=[0,1,4,5] +#################################################################################################### +def fw_config_bitmux_20G(A_lanes=[0,1],print_en=0): + + if not fw_loaded(print_en=0): + print("\n...FW Bitmux 20G: FW not loaded. BITMUX Not Configured!"), + return + + + + # For 2x20G to 4x10G Bitmux mode, 3 options supported for A-Lane groups + group1_bitmux=[0,1] # A_lanes group 1 -> [A0,A1] <-> [B0,B1,B2,B3] + group2_bitmux=[2,3] # A_lanes group 2 -> [A2,A3] <-> [B4,B5,B6,B7] + group3_bitmux=[4,5] # A_lanes group 3 -> [A4,A5] <-> [B4,B5,B6,B7] + + #Determine the corresponding B-Lanes for each group of A-Lanes + group1_selected=0 + group2_selected=0 + B_lanes=[] + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + B_lanes +=[8,9,10,11] + group1_selected=1 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + group2_selected=1 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + group2_selected=1 + + if group1_selected==0 and group2_selected==0: + print("\n*** Bitmux Setup: Invalid Target A-Lanes specified!"), + print("\n*** Options: A_lanes=[0,1]"), + print("\n*** A_lanes=[2,3]"), + print("\n*** A_lanes=[4,5]"), + print("\n*** A_lanes=[0,1,2,3]"), + print("\n*** A_lanes=[0,1,4,5]"), + return + + #lanes = sorted(list(set(A_lanes + B_lanes))) + #prbs_mode_select(lane=lanes, prbs_mode='functional') + + ######## First, do all the destroys ############# + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [0,1] + fw_config_cmd(config_cmd=0x9040,config_detail=0x0000) # 0x9040 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9041,config_detail=0x0000) # 0x9041 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + fw_config_cmd(config_cmd=0x9042,config_detail=0x0000) # 0x9041 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9043,config_detail=0x0000) # 0x9042 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9044,config_detail=0x0000) # 0x9043 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9045,config_detail=0x0000) # 0x9044 = First, FW destroy any instances of these lanes being already used + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + fw_config_cmd(config_cmd=0x9042,config_detail=0x0000) # 0x9041 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9043,config_detail=0x0000) # 0x9042 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9044,config_detail=0x0000) # 0x9043 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9045,config_detail=0x0000) # 0x9044 = First, FW destroy any instances of these lanes being already used + + + ######## Next, do all the activates ############# + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + if print_en: print("\n...FW BitMux 20G : Setting Up Lane A0/A1 to B0/B1/B2/B3..."), + fw_config_cmd(config_cmd=0x8040,config_detail=0x0021) # 0x8040 = FW to Activate Bitmux A1B2 NRZ for Lane A0, 0x0021 = FW Bitmux A1B2 NRZ command + fw_config_cmd(config_cmd=0x8041,config_detail=0x0021) # 0x8041 = FW to Activate Bitmux A1B2 NRZ for Lane A1, 0x0021 = FW Bitmux A1B2 NRZ command + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + if print_en: print("\n...FW BitMux 20G : Setting Up Lane A2/A3 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8042,config_detail=0x0021) # 0x8042 = FW to Activate Bitmux A1B2 NRZ for Lane A2, 0x0021 = FW Bitmux A1B2 NRZ command + fw_config_cmd(config_cmd=0x8043,config_detail=0x0021) # 0x8043 = FW to Activate Bitmux A1B2 NRZ for Lane A3, 0x0021 = FW Bitmux A1B2 NRZ command + + ######## Bitmux A4/A5 to B4/B5/B6/B7 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + if print_en: print("\n...FW BitMux 20G : Setting Up Lane A4/A5 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8044,config_detail=0x0021) # 0x8044 = FW to Activate Bitmux A1B2 NRZ for Lane A4, 0x0021 = FW Bitmux A1B2 NRZ command + fw_config_cmd(config_cmd=0x8045,config_detail=0x0021) # 0x8045 = FW to Activate Bitmux A1B2 NRZ for Lane A5, 0x0021 = FW Bitmux A1B2 NRZ command + + #prbs_mode_select(lane=lanes, prbs_mode='functional') + #fw_adapt_wait(max_wait=20, lane=A_lanes+B_lanes, print_en=1) + + return A_lanes, B_lanes +#################################################################################################### +# FW to Configure lanes in Bitmux A1:B2 NRZ-NRZ mode +# +# A-side NRZ 2x20G to B-side: NRZ 4x10G +# A-lanes are running exactly at 2X the data rate of the B-lanes +# Must initialize and optimize the lanes in at proper data rate before calling this routine +# +# Options: A_lanes=[0,1] +# A_lanes=[2,3] +# A_lanes=[4,5] +# A_lanes=[0,1,2,3] +# A_lanes=[0,1,4,5] +#################################################################################################### +def fw_config_bitmux_40G_LT(A_lanes=[0,1,2,3],print_en=0): + + if not fw_loaded(print_en=0): + print("\n...FW Bitmux 20G: FW not loaded. BITMUX Not Configured!"), + return + + + + # For 2x20G to 4x10G Bitmux mode, 3 options supported for A-Lane groups + group1_bitmux=[0,1] # A_lanes group 1 -> [A0,A1] <-> [B0,B1,B2,B3] + group2_bitmux=[2,3] # A_lanes group 2 -> [A2,A3] <-> [B4,B5,B6,B7] + group3_bitmux=[4,5] # A_lanes group 3 -> [A4,A5] <-> [B4,B5,B6,B7] + + #Determine the corresponding B-Lanes for each group of A-Lanes + group1_selected=0 + group2_selected=0 + B_lanes=[] + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + B_lanes +=[8,9,10,11] + group1_selected=1 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + group2_selected=1 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + group2_selected=1 + + if group1_selected==0 and group2_selected==0: + print("\n*** 40G-ANLT Bitmux Setup: Invalid Target A-Lanes specified!"), + print("\n*** Options: A_lanes=[0,1]"), + print("\n*** A_lanes=[2,3]"), + print("\n*** A_lanes=[4,5]"), + print("\n*** A_lanes=[0,1,2,3]"), + print("\n*** A_lanes=[0,1,4,5]"), + return + + #lanes = sorted(list(set(A_lanes + B_lanes))) + #prbs_mode_select(lane=lanes, prbs_mode='functional') + + ######## First, do all the destroys ############# + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [0,1] + fw_config_cmd(config_cmd=0x9046,config_detail=0x0000) # 0x9046 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + fw_config_cmd(config_cmd=0x9047,config_detail=0x0000) # 0x9046 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9048,config_detail=0x0000) # 0x9047 = First, FW destroy any instances of these lanes being already used + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + fw_config_cmd(config_cmd=0x9047,config_detail=0x0000) # 0x9047 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9048,config_detail=0x0000) # 0x9048 = First, FW destroy any instances of these lanes being already used + + + ######## Next, do all the activates ############# + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + if print_en: print("\n...FW BitMux 40G-ANLT : Setting Up Lane A0/A1 to B0/B1/B2/B3..."), + fw_config_cmd(config_cmd=0x8046,config_detail=0x0221) # 0x8046 = FW to Activate ANLT Bitmux A1B2 NRZ for Lane A0, 0x0021 = FW Bitmux A1B2 NRZ command + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + if print_en: print("\n...FW BitMux 40G-ANLT : Setting Up Lane A2/A3 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8047,config_detail=0x0221) # 0x8047 = FW to Activate ANLT Bitmux A1B2 NRZ for Lane A2, 0x0021 = FW Bitmux A1B2 NRZ command + + ######## Bitmux A4/A5 to B4/B5/B6/B7 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + if print_en: print("\n...FW BitMux 40G-ANLT : Setting Up Lane A4/A5 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8048,config_detail=0x0221) # 0x8044 = FW to Activate Bitmux A1B2 NRZ for Lane A4, 0x0021 = FW Bitmux A1B2 NRZ command + + #prbs_mode_select(lane=lanes, prbs_mode='functional') + #fw_adapt_wait(max_wait=20, lane=A_lanes+B_lanes, print_en=1) + + return A_lanes, B_lanes +#################################################################################################### +# FW to Configure lanes in Bitmux A1:B2 PAM4-NRZ mode +# +# A-side NRZ 2x53G to B-side: NRZ 4x26G +# A-lanes are running exactly at 2X the data rate of the B-lanes +# Must initialize and optimize the lanes in at proper data rate before calling this routine +# +# Options: A_lanes=[0,1] +# A_lanes=[2,3] +# A_lanes=[4,5] +# A_lanes=[0,1,2,3] +# A_lanes=[0,1,4,5] +#################################################################################################### +def fw_config_bitmux_53G(A_lanes=[0,1],print_en=0): + + if not fw_loaded(print_en=0): + print("\n...FW Bitmux 53G: FW not loaded. BITMUX Not Configured!"), + return + + # For 2x20G to 4x10G Bitmux mode, 3 options supported for A-Lane groups + group1_bitmux=[0,1] # A_lanes group 1 -> [A0,A1] <-> [B0,B1,B2,B3] + group2_bitmux=[2,3] # A_lanes group 2 -> [A2,A3] <-> [B4,B5,B6,B7] + group3_bitmux=[4,5] # A_lanes group 3 -> [A4,A5] <-> [B4,B5,B6,B7] + + #Determine the corresponding B-Lanes for each group of A-Lanes + group1_selected=0 + group2_selected=0 + B_lanes=[] + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + B_lanes +=[8,9,10,11] + group1_selected=1 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + group2_selected=1 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + group2_selected=1 + + if group1_selected==0 and group2_selected==0: + print("\n*** Bitmux Setup: Invalid Target A-Lanes specified!"), + print("\n*** Options: A_lanes=[0,1]"), + print("\n*** A_lanes=[2,3]"), + print("\n*** A_lanes=[4,5]"), + print("\n*** A_lanes=[0,1,2,3]"), + print("\n*** A_lanes=[0,1,4,5]"), + return + + #lanes = sorted(list(set(A_lanes + B_lanes))) + #prbs_mode_select(lane=lanes, prbs_mode='functional') + + + ######## First, do all the destroys ############# + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [0,1] + fw_config_cmd(config_cmd=0x9050,config_detail=0x0000) # 0x9050 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9051,config_detail=0x0000) # 0x9051 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + fw_config_cmd(config_cmd=0x9052,config_detail=0x0000) # 0x9052 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9053,config_detail=0x0000) # 0x9053 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9054,config_detail=0x0000) # 0x9054 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9055,config_detail=0x0000) # 0x9055 = First, FW destroy any instances of these lanes being already used + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + fw_config_cmd(config_cmd=0x9052,config_detail=0x0000) # 0x9052 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9053,config_detail=0x0000) # 0x9053 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9054,config_detail=0x0000) # 0x9054 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9055,config_detail=0x0000) # 0x9055 = First, FW destroy any instances of these lanes being already used + + + + ######## Next, do all the activates ############# + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + if print_en: print("\n...FW BitMux 53G : Setting Up Lane A0/A1 to B0/B1/B2/B3..."), + fw_config_cmd(config_cmd=0x8050,config_detail=0x0064) # 0x8050 = FW to Activate Bitmux 53G for Lane A0, 0x0064 = FW Bitmux 53G command + fw_config_cmd(config_cmd=0x8051,config_detail=0x0064) # 0x8051 = FW to Activate Bitmux 53G for Lane A1, 0x0064 = FW Bitmux 53G command + + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + if print_en: print("\n...FW BitMux 53G : Setting Up Lane A2/A3 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8052,config_detail=0x0064) # 0x8052 = FW to Activate Bitmux 53G for Lane A2, 0x0064 = FW Bitmux 53G command + fw_config_cmd(config_cmd=0x8053,config_detail=0x0064) # 0x8053 = FW to Activate Bitmux 53G for Lane A3, 0x0064 = FW Bitmux 53G command + + + ######## Bitmux A4/A5 to B4/B5/B6/B7 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + if print_en: print("\n...FW BitMux 53G : Setting Up Lane A4/A5 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8054,config_detail=0x0064) # 0x8054 = FW to Activate Bitmux 53G for Lane A4, 0x0064 = FW Bitmux 53G command + fw_config_cmd(config_cmd=0x8055,config_detail=0x0064) # 0x8055 = FW to Activate Bitmux 53G for Lane A5, 0x0064 = FW Bitmux 53G command + + + #fw_adapt_wait(max_wait=20, lane=A_lanes+B_lanes, print_en=1) + + + return A_lanes, B_lanes + +def fw_config_bitmux_51G(A_lanes=[0,1],print_en=0): + + if not fw_loaded(print_en=0): + print("\n...FW Bitmux 53G: FW not loaded. BITMUX Not Configured!"), + return + + # For 2x20G to 4x10G Bitmux mode, 3 options supported for A-Lane groups + group1_bitmux=[0,1] # A_lanes group 1 -> [A0,A1] <-> [B0,B1,B2,B3] + group2_bitmux=[2,3] # A_lanes group 2 -> [A2,A3] <-> [B4,B5,B6,B7] + group3_bitmux=[4,5] # A_lanes group 3 -> [A4,A5] <-> [B4,B5,B6,B7] + + #Determine the corresponding B-Lanes for each group of A-Lanes + group1_selected=0 + group2_selected=0 + B_lanes=[] + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + B_lanes +=[8,9,10,11] + group1_selected=1 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + B_lanes+=[12,13,14,15] + group2_selected=1 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + B_lanes+=[12,13,14,15] + group2_selected=1 + + if group1_selected==0 and group2_selected==0: + print("\n*** Bitmux Setup: Invalid Target A-Lanes specified!"), + print("\n*** Options: A_lanes=[0,1]"), + print("\n*** A_lanes=[2,3]"), + print("\n*** A_lanes=[4,5]"), + print("\n*** A_lanes=[0,1,2,3]"), + print("\n*** A_lanes=[0,1,4,5]"), + return + + #lanes = sorted(list(set(A_lanes + B_lanes))) + #prbs_mode_select(lane=lanes, prbs_mode='functional') + + + ######## First, do all the destroys ############# + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [0,1] + fw_config_cmd(config_cmd=0x9060,config_detail=0x0000) # 0x9050 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9061,config_detail=0x0000) # 0x9051 = First, FW destroy any instances of these lanes being already used + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + fw_config_cmd(config_cmd=0x9062,config_detail=0x0000) # 0x9052 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9063,config_detail=0x0000) # 0x9053 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9064,config_detail=0x0000) # 0x9054 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9065,config_detail=0x0000) # 0x9055 = First, FW destroy any instances of these lanes being already used + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + fw_config_cmd(config_cmd=0x9062,config_detail=0x0000) # 0x9052 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9063,config_detail=0x0000) # 0x9053 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9064,config_detail=0x0000) # 0x9054 = First, FW destroy any instances of these lanes being already used + fw_config_cmd(config_cmd=0x9065,config_detail=0x0000) # 0x9055 = First, FW destroy any instances of these lanes being already used + + + + ######## Next, do all the activates ############# + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group1_bitmux): # If A_lanes contains [0,1] + if print_en: print("\n...FW BitMux 53G : Setting Up Lane A0/A1 to B0/B1/B2/B3..."), + fw_config_cmd(config_cmd=0x8060,config_detail=0x0083) # 0x8050 = FW to Activate Bitmux 53G for Lane A0, 0x0064 = FW Bitmux 53G command + fw_config_cmd(config_cmd=0x8061,config_detail=0x0083) # 0x8051 = FW to Activate Bitmux 53G for Lane A1, 0x0064 = FW Bitmux 53G command + + + ######## Bitmux A2/A3 to B4/B5/B6/B7 + if all(elem in A_lanes for elem in group2_bitmux): # If A_lanes contains [2,3] + if print_en: print("\n...FW BitMux 53G : Setting Up Lane A2/A3 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8062,config_detail=0x0083) # 0x8052 = FW to Activate Bitmux 53G for Lane A2, 0x0064 = FW Bitmux 53G command + fw_config_cmd(config_cmd=0x8063,config_detail=0x0083) # 0x8053 = FW to Activate Bitmux 53G for Lane A3, 0x0064 = FW Bitmux 53G command + + + ######## Bitmux A4/A5 to B4/B5/B6/B7 + elif all(elem in A_lanes for elem in group3_bitmux): # If A_lanes contains [4,5] + if print_en: print("\n...FW BitMux 53G : Setting Up Lane A4/A5 to B4/B5/B6/B7..."), + fw_config_cmd(config_cmd=0x8064,config_detail=0x0083) # 0x8054 = FW to Activate Bitmux 53G for Lane A4, 0x0064 = FW Bitmux 53G command + fw_config_cmd(config_cmd=0x8065,config_detail=0x0083) # 0x8055 = FW to Activate Bitmux 53G for Lane A5, 0x0064 = FW Bitmux 53G command + + + #fw_adapt_wait(max_wait=20, lane=A_lanes+B_lanes, print_en=1) + + + return A_lanes, B_lanes + +#################################################################################################### +# +# Configure specified lane(s) in NRZ or PAM4 mode +# +# Note: this function sets minimum requirement for a lane to be in PAM4 or NRZ mode +# It does not do a complete initialization of the lane in a NRZ/PAM4 mode +# See init_lane() for complete initialization. +#################################################################################################### +def set_lane_mode(mode='pam4',lane=None): + + lanes = get_lane_list(lane) + + for ln in lanes: + if mode.upper()!='PAM4': # put lanes in NRZ mode + wreg([0x041,[15]],0, ln) # Disable PAM4 mode + wreg([0x0a0,[13]],0, ln) # Disable PAM4 PRBS Generator + wreg([0x0b0, [1]],1, ln) # Enable NRZ mode + wreg([0x0b0,[11]],1, ln) # Enable NRZ PRBS Generator + else: #################### put lanes in PAM4 mode + wreg([0x0b0, [1]],0, ln) # Disable NRZ mode + wreg([0x0b0,[11]],0, ln) # Disable NRZ PRBS Generator + wreg([0x041,[15]],1, ln) # Enable PAM4 mode + wreg([0x0a0,[13]],1, ln) # Enable PAM4 PRBS Generator +#################################################################################################### +# +# Checks to see if a lane is in PAM4 or NRZ mode +# +# updates the global gEncodingMode variable for this Slice and this lane +# returns: list of [NRZ/PAM4, speed] per lane +# +#################################################################################################### +def get_lane_mode(lane=None): + + lanes = get_lane_list(lane) + + global gEncodingMode + + for ln in lanes: + + if rreg([0x0ff,[12]],ln)==0 or rreg([0x1ff,[12]],ln)==0: # Lane's bandgap is OFF + #print ("\n Slice %d lane %2d is OFF"%(gSlice,ln)), + data_rate= 1.0 + gEncodingMode[gSlice][ln] = ['off',data_rate] + lane_mode_list[ln] = 'off' + + elif rreg([0xb0,[1]],ln) == 0 and rreg([0x41,[15]],ln) == 1: + #print ("\n Slice %d lane %2d is PAM4"%(gSlice,ln)), + data_rate= get_lane_pll(ln)[ln][0][0] + gEncodingMode[gSlice][ln] = ['pam4',data_rate] + lane_mode_list[ln] = 'pam4' + else: + #print ("\n Slice %d lane %2d is NRZ"%(gSlice,ln)), + data_rate= get_lane_pll(ln)[ln][0][0] + gEncodingMode[gSlice][ln] = ['nrz',data_rate] + lane_mode_list[ln] = 'nrz' + + return gEncodingMode +#################################################################################################### +# +# Initialize lane(s) in NRZ or PAM4 mode +# +# Note: this function does a complete initialization of the lane in a NRZ/PAM4 mode +# It does not adapt the RX of the lane to the connected channel +# See opt_lane() for optimization of lane +#################################################################################################### +def init_lane(mode='pam4',datarate=None,input_mode='ac',lane=None): + + lanes = get_lane_list(lane) + + for ln in lanes: + if 'NRZ' in mode.upper(): # put lanes in NRZ mode + if datarate!=None: init_lane_nrz (datarate,input_mode,ln) # NRZ at exactly the requested datarate + elif '10' in mode: init_lane_nrz (10.3125, input_mode,ln) # NRZ-10G + elif '20' in mode: init_lane_nrz (20.6250, input_mode,ln) # NRZ-20G + elif '25' in mode: init_lane_nrz (25.78125,input_mode,ln) # NRZ-25G + else: init_lane_nrz (25.78125,input_mode,ln) # NRZ-25G, or exactly the requested datarate + else: #################### put lanes in PAM4 mode + init_lane_pam4(datarate,input_mode,ln) +#################################################################################################### +# +# Initialize and adapt lane(s) in NRZ or PAM4 mode +# +# Note: this function does a complete initialization and adaptation of lane in a NRZ/PAM4 mode +# It optimizes the RX of the lane to the connected channel +#################################################################################################### +def opt_lane(mode='pam4',datarate=None, input_mode='ac',lane=None): + + lanes = get_lane_list(lane) + set_bandgap('on', 'all') + set_top_pll(pll_side='both', freq=195.3125) + + #### FW-based Adaptation + if fw_loaded(print_en=0): + for ln in lanes: + #init_lane_for_fw(mode = mode,tx_pol=1, rx_pol=RxPolarityMap[gSlice][ln],input_mode = input_mode,lane=ln) + init_lane_for_fw(mode,datarate,input_mode,ln) + fw_config_lane(mode,datarate,lanes) + fw_adapt_wait (lane=lanes, print_en=2) + + #### Python-based Adaptation + else: + for ln in lanes: + if 'NRZ' in mode.upper(): # put lanes in NRZ mode and optimize them + if datarate!=None: opt_lane_nrz (datarate,input_mode,ln) # NRZ-25G, or exactly the requested datarate + elif '10' in mode: opt_lane_nrz (10.3125, input_mode,ln) # NRZ-10G + elif '20' in mode: opt_lane_nrz (20.6250, input_mode,ln) # NRZ-20G + elif '25' in mode: opt_lane_nrz (25.78125,input_mode,ln) # NRZ-25G + else: opt_lane_nrz (25.78125,input_mode,ln) # NRZ-25G, or exactly the requested datarate + else: #################### put lanes in PAM4 mode and optimize them + opt_lane_pam4(datarate,input_mode,ln) + +#################################################################################################### +# +# Initialize target lane(s) in NRZ mode +# +# Note: this function does a complete initialization of the lane in a NRZ mode +# It does not adapt the RX of the lane to the connected channel +# See opt_lane() for complete initialization. +#################################################################################################### +def init_lane_for_fw(mode='nrz',tx_pol=1,rx_pol=0, input_mode='ac',lane=None): + #print'\n...init_lane_for_fw' + lanes = get_lane_list(lane) + global gEncodingMode + + + for ln in lanes: + set_lane_mode(mode=mode,lane=ln) + ####################### put lane in PAM4 mode + if ('PAM4' in mode.upper()): + wreg([0x0af,[5,1]],0x4,lane=gLanePartnerMap[gSlice][ln][1]) # TX Taps scales = (0.5,0.5, 1, 0.5,0.5) + tx_taps(2,-8,17,0,0,lane=ln) + # PAM4 mode, gc=en | Pre=dis | masblsb= default + gc(1,1,lane=ln) + pc(0,0,lane=ln) + msblsb(0,0,lane=ln) + + if gPrbsEn: + prbs_mode_select(lane=ln,prbs_mode='prbs') # PAM4 mode, tx pam4 prbs31 + #wreg(0x042,0xb3fd,ln) + else: + prbs_mode_select(lane=ln,prbs_mode='functional') # PAM4 mode, TX pam4 FUNCTIONAL MODE + #wreg(0x042,0xb3fd,ln) # PAM4 mode, Rx PAM4 gc=en | Pre=dis + + ####################### put lane in NRZ mode + if ('NRZ' in mode.upper()): + wreg([0x0af,[5,1]],0x4,lane=gLanePartnerMap[gSlice][ln][1]) # TX Taps scales = (0.5,0.5, 1, 0.5,0.5) + #tx_taps(0,-8,17,0,0,lane=ln) + #tx_taps(0,0,31,0,0,lane=ln) + #tx_taps(0,-2,25,0,-2,lane=ln) + if ((sel_slice() == 3 or sel_slice() == 2) and ln<=11):#Port 1,2 + tx_taps(0,-2,25,0,-5,lane=ln) + elif (sel_slice() == 7 and ln<=11):#Port3 + tx_taps(0,-4,24,0,0,lane=ln) + elif ((sel_slice() == 6 or sel_slice() == 14 or sel_slice() == 15 or sel_slice() == 31) and ln <=11):#Port4,5,6,7 + tx_taps(0,-4,27,0,-2,lane=ln) + elif((sel_slice() == 6 or sel_slice() == 7 or sel_slice() == 15) and (ln >= 12 and ln <=15)):#Port 10,11,12,13,14 + tx_taps(0,-3,27,0,-5,lane=ln) + elif(sel_slice() == 30 and (ln >= 8 and ln <=13)): #Port 8 and Port 9(lane 1~2) + tx_taps(0,-3,27,0,-5,lane=ln) + elif(sel_slice() == 31 and (ln >= 14 and ln <=15)): #Port 9(lane 3~4) + tx_taps(0,-3,26,0,-5,lane=ln) + else: + tx_taps(0,-2,25,0,-2,lane=ln) + + # NRZ mode, gc=dis | Pre=dis | masblsb= default (none applies in NRZ mode) + gc(0,0,lane=ln) + pc(0,0,lane=ln) + msblsb(0,0,lane=ln) + #wreg([0x161,[8]],1,ln) # NRZ freq_loop enable ## FW set this during init_lane + if gPrbsEn: #print'PRBS_ON' + prbs_mode_select(lane=ln,prbs_mode='prbs') + #wreg(0x161,0x7520,ln) # NRZ mode, Rx checker + else: #print'FUNCTIONAL_ON' + prbs_mode_select(lane=ln,prbs_mode='functional') + #wreg(0x161,0x3520,ln) # NRZ mode, Rx checker off + + if chip_rev()==2.0: + wreg([0x07b,[3]], 1, ln) # R2.0 PAM4 BLWC Pol = 1 + wreg([0x17c,[15]], 0, ln) # R2.0 NRZ BLWC en = 0 (disabled) + + if (input_mode=='dc'): + wreg(c.rx_vcomrefsel_ex_addr,1,ln) # DC-Coupled mode 0x1DD[9]=1 + wreg(c.rx_en_vcominbuf_addr ,1,ln) # DC-Coupled mode 0x1E7[11]=1 + else: + wreg(c.rx_vcomrefsel_ex_addr,0,ln) # AC-Coupled mode 0x1DD[9]=0 + wreg(c.rx_en_vcominbuf_addr ,1,ln) # AC-Coupled mode 0x1E7[11]=1 + + # Set the polarities of the lanes + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + + +def init_lane_nrz(datarate=None, input_mode='ac',lane=None): + + lanes = get_lane_list(lane) + global gEncodingMode + c=NrzReg + + if datarate is None: datarate=25.78125 + # if datarate!=None: datarate=datarate # NRZ at exactly the requested datarate + # elif '10' in mode: datarate=10.3125 # NRZ-10G + # elif '20' in mode: datarate=20.6250 # NRZ-20G + # elif '25' in mode: datarate=25.78125 # NRZ-25G + # else: datarate=25.78125 # NRZ-25G + + for ln in lanes: + #print("\ninit_lane_nrz(): Lane %s, Target DataRate=%3.5fG, Actual DataRate=%3.5f G"%(lane_name_list[ln],datarate,get_lane_pll(ln)[ln][0][0])), + gEncodingMode[gSlice][ln] = ['nrz',datarate] + lane_mode_list[ln] = 'nrz' + ####disable AN/LT registers as default + wreg(0x3000+(0x100*ln),0x0000,lane=0) + wreg(0xe000+(0x100*ln),0xc000,lane=0) + # ---------------- LANE Q NRZ init begin + + #wreg(c.rx_lane_rst_addr, 1, ln) # Keep lane in Reset while programming lane + #wreg(c.rx_pll_pu_addr, 0, ln) # Power down RX PLL while prgramming PLL + #wreg(c.tx_pll_pu_addr, 0, ln) # Power down RX PLL while prgramming PLL + ####################### NRZ mode, Per-Lane PLLs ### + wreg(0x0D7,0x0000,ln) # NRZ mode, TX_PLL, Fractional PLL off + wreg(0x0D8,0x0000,ln) # NRZ mode, TX_PLL, Fractional PLL off + wreg(0x1F0,0x0000,ln) # NRZ mode, RX_PLL, Fractional PLL off + wreg(0x1F1,0x0000,ln) # NRZ mode, RX_PLL, Fractional PLL off + + #wreg(0x0FF,0x5df6,ln) # NRZ mode, TX_BG bandgap | div4=0 + #wreg(0x0FE,0x213e,ln) # NRZ mode, TX PLLN = 66*195.3125 | [3:1] //vcoi=0x7 + wreg(0x0FF,0x5df4,ln) # NRZ mode, TX_BG bandgap | div4=0, div2_pass=0 + wreg(0x0FE,0x10bf,ln) # NRZ mode, TX PLLN = 33*195.3125 | [3:1] //vcoi=0x7 + wreg(0x0FD,0x5636,ln) # NRZ mode, TX PLL,bypass_pll=0 + #wreg(0x0FD,0x5436,ln) # NRZ mode, TX PLL, clear bypass 1p7 regulator 0xFD[9] + wreg(0x0FC,0x7236,ln) # NRZ mode, TX PLL,vvco_reg + wreg(0x0FB,0x7fb7,ln) # NRZ mode, TX PLL,vref_intp + wreg(0x0FA,0x8010,ln) # NRZ mode, TX PLL,testmode_tx_pll + wreg(0x0DB,0x2100,ln) # NRZ mode, TX PLL,[14:8] // tx_vcocap=rx_vcocap=33 or 34 for fvco=25.78125G + wreg(0x0DA,0x7de6,ln) # NRZ mode, TX PLL,[14:10]// bm_vco=0x1f + wreg(0x0D9,0xb760,ln) # NRZ mode, + + wreg(0x1FF,0x5db1,ln) # NRZ mode, RX_BG bandgap | [15:13]//vbg=0 + + wreg(0x1FD,0x213f,ln) # NRZ mode, RX_PLLN= 33*2*195.3125 | [3:1] //vcoi=0x7 + #wreg(0x1FC,0x1048,ln) # NRZ mode, RX PLL, clear bypass 1p7 regulator 0x1FC[9] + wreg(0x1F5,0x4340,ln) # NRZ mode, RX PLL, lcvco_cap [15:9] //rx_vcocap=33 or 34 for fvco=25.78125G + wreg(0x1F4,0x7de6,ln) # NRZ mode, RX PLL, en_div2=0 | [14:10]//bm_vco=0x1f + wreg(0x1F3,0xb760,ln) # NRZ mode, RX PLL, pu_intp_rx + + + + ####################### analog ### + + wreg(0x0f1,0x000f,ln) # NRZ mode, pu_adc|pu_clkcomp|pu_clkreg + wreg(0x0ef,0x9230,ln) # NRZ mode, vrefadc + wreg(0x0ee,0x691c,ln) # NRZ mode, calnbs_top|bot + wreg(0x0ed,0x7777,ln) # NRZ mode, edge + wreg(0x0eb,0x67fc,ln) # NRZ mode, TX Swing + + wreg(0x1f9,0x7686,ln) # NRZ mode, vrefagcdegen + wreg(0x1f6,0x71b0,ln) # NRZ mode, vagcbufdac + wreg(0x1e7,0xc34c,ln) # NRZ mode, pu_agc|pu_agcdl | en_vcominbuf=0 + wreg(0x1e6,0x88a5,ln) # NRZ mode, bypass_agcreg + wreg(0x1e5,0x6c38,ln) # NRZ mode, 4e3c # vrefagc1p5reg + + wreg(0x1dd,0xc162,ln) # NRZ mode, c1e2 # ffe_delay | en_skef | skef_value + wreg(0x1da,0x6f00,ln) # NRZ mode, 6d80 # clkphase0 + + wreg(0x1d4,0x01c0,ln) # NRZ mode, agcgain1 | agacgain2 + wreg(0x1d5,0x0100,ln) # NRZ mode, blwc_en + wreg(0x1d6,0xee00,ln) # NRZ mode, en_az_short_pulse + + ####################### NRZ Mode Configuration + wreg(0x041,0x0000,ln) # NRZ mode, Toggle PAM4_RX_ENABLE + wreg(0x041,0x8000,ln) # NRZ mode, Toggle PAM4_RX_ENABLE + wreg(0x041,0x0000,ln) # NRZ mode, Toggle PAM4_RX_ENABLE + wreg(0x0b0,0x4802,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode (4802) | Toggle PAM4_TX_ENABLE + wreg(0x0b0,0x0000,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode (4802) | Toggle PAM4_TX_ENABLE + wreg(0x0b0,0x4802,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode (4802) | Toggle PAM4_TX_ENABLE + wreg(0x1e7,0x836c,ln) # NRZ mode, ffe disable in nrz mode (agc_dl=0) + + ####################### NRZ SM Configuration + #wreg(0x101,0x4201,ln) + wreg(0x101,0x0201,ln) # NRZ mode, delta_freeze + wreg(0x102,0x1006,ln) # NRZ mode, cntr_target=0x100 during link-up, change to 0x002 after + wreg(0x103,0x5933,ln) + wreg(0x104,0x700a,ln) + #wreg(0x105,0x8682,ln) #8e82, # UPDATE 20180521 + #wreg(0x105,0x8e82,ln) #8e82, + wreg(0x106,0xA100,ln) + wreg(0x108,0x688B,ln) + wreg(0x10C,0x8000,ln) + wreg(0x13B,0xe000,ln) # NRZ mode, Set KP=6, # UPDATE 20180521 + #wreg(0x145,0x8080,ln) # commented out CHANGE_FOR_10G, # UPDATE 20180521 + wreg(0x14D,0x8000,ln) # NRZ mode, OW INIT_FREQ=0 + wreg([0x014D, [10,0]], 0x7D8, ln) #set one initial freq to be -160ppm, # CHANGE_FOR_10G, # UPDATE 20180521 + wreg(0x14F,0x0100,ln) + wreg(0x150,0x5040,ln) + wreg(0x161,0x0120,ln) # NRZ mode, Rx checker power-down. + wreg(0x163,0x0080,ln) + wreg(0x164,0x8080,ln) + wreg(0x179,0x8874,ln) # 887e bb_mode=1 + wreg(0x180,0x3500,ln) + wreg(0x181,0x1000,ln) + wreg([0x0181, [10,0]], 0x7D8, ln) #set one initial freq to be -160ppm, # CHANGE_FOR_10G, # UPDATE 20180521 + wreg(0x182,0xD800,ln) + + #wreg(0x18C,0x0040,ln) # CHANGE_FOR_10G # UPDATE 20180521 + wreg(0x176,0x418A,ln) #209a ctle_map + wreg(0x177,0x3837,ln) + wreg(0x178,0x97EE,ln) + wreg(0x14E,0x3800,ln) #CTLE=7 + + wreg(0x17C,0x0000,ln) # REV_2.0 default = 0x8001 + + ####################### NRZ mode, TX setting + if gNrzTxSourceIsCredo: + wreg(0x0a5,0x0000,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, pre2 + wreg(0x0a7,0xf800,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, pre1 + wreg(0x0a9,0x1100,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, main + wreg(0x0ab,0x0000,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, post1 + wreg(0x0ad,0x0000,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, post2 + wreg(0x0af,0xfc08,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, tx_automode|no gc|nopre |SHmode + + ####################### NRZ mode, TX PRBS gen and Rx PRBS checker + if gPrbsEn: + wreg(0x0a0,0xeb20,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, tx prbs31 + wreg(0x0a0,0xe320,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, tx prbs31 + wreg(0x0a0,0xeb20,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, tx prbs31 + wreg(0x161,0x7520,ln) # NRZ mode, Rx checker + else: + wreg(0x0a0,0x0120,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, TX functional mode + wreg(0x0a0,0x0120,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, TX functional mode + wreg(0x0a0,0x0120,lane=gLanePartnerMap[gSlice][ln][1]) # NRZ mode, TX functional mode + wreg(0x161,0x3520,ln) # NRZ mode, Rx checker off + + #set_lane_pll(tgt_pll='both',datarate=datarate, div2=0, lane=ln) + + if chip_rev()==2.0: + wreg([0x07b,[3]], 1, ln) # R2.0 PAM4 BLWC Pol = 1 + wreg([0x17c,[15]], 0, ln) # R2.0 NRZ BLWC en = 0 (disabled) + if datarate < 24.0: # If 10G or 20G using Frac-N, expanded to 20 bits for TX-PLL + wreg([0x0d9,[3,0]],0x6, ln) # NRZ-10G/20G mode, 0x0D9[3:0] TX PLL FRAC_N[19:16]=0x6 = 0.4 (R2.0: 20 bits, R1.0: 16 bits) + + if datarate < 15.0: # NRZ 10.3125G , NRZ Half-Rate Mode + #### disable Fractional PLLs while programming PLLs, # UPDATE 20180521 + wreg(c.tx_pll_frac_en_addr, 0, ln) # NRZ-10G mode, 0x0D7 [13] TX PLL FRAC_EN=0 while programming PLLs + wreg(c.rx_pll_frac_en_addr, 0, ln) # NRZ-10G mode, 0x1F0 [13] RX PLL FRAC_EN=0 while programming PLLs + + wreg(c.tx_pll_lvcocap_addr, 85, ln) # NRZ-10G mode, 0x0DB [14:8] TX PLL VCOCAP=84 or 85 for fvco=20.625G + wreg(c.tx_pll_n_addr, 26, ln) # NRZ-10G mode, 0x0FE [15:7] TX_PLL N= 26.4*2*195.3125 + wreg(c.tx_pll_div4_addr, 0, ln) # NRZ-10G mode, 0x0FF [0] TX_PLL DIV4=0 + wreg(c.tx_pll_div2_addr, 0, ln) # NRZ-10G mode, 0x0FF [1] TX PLL DIV2=0 + if chip_rev()==2.0: + wreg([0x0d9,[3,0]], 0x6, ln) # NRZ-10G mode, 0x0D9 [3:0] TX PLL FRAC_N[19:16]=0x6 = 0.4 (R2.0: 20 bits, R1.0: 16 bits) + wreg(c.tx_pll_frac_n_addr, 0x6666, ln) # NRZ-10G mode, 0x0D8 [15:0] TX PLL FRAC_N[15: 0]=0x6666 = 0.4 + else: + wreg([0x0d9,[3,0]], 0x0, ln) # NRZ-10G mode, 0x0D9 [3:0] TX PLL FRAC_N[19:16]=0x0 = 0.4 (R2.0: 20 bits, R1.0: 16 bits) + wreg(c.tx_pll_frac_n_addr, 0x6666, ln) # NRZ-10G mode, 0x0D8 [15:0] TX PLL FRAC_N[15: 0]=0x6666 = 0.4 + + wreg(c.rx_pll_frac_order_addr, 2, ln) # NRZ-10G mode, 0x1F0[15:14] RX PLL FRAC_ORDER =10 + + wreg(c.rx_pll_lvcocap_addr, 85, ln) # NRZ-10G mode, 0x1F5 [15:9] RX PLL VCOCAP=84 or 85 for fvco=20.625G + wreg(c.rx_pll_n_addr, 52, ln) # NRZ-10G mode, 0x1FD [15:7] RX_PLL N= 52.8*1*195.3125 + wreg(c.rx_pll_div4_addr, 0, ln) # NRZ-10G mode, 0x1FF [6] RX_PLL DIV4=0 + wreg(c.rx_pll_div2_addr, 1, ln) # NRZ-10G mode, 0x1F4 [8] RX PLL DIV2=1 + wreg(c.rx_pll_frac_n_addr, 0xCCCC, ln) # NRZ-10G mode, 0x1F1 [15:0] RX PLL FRAC_N=0xCCCC = 0.8 + wreg(c.tx_pll_frac_order_addr, 2, ln) # NRZ-10G mode, 0x0D7[15:14] TX PLL FRAC_ORDER =10 + + wreg(c.rx_pll_pu_addr, 1, ln) # NRZ-10G mode,Power up RX PLL after prgramming PLL and before toggling FRAC_EN + wreg(c.tx_pll_pu_addr, 1, ln) # NRZ-10G mode,Power up TX PLL after prgramming PLL and before toggling FRAC_EN + + #### Enable Fractional PLLs after programming PLLs, # UPDATE 20180521 + wreg(c.tx_pll_frac_en_addr, 1, ln) # NRZ-10G mode, 0x0D7 [13] TX PLL FRAC_EN=1 after programming PLLs + wreg(c.rx_pll_frac_en_addr, 1, ln) # NRZ-10G mode, 0x1F0 [13] RX PLL FRAC_EN=1 after programming PLLs + + wreg(c.tx_mode10g_en_addr, 1, ln) # NRZ-10G mode, TX_NRZ_10G_EN=1 (or Enable NRZ Half-Rate Mode) + wreg(c.rx_mode10g_addr, 1, ln) # NRZ-10G mode, RX_NRZ_10G_EN=1 (or Enable NRZ Half-Rate Mode) + + wreg(c.rx_delta_adapt_en_addr, 0, ln) # NRZ-10G mode, Disable Delta Adaptation loop(0x0101=0x0201) + wreg(0x0165,0x0001, ln) # NRZ-10G Mode, INTP Half Rate mode [0] = 1 + wreg(0x0175,0xC6AF, ln) # NRZ-10G Mode, Margin Counter Phases 4321 en [7:4]=1010 + wreg(0x0100,0x4010, ln) # NRZ-10G mode, F1F2_INIT_0, 0x5185 + wreg(0x0107,0x4013, ln) # NRZ-10G mode, F1F2_INIT_1, 0x5185 + wreg(0x0183,0x4013, ln) # NRZ-10G mode, F1F2_INIT_2, 0x5185 + wreg(0x0184,0x8007, ln) # NRZ-10G mode, F1F2_INIT_3, 0x9185 + wreg(0x0185,0x4013, ln) # NRZ-10G mode, F1F2_INIT_4, 0x5185 + wreg(0x0186,0xC014, ln) # NRZ-10G mode, F1F2_INIT_5, 0xD185 + wreg(0x0187,0xC012, ln) # NRZ-10G mode, F1F2_INIT_6, 0x5185 + wreg(0x0188,0x4006, ln) # NRZ-10G mode, F1F2_INIT_7, 0x5185 + + elif datarate < 24.0: # NRZ 20.6250G, , NRZ Full-Rate Mode + #### disable Fractional PLLs while programming PLLs,# UPDATE 20180521 + wreg(c.tx_pll_frac_en_addr, 0, ln) # NRZ-20G mode, 0x0D7 [13] TX PLL FRAC_EN=0 while programming PLLs + wreg(c.rx_pll_frac_en_addr, 0, ln) # NRZ-20G mode, 0x1F0 [13] RX PLL FRAC_EN=0 while programming PLLs + + wreg(c.tx_pll_lvcocap_addr, 85, ln) # NRZ-20G mode, 0x0DB [14:8] TX PLL VCOCAP=84 or 85 for fvco=20.625G + wreg(c.tx_pll_n_addr, 26, ln) # NRZ-20G mode, 0x0FE [15:7] TX_PLL N= 26.4*2*195.3125 + wreg(c.tx_pll_div4_addr, 0, ln) # NRZ-20G mode, 0x0FF [0] TX_PLL DIV4=0 + wreg(c.tx_pll_div2_addr, 0, ln) # NRZ-20G mode, 0x0FF [1] TX PLL DIV2=0 + if chip_rev()==2.0: + wreg([0x0d9,[3,0]], 0x6, ln) # NRZ-10G mode, 0x0D9 [3:0] TX PLL FRAC_N[19:16]=0x6 = 0.4 (R2.0: 20 bits, R1.0: 16 bits) + wreg(c.tx_pll_frac_n_addr, 0x6666, ln) # NRZ-10G mode, 0x0D8 [15:0] TX PLL FRAC_N[15: 0]=0x6666 = 0.4 + else: + wreg([0x0d9,[3,0]], 0x0, ln) # NRZ-10G mode, 0x0D9 [3:0] TX PLL FRAC_N[19:16]=0x0 = 0.4 (R2.0: 20 bits, R1.0: 16 bits) + wreg(c.tx_pll_frac_n_addr, 0x6666, ln) # NRZ-10G mode, 0x0D8 [15:0] TX PLL FRAC_N[15: 0]=0x6666 = 0.4 + wreg(c.tx_pll_frac_order_addr, 2, ln) # NRZ-20G mode, 0x0D7[15:14] TX PLL FRAC_ORDER =10 + + wreg(c.rx_pll_lvcocap_addr, 85, ln) # NRZ-20G mode, 0x1F5 [15:9] RX PLL VCOCAP=84 or 85 for fvco=20.625G + wreg(c.rx_pll_n_addr, 52, ln) # NRZ-20G mode, 0x1FD [15:7] RX_PLL N= 52.8*1*195.3125 + wreg(c.rx_pll_div4_addr, 0, ln) # NRZ-20G mode, 0x1FF [6] RX_PLL DIV4=0 + wreg(c.rx_pll_div2_addr, 1, ln) # NRZ-20G mode, 0x1F4 [8] RX PLL DIV2=1 + wreg(c.rx_pll_frac_n_addr, 0xCCCC, ln) # NRZ-20G mode, 0x1F1 [15:0] RX PLL FRAC_N=0xCCCC = 0.8 + wreg(c.rx_pll_frac_order_addr, 2, ln) # NRZ-20G mode, 0x1F0[15:14] RX PLL FRAC_ORDER =10 + + wreg(c.rx_pll_pu_addr, 1, ln) # NRZ-20G mode,Power up RX PLL after prgramming PLL and before toggling FRAC_EN + wreg(c.tx_pll_pu_addr, 1, ln) # NRZ-20G mode,Power up TX PLL after prgramming PLL and before toggling FRAC_EN + + #### Enable Fractional PLLs after programming PLLs,# UPDATE 20180521 + wreg(c.tx_pll_frac_en_addr, 1, ln) # NRZ-20G mode, 0x0D7 [13] TX PLL FRAC_EN=1 after programming PLLs + wreg(c.rx_pll_frac_en_addr, 1, ln) # NRZ-20G mode, 0x1F0 [13] RX PLL FRAC_EN=1 after programming PLLs + + wreg(c.tx_mode10g_en_addr, 0, ln) # NRZ-20G mode, TX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + wreg(c.rx_mode10g_addr, 0, ln) # NRZ-20G mode, RX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + wreg(0x165,0x0000,ln) # NRZ-FullRate Mode, INTP Half Rate mode [0] = 0 + wreg(0x175,0xC6FF,ln) # NRZ-FullRate Mode, Margin Counter Phases 4321 en [7:4]=1111 + wreg(0x100,0x4900,ln) # NRZ-FullRate mode, F1F2_INIT_0, 0x5185 + wreg(0x107,0x44FB,ln) # NRZ-FullRate mode, F1F2_INIT_1, 0x5185 + wreg(0x183,0x4B08,ln) # NRZ-FullRate mode, F1F2_INIT_2, 0x5185 + wreg(0x184,0x82FA,ln) # NRZ-FullRate mode, F1F2_INIT_3, 0x9185 + wreg(0x185,0x4B82,ln) # NRZ-FullRate mode, F1F2_INIT_4, 0x5185 + wreg(0x186,0xCB88,ln) # NRZ-FullRate mode, F1F2_INIT_5, 0xD185 + wreg(0x187,0xC97A,ln) # NRZ-FullRate mode, F1F2_INIT_6, 0x5185 + wreg(0x188,0x417a,ln) # NRZ-FullRate mode, F1F2_INIT_7, 0x5185 + + else: # NRZ 25.78125G, , NRZ Full-Rate Mode + #### disable Fractional PLLs while programming PLLs,# UPDATE 20180521 + wreg(c.tx_pll_frac_en_addr, 0, ln) # NRZ-25G mode, 0x0D7 [13] TX PLL FRAC_EN=0 while programming PLLs + wreg(c.rx_pll_frac_en_addr, 0, ln) # NRZ-25G mode, 0x1F0 [13] RX PLL FRAC_EN=0 while programming PLLs + + wreg(c.tx_pll_lvcocap_addr, 34, ln) # NRZ-25G mode, 0x0DB [14:8] TX PLL VCOCAP=33 or 34 for fvco=25.78125G + wreg(c.tx_pll_n_addr, 33, ln) # NRZ-25G mode, 0x0FE [15:7] TX_PLL N= 33*2*195.3125 + wreg(c.tx_pll_div4_addr, 0, ln) # NRZ-25G mode, 0x0FF [0] TX_PLL DIV4=0 + wreg(c.tx_pll_div2_addr, 0, ln) # NRZ-25G mode, 0x0FF [1] TX PLL DIV2=0 + wreg([0x0d9,[3,0]], 0, ln) # NRZ-25G mode, 0x0D9 [3:0] TX PLL FRAC_N[19:16]=0 (R2.0: 20 bits, R1.0: 16 bits) + wreg(c.tx_pll_frac_n_addr, 0, ln) # NRZ-25G mode, 0x0D8 [15:0] TX PLL FRAC_N=0 + wreg(c.tx_pll_frac_order_addr, 0, ln) # NRZ-25G mode, 0x0D7[15:14] TX PLL FRAC_ORDER =0 + + wreg(c.rx_pll_lvcocap_addr, 34, ln) # NRZ-25G mode, 0x1F5 [15:9] RX PLL VCOCAP=33 or 34 for fvco=25.78125G + wreg(c.rx_pll_n_addr, 66, ln) # NRZ-25G mode, 0x1FD [15:7] RX_PLL N= 66*1*195.3125 + wreg(c.rx_pll_div4_addr, 0, ln) # NRZ-25G mode, 0x1FF [6] RX_PLL DIV4=0 + wreg(c.rx_pll_div2_addr, 1, ln) # NRZ-25G mode, 0x1F4 [8] RX PLL DIV2=0 + wreg(c.rx_pll_frac_n_addr, 0, ln) # NRZ-25G mode, 0x1F1 [15:0] RX PLL FRAC_N=0 + wreg(c.rx_pll_frac_order_addr, 0, ln) # NRZ-25G mode, 0x1F0[15:14] RX PLL FRAC_ORDER =0 + + wreg(c.rx_pll_pu_addr, 1, ln) # NRZ-25G mode,Power up RX PLL after prgramming PLL and before toggling FRAC_EN + wreg(c.tx_pll_pu_addr, 1, ln) # NRZ-25G mode,Power up TX PLL after prgramming PLL and before toggling FRAC_EN + + #### Enable Fractional PLLs after programming PLLs, if needed # UPDATE 20180521 + wreg(c.tx_pll_frac_en_addr, 0, ln) # NRZ-25G mode, 0x0D7 [13] TX PLL FRAC_EN=0 kept off for 25G + wreg(c.rx_pll_frac_en_addr, 0, ln) # NRZ-25G mode, 0x1F0 [13] RX PLL FRAC_EN=0 kept off for 25G + + wreg(c.tx_mode10g_en_addr, 0, ln) # NRZ-25G mode, TX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + wreg(c.rx_mode10g_addr, 0, ln) # NRZ-25G mode, RX_NRZ_10G_EN=0 (or Disable NRZ Half-Rate Mode) + wreg(0x165,0x0000,ln) # NRZ-FullRate Mode, INTP Half Rate mode [0] = 0 + wreg(0x175,0xC6FF,ln) # NRZ-FullRate Mode, Margin Counter Phases 4321 en [7:4]=1111 + wreg(0x100,0x4900,ln) # NRZ-FullRate mode, F1F2_INIT_0, 0x5185 + wreg(0x107,0x44FB,ln) # NRZ-FullRate mode, F1F2_INIT_1, 0x5185 + wreg(0x183,0x4B08,ln) # NRZ-FullRate mode, F1F2_INIT_2, 0x5185 + wreg(0x184,0x82FA,ln) # NRZ-FullRate mode, F1F2_INIT_3, 0x9185 + wreg(0x185,0x4B82,ln) # NRZ-FullRate mode, F1F2_INIT_4, 0x5185 + wreg(0x186,0xCB88,ln) # NRZ-FullRate mode, F1F2_INIT_5, 0xD185 + wreg(0x187,0xC97A,ln) # NRZ-FullRate mode, F1F2_INIT_6, 0x5185 + wreg(0x188,0x417a,ln) # NRZ-FullRate mode, F1F2_INIT_7, 0x5185 + ''' + wreg(0x165,0x0000,ln) # NRZ-FullRate Mode, INTP Half Rate mode [0] = 0 + wreg(0x175,0xC6FF,ln) # NRZ-FullRate Mode, Margin Counter Phases 4321 en [7:4]=1111 + wreg(0x100,0x4900,ln) # NRZ-FullRate mode, F1F2_INIT_0, 0x5185 + wreg(0x107,0x44FB,ln) # NRZ-FullRate mode, F1F2_INIT_1, 0x5185 + wreg(0x183,0x4B08,ln) # NRZ-FullRate mode, F1F2_INIT_2, 0x5185 + wreg(0x184,0x82FA,ln) # NRZ-FullRate mode, F1F2_INIT_3, 0x9185 + wreg(0x185,0x4B82,ln) # NRZ-FullRate mode, F1F2_INIT_4, 0x5185 + wreg(0x186,0xCB88,ln) # NRZ-FullRate mode, F1F2_INIT_5, 0xD185 + wreg(0x187,0xC97A,ln) # NRZ-FullRate mode, F1F2_INIT_6, 0x5185 + wreg(0x188,0x417a,ln) # NRZ-FullRate mode, F1F2_INIT_7, 0x5185 + ''' + + if ln%2: # ODD lanes + set_bandgap(bg_val=7,lane=ln) + else: # Even lanes + set_bandgap(bg_val=2,lane=ln) + + ####################### NRZ mode, ln Reset + if (input_mode=='dc'): + wreg(c.rx_vcomrefsel_ex_addr,1,ln) # DC-Coupled mode 0x1DD[9]=1 + wreg(c.rx_en_vcominbuf_addr ,1,ln) # DC-Coupled mode 0x1E7[11]=1 + else: + wreg(c.rx_vcomrefsel_ex_addr,0,ln) # AC-Coupled mode 0x1DD[9]=0 + wreg(c.rx_en_vcominbuf_addr ,1,ln) # AC-Coupled mode 0x1E7[11]=1 + + # ---------------- LANE Q NRZ init end + + # Set the polarities of the lanes + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + + #print("\ninit_lane_nrz(): Lane %s, Target DataRate=%3.5fG, Actual DataRate=%3.5f G"%(lane_name_list[ln],datarate,get_lane_pll(ln)[ln][0][0])), + + get_lane_mode(lanes) # update the Encoding modes of all lanes for this Slice + #for ln in lanes: + # print("\n init_lane_nrz(): Lane %s, Target DataRate=%3.5fG, Actual DataRate=%3.5f G"%(lane_name_list[ln],datarate,get_lane_pll(ln)[ln][0][0])), + + if not fw_loaded(print_en=0): + for ln in lanes: + lr(lane=ln) + + + #rx_monitor_clear(ln) +#################################################################################################### +# +# Initialize the target lane, or list of lanes, to PAM4 mode +#################################################################################################### +def init_lane_pam4(datarate=None,input_mode='ac',lane=None): + + lanes = get_lane_list(lane) + global gEncodingMode + c=Pam4Reg + ### First put the target lanes' State Machine in reset mode while programming lane registers and PLLs + for ln in lanes: + wreg(c.rx_lane_rst_addr, 1, ln) # Keep lane in Reset while programming lane + wreg(c.rx_pll_pu_addr, 0, ln) # Power down RX PLL while prgramming PLL + wreg(c.tx_pll_pu_addr, 0, ln) # Power down RX PLL while prgramming PLL + + for ln in lanes: + gEncodingMode[gSlice][ln] = ['pam4',53.125] + lane_mode_list[ln] = 'pam4' + ####disable AN/LT registers as default + wreg(0x3000+(0x100*ln),0x0000,lane=0) + wreg(0xe000+(0x100*ln),0xc000,lane=0) + # ---------------- LANE Q PAM4 init begin + ####################### Per-Lane PLLs ### + wreg(0x1F0,0x0000,ln) # PAM4 mode, RX_PLL, Fractional PLL off + wreg(0x1F1,0x0000,ln) # PAM4 mode, RX_PLL, Fractional PLL off + wreg(0x0D7,0x0000,ln) # PAM4 mode, TX_PLL, Fractional PLL off + wreg(0x0D8,0x0000,ln) # PAM4 mode, TX_PLL, Fractional PLL off + + #wreg(0x0FF,0x5df6,ln) # PAM4 mode, TX_BG bandgap | div4=0 + #wreg(0x0FE,0x223e,ln) # PAM4 mode, TX PLLN = 68*195.3125*4*2 | [3:1] //vcoi=0x7 + wreg(0x0FF,0x5df4,ln) # PAM4 mode, TX_BG bandgap | div4=0 + wreg(0x0FE,0x113e,ln) # PAM4 mode, TX PLLN = 34*195.3125*4 | [3:1] //vcoi=0x7 + #wreg(0x0FD,0x5636,ln) # PAM4 mode, TX PLL, bypass_pll=0 + #wreg(0x0FD,0x5436,ln) # PAM4 mode, TX PLL, bypass_pll=0, clear bypass 1p7 regulator 0xFD[9] + wreg(0x0FC,0x7236,ln) # PAM4 mode, TX PLL, vvco_reg + wreg(0x0FB,0x7fb6,ln) # PAM4 mode, TX PLL, vref_intp + wreg(0x0FA,0x8010,ln) # PAM4 mode, TX PLL, testmode_tx_pll + wreg(0x0DB,0x1e00,ln) # PAM4 mode, TX PLL, [14:8] // tx_vcocap=rx_vcocap=29 or 30 for fvco=26.5625G + wreg(0x0DA,0x7de6,ln) # PAM4 mode, TX PLL, [14:10]// bm_vco=0x1f + wreg(0x0D9,0xb760,ln) + + wreg(0x1FF,0x5db1,ln) # PAM4 mode, RX_BG bandgap | [15:13]//vbg=0 + #wreg(0x1FC,0x1048,ln) # PAM4 mode, RX PLL, clear bypass 1p7 regulator 0x1FC[9] + #wreg(0x1FD,0x213e,ln) # PAM4 mode, RX_PLLN= 33*2*195.3125 | [3:1] //vcoi=0x7 + wreg(0x1F5,0x3d40,ln) # PAM4 mode, RX PLL, lcvco_cap [15:9] //tx_vcocap=rx_vcocap=29 or 30 for fvco=26.5625G + wreg(0x1FD,0x223e,ln) # PAM4 mode, RX_PLLN= 34*195.3125*4*2 [3:1] //vcoi=0x7 + #wreg(0x1F5,0x3c40,ln) # PAM4 mode, RX PLL, lcvco_cap [15:9] //tx_vcocap=rx_vcocap=29 or 30 for fvco=26.5625G + #wreg(0x1FD,0x113e,ln) # PAM4 mode, RX_PLLN= 34*195.3125*4*2 [3:1] //vcoi=0x7 + wreg(0x1F4,0x7de6,ln) # PAM4 mode, RX PLL, en_div2=0 | [14:10]//bm_vco=0x1f + wreg(0x1F3,0xb760,ln) # PAM4 mode, RX PLL, pu_intp_rx + + + #### From Xiaofan 20171204 + wreg(0x0FD,0x1436,ln) # PAM4 mode, bypass_pll=1, bypass1p7reg=0 + wreg(0x0FB,0x6fb6,ln) # PAM4 mode, vref_intp, vref1p3vcodiv=3 + wreg(0x1FC,0x1448,ln) # PAM4 mode, bypass_pll=1, bypass1p7reg=0 + + if ln%2: # ODD lanes + set_bandgap(bg_val=7,lane=ln) + else: # Even lanes + set_bandgap(bg_val=2,lane=ln) + + ####################### analog ### + wreg(0x0f1,0x0007,ln) # PAM4 mode, pu_adc|pu_clkcomp|pu_clkreg + wreg(0x0ef,0x9230,ln) # PAM4 mode, vrefadc + wreg(0x0ee,0x691c,ln) # PAM4 mode, calnbs_top|bot + wreg(0x0ed,0x8888,ln) # PAM4 mode, edge + wreg(0x0eb,0x67fc,ln) # PAM4 mode, TX Swing + + wreg(0x1f9,0x7e86,ln) # PAM4 mode, vrefagcdegen (was 0x7686) + wreg(0x1f6,0x71b0,ln) # PAM4 mode, vagcbufdac + wreg(0x1e7,0xc34c,ln) # PAM4 mode, pu_agc|pu_agcdl | en_vcominbuf=0 + + + wreg(0x1e6,0x88a5,ln) # PAM4 mode, bypass_agcreg + wreg(0x1e5,0x6c38,ln) # PAM4 mode, 4e3c # PAM4 mode, vrefagc1p5reg + + wreg(0x1da,0x6f00,ln) # PAM4 mode, 6d80 # clkphase0 + + wreg(0x1d4,0x01c0,ln) # PAM4 mode, agcgain1 | agacgain2 + wreg(0x1d5,0x0100,ln) # PAM4 mode, blwc_en + wreg(0x1d6,0xcc00,ln) # PAM4 mode, en_az_short_pulse #rajan + + ####################### PAM4 Mode Configuration + wreg(0x041,0x83df,ln) # PAM4 mode, up/dn mode OFF | pam4_en=1 + wreg(0x0b0,0x4000,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, (4000) + wreg(0x0b0,0x4802,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, (4000) + wreg(0x0b0,0x4000,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, (4000) + wreg(0x1e7,0xc36c,ln) # PAM4 mode, ffe enabled in pam4 mode (agc_dl=1) + + ####################### PAM4 SM Configuration + wreg(0x000,0x286b,ln) + wreg(0x001,0xc000,ln) # changed from 0x8000 to 0xc000 per Yifei 20171203 + wreg(0x002,0x4000,ln) + wreg(0x003,0x7873,ln) + wreg(0x005,0xbd2a,ln) + wreg(0x006,0x762b,ln) + wreg(0x007,0x3ac2,ln) + wreg(0x008,0xc001,ln) + wreg(0x00a,0xe5b1,ln) + wreg(0x00b,0x3d15,ln) + wreg(0x00c,0x0080,ln) + wreg(0x044,0x1035,ln) + wreg(0x04b,0xe802,ln) + wreg(0x079,0x00a4,ln) #--- Turn On TED Qualifier 4/24/2018 + wreg(0x07b,0x4004,ln) #---- Set BLWC MU=4 4/24/2018 + wreg(0x087,0x0800,ln) + + # Updated rajan - need to verify + wreg(0x005 ,0xbd29, ln) + wreg(0x007 ,0x32bf, ln) + wreg(0x009 ,0x7665, ln) + + ####################### PAM4 Rx optimize parameters + sel_ctle_map(IL='ALL', lane=ln) + ctle(7,ln) + #wreg(0x048,0x2518,ln) # PAM4 mode, ctle_map + #wreg(0x049,0x79eb,ln) # PAM4 mode, ctle_map + #wreg(0x04a,0xbf3f,ln) # PAM4 mode, ctle_map, CTLE7=(7,7) + #wreg(0x021,0x00f0,ln) # PAM4 mode, CTLE=7 + wreg(0x020,0x03c0,ln) # PAM4 mode, timing loop|Kp=7 | Kf Set Kp=7 to compensate TED Qualifier ON 4/24/2018 + + wreg(0x1d5,0x0100,ln) # PAM4 mode, bit8=1, see 0x007[14], baseline_ow en + wreg(0x1e0,0xfc40,ln) # PAM4 mode, ffe_pol | pu_sum + wreg(0x1e1,0x1000,ln) # PAM4 mode, ffe_gain12|ffe_sum4 + wreg(0x1e2,0x1601,ln) # PAM4 mode, ffe_k1 | ffe_sum3 + wreg(0x1e3,0x0101,ln) # PAM4 mode, ffe_k2 | ffe_sum2 + wreg(0x1e4,0x0101,ln) # PAM4 mode, ffe_s2| ffe_sum1 + wreg(0x1df,0x6666,ln) # PAM4 mode, ffe1234_delay + wreg(0x1de,0x77cc,ln) # PAM4 mode, ffe5678_delay + + ####################### Direct Connect (XSR) + wreg(0x1dd,0xc1c2,ln) # PAM4 mode, ffe9_delay | en_skef = 0 | skef_value + wreg(0x1d4,0x0260,ln) # PAM4 mode, 0d00 # PAM4 mode, agcgain1[15:9] (bin=4) / agcgain2 [8:4] (bin=31) + wreg(0x004,0xb029,ln) # PAM4 mode, b029 f1_over_init + wreg(0x012,0x2500,ln) # PAM4 mode, 3f80 Delta + wreg(0x0ed,0x7777,ln) # PAM4 mode, 7777 Edge + + ######################## Super Cal + #wreg(0x004,0xb029,ln) # bit 0 =1 + wreg(0x077,0x4e5c,ln) + wreg(0x078,0xe080,ln) + wreg(0x009,0x8666,ln) + wreg(0x087,0x0e00,ln) # super-cal enable | 0800 disable + + ####################### PAM4 mode, TX setting + if gPam4TxSourceIsCredo: + wreg(0x0a5,0x0200,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, pre2 + wreg(0x0a7,0xf800,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, pre1 + wreg(0x0a9,0x1100,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, main + wreg(0x0ab,0x0000,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, post1 + wreg(0x0ad,0x0000,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, post2 + wreg(0x0af,0xfa08,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, tx_automode| MSB first|gc=en|Pre off|SHmode + + ####################### TX PRBS gen and Rx PRBS checker + if gPrbsEn: + wreg(0x0a0,0xe320,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, PRBS clock en before Patt en + wreg(0x0a0,0xeb20,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, tx pam4 prbs31 + wreg(0x043,0x0cfa,ln) # PAM4 mode, Rx PAM4 prbs31 checker | MSB first + wreg(0x042,0xb3fd,ln) # PAM4 mode, Rx PAM4 gc=en | Pre=dis + else: + wreg(0x0a0,0xe320,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, PRBS clock en before Patt en + wreg(0x0a0,0x8320,lane=gLanePartnerMap[gSlice][ln][1]) # PAM4 mode, TX pam4 FUNCTIONAL MODE + wreg(0x043,0x0ce2,ln) # PAM4 mode, Rx PAM4 FUNCTIONAL MODE | MSB first + wreg(0x042,0xb3fd,ln) # PAM4 mode, Rx PAM4 gc=en | Pre=dis + + ####################### PAM4 mode, ln Reset + wreg(0x087,0x0800,ln) # super-cal disable + + #if datarate!=None: + #set_lane_pll(tgt_pll='both',datarate=datarate, div2=0, lane=ln) + + if chip_rev()==2.0: + wreg([0x07b,[3]], 1, ln) # R2.0 PAM4 BLWC Pol = 1 + wreg([0x17c,[15]], 0, ln) # R2.0 NRZ BLWC en = 0 (disabled) + + # PAM4 50G: PLL = 53.125Gbps + #### disable Fractional PLLs while programming PLLs + wreg(c.tx_pll_frac_en_addr, 0, ln) # PAM4-53G mode, 0x0D7 [13] TX PLL FRAC_EN=0 + wreg(c.rx_pll_frac_en_addr, 0, ln) # PAM4-53G mode, 0x1F0 [13] RX PLL FRAC_EN=0 + + wreg(c.tx_pll_lvcocap_addr, 30, ln) # PAM4-53G mode, 0x0DB [14:8] TX PLL VCOCAP=30 for fvco=26.5625G + wreg(c.tx_pll_n_addr, 34, ln) # PAM4-53G mode, 0x0FE [15:7] TX_PLL N= 34*2*195.3125 + wreg(c.tx_pll_div4_addr, 0, ln) # PAM4-53G mode, 0x0FF [0] TX_PLL DIV4=0 + wreg(c.tx_pll_div2_addr, 0, ln) # PAM4-53G mode, 0x0FF [1] TX PLL DIV2=0 + wreg(c.tx_pll_frac_n_addr, 0, ln) # PAM4-53G mode, 0x0D8 [15:0] TX PLL FRAC_N=0 + wreg(c.tx_pll_frac_order_addr, 0, ln) # PAM4-53G mode, 0x0D7[15:14] TX PLL FRAC_ORDER =10 + + wreg(c.rx_pll_lvcocap_addr, 30, ln) # PAM4-53G mode, 0x1F5 [15:9] RX PLL VCOCAP=30 for fvco=26.5625G + wreg(c.rx_pll_n_addr, 68, ln) # PAM4-53G mode, 0x1FD [15:7] RX_PLL N= 68*1*195.3125 + wreg(c.rx_pll_div4_addr, 0, ln) # PAM4-53G mode, 0x1FF [6] RX_PLL DIV4=0 + wreg(c.rx_pll_div2_addr, 1, ln) # PAM4-53G mode, 0x1F4 [8] RX PLL DIV2=0 + wreg(c.rx_pll_frac_n_addr, 0, ln) # PAM4-53G mode, 0x1F1 [15:0] RX PLL FRAC_N=0 + wreg(c.rx_pll_frac_order_addr, 0, ln) # PAM4-53G mode, 0x1F0[15:14] RX PLL FRAC_ORDER =10 + + wreg(c.rx_pll_pu_addr, 1, ln) # PAM4-53G mode,Power up RX PLL after prgramming PLL and before toggling FRAC_EN + wreg(c.tx_pll_pu_addr, 1, ln) # PAM4-53G mode,Power up TX PLL after prgramming PLL and before toggling FRAC_EN + + #### Enable Fractional PLLs after programming PLLs, if needed + wreg(c.tx_pll_frac_en_addr, 0, ln) # PAM4-53G mode, 0x0D7 [13] TX PLL FRAC_EN=0 kept off for 50G + wreg(c.rx_pll_frac_en_addr, 0, ln) # PAM4-53G mode, 0x1F0 [13] RX PLL FRAC_EN=0 kept off for 50G + + if (input_mode=='dc'): + wreg(c.rx_vcomrefsel_ex_addr,1,ln) # DC-Coupled mode 0x1DD[9]=1 + wreg(c.rx_en_vcominbuf_addr ,1,ln) # DC-Coupled mode 0x1E7[11]=1 + else: + wreg(c.rx_vcomrefsel_ex_addr,0,ln) # AC-Coupled mode 0x1DD[9]=0 + wreg(c.rx_en_vcominbuf_addr ,1,ln) # AC-Coupled mode 0x1E7[11]=1 + + # Set the polarities of the lanes + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + # ---------------- LANE Q PAM4 init end + + get_lane_mode(lanes) # update the Encoding modes of all lanes for this Slice + if not fw_loaded(print_en=0): + for ln in lanes: + lr(lane=ln) +#################################################################################################### +def lane_power(lane=None, slice=[0,1], rx_off=1, tx_off=1, rx_bg_off=1, tx_bg_off=1): + + tx_bg_val=7 + rx_bg_val=7 + + slices = get_slice_list(slice) + lanes = get_lane_list(lane) + get_lane_mode(lanes) + + for slc in slices: + sel_slice(slc) + for ln in lanes: + ### First step: Band Gap Power UP + if rx_bg_off == 0: + wregBits(0x1FF, [12], 1, ln) + if tx_bg_off == 0: + wregBits(0x0FF, [12], 1, ln) + + ### RX Power DOWN + if rx_off == 1: + wregBits(0x181, [11], 1, ln) # NRZ state machine reset + wregBits(0x000, [15], 1, ln) # PAM4 state machine reset + wregBits(0x1FF, [11], 0, ln) + wregBits(0x1FF, [15, 13], 0, ln) # RX Bandgap setting to 0 + wregBits(0x1FF, [7], 0, ln) + wregBits(0x1FF, [5], 0, ln) + wregBits(0x1FE, [15, 14], 0, ln) + wregBits(0x1FD, [0], 0, ln) # RX PLL down + wregBits(0x1FC, [6, 1], 0, ln) + wregBits(0x1F8, [15, 13], 0, ln) + wregBits(0x1F8, [9], 0, ln) + wregBits(0x1F3, [5], 0, ln) + wregBits(0x1E7, [15, 14], 0, ln) + wregBits(0x1E0, [15, 10], 0, ln) # PU FFE DEGEN + wregBits(0x1DD, [1], 0, ln) # PU_INTP + wregBits(0x0F1, [2, 0], 0, ln) # PU_ADC,CLKCOMP,CLKCOMPREG + wregBits(0x091, [8], 0, ln) # XCORR OFF + wregBits(0x1C1, [1,0], 0, ln) # PU_FEC_ANA + wreg(0x980c, 0xffff, lane=0) # disable low freq Bitmux fifo + wreg(0x980d, 0xffff, lane=0) # disable low freq Bitmux fifo + wreg(0x3000+(0x100*ln),0x0000,lane=0) # Disable LT + if ln<4: wreg(0xF002+(0x010*ln ),0x0000,lane=0) # Disable AN lanes 0 to 3 + elif ln<8: wreg(0xF102+(0x010*(ln-4)),0x0000,lane=0) # Disable AN lanes 4 to 7 + + ### RX Power UP + else: + wregBits(0x1FF, [15, 13], rx_bg_val,ln) # RX Bandgap setting to 7 + wregBits(0x1FF, [11], 1, ln) + wregBits(0x1FF, [7], 1, ln) + wregBits(0x1FF, [5], 1, ln) + wregBits(0x1FE, [15], 1, ln) + wregBits(0x1FD, [0], 1, ln) # RX PLL UP + wregBits(0x1FC, [6, 1], 0x24, ln) + wregBits(0x1F8, [15,13], 7, ln) + wregBits(0x1F8, [9], 1, ln) + wregBits(0x1F3, [5], 1, ln) + wregBits(0x1E7, [15], 1, ln) + if gEncodingMode[ln][0].upper() == 'PAM4': + wregBits(0x1FE, [14], 1, ln) # PAM4: FFE MA PU + wregBits(0x1E7, [14], 1, ln) # PAM4: FFE on + wregBits(0x1E0, [15,10],0x3F,ln) # PAM4: PU FFE DEGEN + wregBits(0x091, [8], 1, ln) # XCORR ON + else: + wregBits(0x1FE, [14], 0, ln) # NRZ: FFE MA PU + wregBits(0x1E7,[14], 0, ln) # NRZ: FFE off + wregBits(0x1E0,[15,10],0, ln) # NRZ: PU FFE DEGEN + wregBits(0x091, [8], 0, ln) # XCORR OFF + wregBits(0x1DD, [1], 1, ln) # PU_INTP + wregBits(0x0F1, [2,0], 7, ln) # PU_ADC,CLKCOMP,CLKCOMPREG + wregBits(0x1C1, [1,0], 3, ln) # PU_FEC_ANA + wreg(0x980c,0x0000,lane=0) # enable low freq Bitmux fifo + wreg(0x980d,0x0000,lane=0) # enable low freq Bitmux fifo + + + ### TX Power DOWN + if tx_off == 1: + wregBits(0x0FF, [15, 13], 0, ln) # TX Bandgap 0 + wregBits(0x0FF, [11], 0, ln) # TX RVDD PU + wregBits(0x0FF, [10], 0, ln) # TX RVDDVCO PU + wregBits(0x0FF, [7], 0, ln) # TX RVDDLOOP PU + wregBits(0x0FE, [0], 0, ln) # TX PLL PU + wregBits(0x0FA, [15], 0, ln) # TX PU DRV MA + wregBits(0x0EB, [13], 0, ln) # TX DRV PU + wregBits(0x0EA, [6], 0, ln) # TX HIMODE PU + wregBits(0x0FD, [6, 1], 0, ln) # TX DRV-PLLPMP PU + ### TX Power UP + else: + wregBits(0x0FF, [15, 13], tx_bg_val,ln) # TX Bandgap 7 + wregBits(0x0FF, [11], 1, ln) # TX RVDD PU + wregBits(0x0FF, [10], 1, ln) # TX RVDDVCO PU + wregBits(0x0FF, [7], 1, ln) # TX RVDDLOOP PU + wregBits(0x0FE, [0], 1, ln) # TX PLL UP + wregBits(0x0FA, [15], 1, ln) # TX PU DRV MA + wregBits(0x0EB, [13], 1, ln) # TX DRV UP + wregBits(0x0EA, [6], 0, ln) # TX HIMODE PU + wregBits(0x0FD, [6,1], 0x1B, ln) # TX DRV-PLLPMP PU + + ### Last step: Band Gap Power DOWN + if rx_bg_off == 1: + wregBits(0x1FF, [12], 0, ln) + if tx_bg_off == 1: + wregBits(0x0FF, [12], 0, ln) +#################################################################################################### +def analog_low_power(): + PRNT_EN=0 + regg(0xfe,0x1167,lane=0,print_en=PRNT_EN) # PAM4 TX PLL LVCOI = 7 -> 3 + regg(0xfe,0x1167,lane=1,print_en=PRNT_EN) + regg(0xfe,0x1167,lane=2,print_en=PRNT_EN) + regg(0xfe,0x1167,lane=3,print_en=PRNT_EN) + regg(0xfe,0x10b7,lane=8,print_en=PRNT_EN) + regg(0xfe,0x10b7,lane=9,print_en=PRNT_EN) + regg(0xfe,0x10b7,lane=10,print_en=PRNT_EN) # NRZ TX PLL LVCOI = 7 -> 3 + regg(0xfe,0x10b7,lane=11,print_en=PRNT_EN) + regg(0xfe,0x10b7,lane=12,print_en=PRNT_EN) + regg(0xfe,0x10b7,lane=13,print_en=PRNT_EN) + regg(0xfe,0x10b7,lane=14,print_en=PRNT_EN) + regg(0xfe,0x10b7,lane=15,print_en=PRNT_EN) + regg(0x0da,0x3de6,print_en=PRNT_EN) # PAM4/NRZ TX PLL BM_VCOI = 7 -> 3 + regg(0x1f6,0x70b0,print_en=PRNT_EN) # RX analog bufdac, acomp, was 0xd1b0 + regg(0x0eb,0x6248,print_en=PRNT_EN) # TX vdrv reg1/2/3 = 7/7/7 -> 2/2/2 was 0x67fc + for slc in range(2): + sel_slice(slc) + for ln in range(16): + wreg([0x043, [6,0]],0,ln) # Power Down PAM4 RX PRBS Checker + wreg([0x161, [10]],0,ln) # Power Down NRZ RX PRBS Checker + wreg([0x0A0,[15,8]],0,ln) # Power Down PAM4 TX PRBS Generator + wreg([0x0B0,[15,2]],0,ln) # Power Down NRZ TX PRBS Generator + sel_slice(0) +#################################################################################################### +def gearbox_power_save_mode(unused_lanes=[4,5,6,7]): + PRNT_EN=0 + print("\n...Applied Gearbox Power Saving Features!") + ################################ disable bandgap of unused lanes + regg(0x0ff,0x0df4,lane=unused_lanes,print_en=PRNT_EN); + regg(0x1ff,0x0db1,lane=unused_lanes,print_en=PRNT_EN) + + ################################# shut down analog setting of unused lanes + regg(0x1ff ,0x4111,lane=unused_lanes,print_en=PRNT_EN) + regg(0x1fe ,0x0000,lane=unused_lanes,print_en=PRNT_EN) + regg(0x1fd ,0x223e,lane=unused_lanes,print_en=PRNT_EN) + regg(0x1f8 ,0x0000,lane=unused_lanes,print_en=PRNT_EN) + regg(0x1f3 ,0xb740,lane=unused_lanes,print_en=PRNT_EN) + regg(0x1e7 ,0x036c,lane=unused_lanes,print_en=PRNT_EN) + regg(0x1dd ,0x6160,lane=unused_lanes,print_en=PRNT_EN) + regg(0x0ff ,0x4166,lane=unused_lanes,print_en=PRNT_EN) + regg(0x0fe ,0x223e,lane=unused_lanes,print_en=PRNT_EN) + regg(0x0f1 ,0x0000,lane=unused_lanes,print_en=PRNT_EN) + regg(0x0eb ,0x436c,lane=unused_lanes,print_en=PRNT_EN) + + ########### disable xcorr-gate + regg(0x91,lane=range(8,16)+unused_lanes,print_en=PRNT_EN) + + ############## disable BLWC + regg(0x07b,0,print_en=PRNT_EN) + regg(0x17c,0,print_en=PRNT_EN) + + ############## disable fec analyzer + regg(0x1c1,0,print_en=PRNT_EN) + + ####################### disable linktraining module + regg(0x3400,0,print_en=PRNT_EN) + regg(0x3500,0,print_en=PRNT_EN) + regg(0x3600,0,print_en=PRNT_EN) + regg(0x3700,0,print_en=PRNT_EN) + + ########################## AN bypass + regg(0xf002,0x8000,print_en=PRNT_EN) + regg(0xf012,0x8000,print_en=PRNT_EN) + regg(0xf022,0x8000,print_en=PRNT_EN) + regg(0xf032,0x8000,print_en=PRNT_EN) + + regg(0xf102,0x8000,print_en=PRNT_EN) + regg(0xf112,0x8000,print_en=PRNT_EN) + regg(0xf122,0x8000,print_en=PRNT_EN) + regg(0xf132,0x8000,print_en=PRNT_EN) + + ########################## disable low freq fifo + regg(0x980c,0xffff,print_en=PRNT_EN) + regg(0x980d,0xffff,print_en=PRNT_EN) + + analog_low_power() + +#################################################################################################### +def gearbox_power_save_mode_new(unused_lanes=[2,3,6,7]): + for slc in range(2): + sel_slice(slc) + ################################ disable bandgap of unused lanes + #reg(0xff,0x0df4,lane=unused_lanes);reg(0x1ff,0x0db1,lane=unused_lanes) + lane_power(lane=unused_lanes, slice=[0,1], rx_off=1, tx_off=1, rx_bg_off=1, tx_bg_off=1) + + ################################# shut down analog setting of unused lanes + wreg(0x1ff ,0x4111,lane=unused_lanes) + wreg(0x1fe ,0x0000,lane=unused_lanes) + wreg(0x1fd ,0x223e,lane=unused_lanes) + wreg(0x1f8 ,0x0000,lane=unused_lanes) + wreg(0x1f3 ,0xb740,lane=unused_lanes) + wreg(0x1e7 ,0x036c,lane=unused_lanes) + wreg(0x1dd ,0x6160,lane=unused_lanes) + wreg(0x0ff ,0x4166,lane=unused_lanes) + wreg(0x0fe ,0x223e,lane=unused_lanes) + wreg(0x0f1 ,0x0000,lane=unused_lanes) + wreg(0x0eb ,0x436c,lane=unused_lanes) + + ########### disable xcorr-gate + wreg(0x91,0,lane=range(8,16)+unused_lanes) + + ############## disable BLWC + wreg(0x07b,0,lane=range(8,16)+unused_lanes); + wreg(0x17c,0,lane=range(8,16)+unused_lanes) + + ############## disable fec analyzer + wreg(0x1c1,0,lane='all') + + ####################### disable linktraining module + wreg(0x3400,0,lane='all') + wreg(0x3500,0,lane='all') + wreg(0x3600,0,lane='all') + wreg(0x3700,0,lane='all') + + ########################## AN bypass + wreg(0xf002,0x8000,lane='all') + wreg(0xf012,0x8000,lane='all') + wreg(0xf022,0x8000,lane='all') + wreg(0xf032,0x8000,lane='all') + + wreg(0xf102,0x8000,lane='all') + wreg(0xf112,0x8000,lane='all') + wreg(0xf122,0x8000,lane='all') + wreg(0xf132,0x8000,lane='all') + + ########################## disable low freq fifo + wreg(0x980c,0xffff,lane='all') + wreg(0x980d,0xffff,lane='all') +#################################################################################################### +#################################################################################################### +# Initialize lane to NRZ mode and then adapt RX +# +# +# +#################################################################################################### +def opt_lane_nrz(datarate=None, input_mode='ac',lane=None): + + global gLanePartnerMap # TX Source for RX, one per lane per Slice + global gChanEst; # Channel Estimates, one set per lane per Slice + lanes = get_lane_list(lane) + #get_lane_mode(lanes) # update the Encoding modes of all lanes for this Slice + #c=NrzReg + for ln in lanes: + get_lane_mode(ln) + + if fw_loaded(print_en=0) == 1: + init_lane_for_fw(mode = 'nrz', rx_pol=RxPolarityMap[gSlice][ln],input_mode = input_mode,lane=ln) + print ('init_lane_for_fw_nrz') + else:init_lane_nrz(datarate, input_mode,ln) # NRZ mode + line_encoding_mode = gEncodingMode[gSlice][ln][0] + peer_encoding_mode = gEncodingMode[gSlice][gLanePartnerMap[gSlice][ln][1]][0] + ctle_map(0,1,3, lane=ln) + ctle_map(1,1,5, lane=ln) + ctle_map(2,1,7, lane=ln) + ctle_map(3,2,7, lane=ln) + ctle_map(4,3,7, lane=ln) + ctle_map(5,4,7, lane=ln) + ctle_map(6,5,7, lane=ln) + ctle_map(7,7,7, lane=ln) + + if gNrzTxSourceIsCredo: # Make sure TxPeer Lane is also the same mode and data rate as this lane (NRZ or PAM4) + if line_encoding_mode != peer_encoding_mode : + print ("\nSlice %d Lane %s is in %s mode. Its TX Peer (%s) is in %s Mode"%(gSlice, lane_name_list[ln],line_encoding_mode.upper(), lane_name_list[gLanePartnerMap[gSlice][ln][1]],peer_encoding_mode.upper())) + continue + else: + tx_taps(0,-8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + time.sleep(1) + + of, hf, chan_est = channel_analyzer_nrz(lane=ln) + gChanEst[gSlice][ln]=[chan_est,of,hf] + if chan_est == 0.0: # LANE FAILED Channel Estimation + print ("\nSlice %d Lane %s (NRZ) Channel Analyzer: ChanEst: %6.3f <<< FAILED"%(gSlice, lane_name_list[ln],chan_est)), + else: + print ("\nSlice %d Lane %s (NRZ) Channel Analyzer: ChanEst : %6.3f, OF: %2d, HF: %2d"%(gSlice,lane_name_list[ln],chan_est, of, hf)), + + if chan_est == 0.0: # LANE FAILED + agcgain(1,1,lane=ln) # initial DC Gain + elif chan_est < 1.20: # DIRECT LOOPBACK ############## USE SR TABLE ################# + ctle(7, lane=ln) + agcgain(1,28,lane=ln) # initial DC Gain + #agcgain(1,4,lane=ln) # initial DC Gain + elif chan_est < 1.40: + ctle(6, lane=ln) + agcgain(5,31,lane=ln) + elif chan_est < 1.55: + ctle(5, lane=ln) + agcgain(10,31,lane=ln) + elif chan_est < 1.80: + ctle(4, lane=ln) + agcgain(15,31,lane=ln) + elif chan_est < 2.09: + ctle(3, lane=ln) + agcgain(25,31,lane=ln) + elif chan_est < 2.70: + ctle(2, lane=ln) + agcgain(40,31,lane=ln) + else: + ctle(1, lane=ln) + agcgain(60,31,lane=ln) + + tx_taps_table(chan_est,ln) # select TX Taps based on channel estimate + if chan_est != 0: # Only if Lane passed Channel Estimation, finish the rest of adaptation + lr(lane=ln) # reset lane + #if (sig_det(lane=ln)[ln])==1: # if PHY RDY = 0, save time and skip the rest of adaptation + ctle_search_nrz(lane=ln, t=0.02) + lr(lane=ln) + cntr_tgt_nrz(tgt_val='low', lane=ln) + + serdes_params(lane=ln) + +#################################################################################################### +def opt_lane_pam4(datarate=None,input_mode='ac',lane=None): + + global gLanePartnerMap # TX Source for RX, one per lane per Slice + global gChanEst; # Channel Estimates, one set per lane per Slice + lanes = get_lane_list(lane) + #get_lane_mode(lanes) # update the Encoding modes of all lanes for this Slice + c=Pam4Reg + ########## DEVICE 0 EXTERNAL LOOPBACK LANES + for ln in lanes: + get_lane_mode(ln) + init_lane_pam4(datarate,input_mode,ln) # PAM4 mode, BER ~1e7 + line_encoding_mode = gEncodingMode[gSlice][ln][0] + peer_encoding_mode = gEncodingMode[gSlice][gLanePartnerMap[gSlice][ln][1]][0] + + + if gPam4TxSourceIsCredo: # Make sure TxPeer Lane is also the same mode and data rate as this lane (NRZ or PAM4) + if line_encoding_mode != peer_encoding_mode : + print ("\nSlice %d Lane %s is in %s mode. Its TX Peer (%s) is in %s Mode"%(gSlice, lane_name_list[ln],line_encoding_mode.upper(), lane_name_list[gLanePartnerMap[gSlice][ln][1]],peer_encoding_mode.upper())) + continue + else: # Initialize This lane's TX Partner before getting Channel Estimate + tx_taps(+5,-16,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + time.sleep(.1) + + dc_gain(22,31,8,1, ln) + delta_ph(-1,ln) + f13(3,ln) + lr(ln) + opt_agc1,opt_agc2 = dc_gain_search(lane=ln, target_dac_val = 10) + + of,hf,chan_est= channel_analyzer_pam4(gain1_val = opt_agc1, gain2_val = opt_agc2, lane=ln) + gChanEst[gSlice][ln]=[chan_est,of,hf] + if chan_est == 0.0: # LANE FAILED Channel Estimation + print ("\nSlice %d Lane %s (PAM4) Channel Analyzer: ChanEst FAILED <<<"%(gSlice, lane_name_list[ln])), + else: + print ("\nSlice %d Lane %s (PAM4) Channel Analyzer: ChanEst: %5.3f, OF: %2d, HF: %2d"%(gSlice, lane_name_list[ln],chan_est, of, hf)), + + if chan_est < 1.80: ############## USE SR TABLE ################# + ctle_map(0,7,1, lane=ln) + ctle_map(1,3,4, lane=ln) + ctle_map(2,3,5, lane=ln) + ctle_map(3,6,3, lane=ln) + ctle_map(4,4,6, lane=ln) + ctle_map(5,7,5, lane=ln) + ctle_map(6,6,7, lane=ln) + ctle_map(7,7,7, lane=ln) + + else: ############## USE LR TABLE ################# + ctle_map(0,2,1, lane=ln) # unusual value <--- just for testing + ctle_map(1,3,1, lane=ln) + ctle_map(2,2,2, lane=ln) + ctle_map(3,4,1, lane=ln) + ctle_map(4,5,1, lane=ln) + ctle_map(5,6,1, lane=ln) + ctle_map(6,7,1, lane=ln) + ctle_map(7,3,4, lane=ln) + + if chan_est == 0.0: # LANE FAILED Channel Estimation + agcgain(1,1,lane=ln) # initial DC Gain + elif chan_est <1.25: # DIRECT LOOPBACK ############## USE SR TABLE ################# + ctle(7, lane=ln) + delta_ph(4,ln) + f13(1,ln) + edge(4,4,4,4,ln) + skef(1,3,ln) + dc_gain(1,1,8,8, ln) # initial DC Gain + ffe_taps(0x66,0x11,-0x11,0x11,0x01,0x01,ln) # initial FFE Taps + elif chan_est <1.36: # Artek 0%, SR, less than 10dB (7,5) + ctle(7, lane=ln) + delta_ph(2,ln) + f13(3,ln) + edge(4,4,4,4,ln) + skef(1,4,ln) + dc_gain(1,10,8,8, ln) # initial DC Gain + ffe_taps(0x33,0x11,-0x11,0x12,0x01,0x01,ln) + elif chan_est <1.47: # Artek 0%, SR, less than 10dB (7,5) + ctle(6, lane=ln) + delta_ph(-6,ln) + f13(4,ln) + edge(6,6,6,6,ln) + skef(1,5,ln) + dc_gain(1,10,8,8, ln) # initial DC Gain + ffe_taps(0x44,0x00,0x00,-0x11,0x01,0x01,ln) + elif chan_est <1.55: # Artek 10%, MR - 1.57 (4,6) + ctle(5, lane=ln) + delta_ph(-6,ln) + f13(4,ln) + edge(6,6,6,6,ln) + skef(1,5,ln) + dc_gain(1,25,8,8, ln) # initial DC Gain + ffe_taps(0x77,0x01,0x11,-0x55,0x01,0x01,ln) # initial FFE Taps + elif chan_est <1.59: # Artek 20%, MR, ctle(4,6) + ctle(4, lane=ln) + delta_ph(-6,ln) + f13(4,ln) + edge(6,6,6,6,ln) + skef(1,5,ln) + dc_gain(8,31,8,8, ln) # initial DC Gain + ffe_taps(0x77,0x01,0x11,-0x55,0x01,0x01,ln) # initial FFE Taps + elif chan_est <1.68: # Artek 30%, MR, ctle(3,7) + ctle(3, lane=ln) + delta_ph(-6,ln) + f13(5,ln) + edge(9,9,9,9,ln) + skef(1,6,ln) + #dc_gain(10,31,8,8, ln) + ffe_taps(0x77,0x01,0x11,-0x55,0x01,0x01,ln) # initial FFE Taps + elif chan_est <1.80: # Artek 40%, ctle(3,5) ###### SR TABLE ############# + ctle(2, lane=ln) + delta_ph(-8,ln) + f13(5,ln) + edge(10,10,10,10,ln) + skef(1,6,ln) + #dc_gain(15,31,8,8, ln) + dc_gain(30,31,8,8, ln) + ffe_taps(0x77,0x11,0x11,-0x55,0x01,0x01,ln) # initial FFE Taps + + ################# NEW CTLE TABLE USED ####################### after this condition > 1.80 + elif chan_est <1.95: # Artek 50% ctle(7,2) + ctle(6, lane=ln) + delta_ph(-5,ln) + f13(6,ln) + edge(10,10,10,10,ln) + skef(1,7,ln) + #dc_gain(20,31,8,8, ln) + dc_gain(30,31,8,8, ln) + ffe_taps(0x77,0x11,0x11,-0x55,0x01,0x01,ln) + elif chan_est <2.05: # Artek 60% ctle(3,4) #### NEW TABLE USED ##### + ctle(5, lane=ln) + delta_ph(-5,ln) + f13(6,ln) + edge(11,11,11,11,ln) + skef(1,7,ln) + dc_gain(20,31,8,8, ln) + ffe_taps(0x77,0x01,0x11,-0x55,0x01,0x01,ln) + elif chan_est <2.25: # Artek 70%, (6,2) + ctle(4, lane=ln) + delta_ph(-6,ln) + f13(6,ln) + edge(12,12,12,12,ln) + skef(1,7,ln) + #dc_gain(25,31,8,2, ln) + ffe_taps(0x77,0x01,0x11,-0x55,0x01,0x01,ln) + elif chan_est <2.45: # Artek 80% , (5,2) + ctle(3, lane=ln) + delta_ph(-7,ln) + f13(7,ln) + edge(12,12,12,12,ln) + skef(1,7,ln) + dc_gain(30,31,8,2, ln) + ffe_taps(0x77,0x01,0x11,-0x55,0x01,0x01,ln) + elif chan_est <2.7: # Artek 90%, (4,2) + ctle(2, lane=ln) + delta_ph(-8,ln) + f13(8,ln) + edge(13,13,13,13,ln) + skef(1,7,ln) + #dc_gain(35,31,8,2, ln) + dc_gain(50,31,8,2, ln) + ffe_taps(0x77,0x01,0x11,0x11,0x01,0x01,ln) + elif chan_est <3.25: # Artek 100%, (6,1) + ctle(1, lane=ln) + delta_ph(-14,ln) + f13(9,ln) + edge(13,13,13,13,ln) + skef(1,7,ln) + #dc_gain(40,31,15,1, ln) + dc_gain(70,31,15,1, ln) + ffe_taps(0x11,0x11,0x11,0x11,0x32,0x30,ln) + else: #if chan_est >=3.25: # Artek 100%, (6,1) + #if gPam4TxSourceIsCredo: tx_taps(+3,-12,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + ctle(0, lane=ln) + delta_ph(-14,ln) + f13(9,ln) + edge(13,13,13,13,ln) + skef(1,7,ln) + dc_gain(90,31,15,1, ln) + ffe_taps(0x11,0x55, 0x01,0x11,0x01,0x01,ln) + + print ("\nSlice %d Lane %s (PAM4) CTLE selection in EQ1: %d"%(gSlice, lane_name_list[ln],ctle2(lane=ln))) + tx_taps_table(chan_est,ln) # select TX Taps based on channel estimate + if chan_est != 0.0: # LANE PASSED Channel Estimation + #f13_table(lane=ln) + #dc_gain_search(lane=ln,target_dac_val=10) + lr(ln) + + #if sig_det(lane=ln)[ln]: # if PHY RDY = 0, save time and skip the rest of adaptation + #lane_reset_fast(ln) # reset lanes + time.sleep(1) + + wreg(c.rx_theta_update_mode_addr,0,ln) # Disable updn Mode + delta_search(lane=ln, print_en=0) + #ctle_search(lane=ln, t=0.5) + ctle_fine_search(lane=ln) + if chan_est > 1.6: + ctle_fine_search(lane=ln) + #ctle_search(lane=ln, t=0.5) + dc_gain_search(lane=ln) + lr(ln) + time.sleep(1) + print ("\nSlice %d Lane %s (PAM4) CTLE selection in ctle_search: %d"%(gSlice, lane_name_list[ln],ctle2(lane=ln))) + + wreg(c.rx_theta_update_mode_addr,7,ln) # Enable updn Mode + time.sleep(.1) + delta_search(lane=ln, print_en=0) + f13_table(lane=ln) + lr(ln) + time.sleep(.5) + i=0 + list = [1,1,1,-1,-1,-1] + while i < 5: + if eye_check(lane=ln)[0] != 0: + i+=1 + f13(val=(f13(lane=ln)[0]+list[i]),lane=ln) + lane_reset_fast(ln) + time.sleep(.3) + else: + break + print("\nSlice %d Lane %s final f13 value: %d"%(gSlice, lane_name_list[ln],f13(lane=ln)[0])), + + if chan_est >=1.47: + ffe_search_a1_orig(lane=ln, print_en=0) + + lr(ln) # reset lanes + time.sleep(.5) + background_cal(enable='en', lane=ln) + time.sleep(.5) + + serdes_params(lane=ln) + +#################################################################################################### +def tx_taps_table(chan_est=None,lane=None): + + global gLanePartnerMap # TX Source for RX, one per lane per Slice + global gChanEst; # Channel Estimates, one set per lane per Slice + lanes = get_lane_list(lane) + #get_lane_mode(lanes) # update the Encoding modes of all lanes for this Slice + + for ln in lanes: + get_lane_mode(ln) + ##### Check if this lane is PAM4 or NRZ + line_encoding_mode = gEncodingMode[gSlice][ln][0] + peer_encoding_mode = gEncodingMode[gSlice][gLanePartnerMap[gSlice][ln][1]][0] + + ##### Check if this lane's TX Peer is from Credo TX and both ends' mode (PAM4 or NRZ) match + if (gPam4TxSourceIsCredo==1 or gNrzTxSourceIsCredo==1) and (line_encoding_mode!=peer_encoding_mode) : + print ("\n***tx_taps_chan_est(): Slice %d Lane %s is in %s mode. Its TX Peer (%s) is in %s Mode"%(gSlice, lane_name_list[ln],line_encoding_mode.upper(), lane_name_list[gLanePartnerMap[gSlice][ln][1]],peer_encoding_mode.upper())) + continue + + ##### If user does not pass Chan Estimate, get the chan estimate from most recent Rx Adaptation + if chan_est is None: + if fw_loaded(print_en=0): + dbg_md = 2 if line_encoding_mode=='pam4' else 1 + chanEst =(fw_debug_info(section=dbg_md, index=2,lane=ln)[ln]) / 256.0 + of = fw_debug_info(section=dbg_md, index=4,lane=ln)[ln] + hf = fw_debug_info(section=dbg_md, index=5,lane=ln)[ln] + gChanEst[gSlice][ln]=[chanEst,of,hf] + + #print ("%5.3f,%2d,%2d" %(gChanEst[gSlice][ln][0],gChanEst[gSlice][ln][1],gChanEst[gSlice][ln][2])), + chanEst = gChanEst[gSlice][ln][0] + else: + chanEst=chan_est + + ##### This lane is PAM4. Set the TX if the TX source for this lane is Credo TX + if line_encoding_mode=='pam4' and gPam4TxSourceIsCredo==1: + if chanEst <0.90: tx_taps(+2, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # default or used for channel analyzer + elif chanEst <1.25: tx_taps(+1, -6,16,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # DIRECT LOOPBACK + elif chanEst <1.36: tx_taps(+1, -6,16,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 0%, SR, less than 10dB + elif chanEst <1.47: tx_taps(+2, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 0%, SR, less than 10dB + elif chanEst <1.55: tx_taps(+3,-12,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 10%, MR + elif chanEst <1.59: tx_taps(+3,-12,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 20%, MR + elif chanEst <1.68: tx_taps(+3,-12,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 30%, MR + elif chanEst <1.80: tx_taps(+3,-12,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 40%, + elif chanEst <1.95: tx_taps(+4,-12,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 50% + elif chanEst <2.05: tx_taps(+4,-12,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 60% + elif chanEst <2.25: tx_taps(+4,-15,18,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 70% + elif chanEst <2.45: tx_taps(+4,-15,18,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 80% LR + elif chanEst <2.70: tx_taps(+4,-15,18,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 90% LR + elif chanEst <3.20: tx_taps(+4,-15,18,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # Artek 100% LR + else: tx_taps(+4,-15,18,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # + + ###### This lane is NRZ. Set the TX if the TX source for this lane is Credo TX + elif line_encoding_mode=='nrz' and gNrzTxSourceIsCredo==1: + if chanEst < 0.90: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # default + elif chanEst < 1.20: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + elif chanEst < 1.40: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + elif chanEst < 1.55: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + elif chanEst < 1.80: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + elif chanEst < 2.09: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + elif chanEst < 4.00: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) + else: tx_taps( 0, -8,17,0,0,lane=gLanePartnerMap[gSlice][ln][1]) # default or used for channel analyzer + + tt=tx_taps(lane=gLanePartnerMap[gSlice][ln])[gLanePartnerMap[gSlice][ln][1]] + diff = '-' if ln==gLanePartnerMap[gSlice][ln][1] else '*' + print ("\n (%2d,%3d,%2d,%d,%d) %s-TX %s--> %s-RX (ChanEst: %5.3f) "%(tt[0],tt[1],tt[2],tt[3],tt[4],lane_name_list[gLanePartnerMap[gSlice][ln]], diff, lane_name_list[ln], chanEst)), +#################################################################################################### +def fw_serdes_params(lane=None,slice=None,print_en=1): + + fullstring = "" + + if not fw_loaded(print_en=0): + print ("\n######## FW is Not Loaded ! #########"), + + lanes = get_lane_list(lane) + + if slice is None: # if slice is not defined used gSlice + slice=gSlice + + top_pll_A_cap = rreg([0x9501,[12,6]]) + top_pll_B_cap = rreg([0x9601,[12,6]]) + + pam4_lane_in_this_slice=0 + for ln in lanes: + if fw_loaded(print_en=0): + [lane_mode,lane_speed]=fw_lane_speed(ln)[ln] + gEncodingMode[gSlice][ln][0] = lane_mode + else: # avoid crash if FW not loaded + get_lane_mode(ln) + if gEncodingMode[gSlice][ln][0] == 'pam4': + pam4_lane_in_this_slice=1 + + die_temp = fw_temp_sensor(print_en=0) + die_rev = chip_rev(print_en=0) + + ver_code = fw_ver(print_en=0) + ver_str = "v%02d.%02d.%02d" %(ver_code>>16&0xFF,ver_code>>8&0xFF,ver_code&0xFF) + crc_code = fw_crc(print_en=0) + crc_str = "CRC-0x%04X" %(crc_code) + + #top_line = "\n#+------------------------------------ S E R D E S P A R A M S -------- Rev %s, Slice %d, Temp %5.1fC ----------------------------------------------------------------+"%('A0' if die_rev==1.0 else 'B0',slice,die_temp) + top_line = "\n# SERDES PARAMS --- Rev %s, Slice %d, FW %s %s, Temp %5.1f C "%('A0' if die_rev==1.0 else 'B0',slice,ver_str,crc_str,die_temp) + line_separator= "\n#+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+" + fullstring += top_line + fullstring += line_separator + fullstring += ("\n#| | | FW COUNTERS |SD,Rdy,|FRQ |PLL Cal| CHANNEL | CTLE | | | EYE MARGIN | DFE | TIMING | FFE Taps |") + if pam4_lane_in_this_slice: + fullstring += ("\n#|Lane |Mode| Adp ,ReAdp,LLost|AdpDone|PPM | %d,%d | Est ,OF,HF | Peaking, G1,G2 |SK|DAC| 1 , 2 , 3 | F0 , F1 ,F1/F0,F1+F0,F13|Del,Edge| K1 , K2 , K3 , K4 ,S1,S2,Sf|"%(top_pll_A_cap,top_pll_B_cap)) + else: + fullstring += ("\n#|Lane |Mode| Adp ,ReAdp,LLost|AdpDone|PPM | %d,%d | Est ,OF,HF | Peaking, G1,G2 |SK|DAC| 1 , 2 , 3 | F1, F2, F3 |Del,Edge| K1 , K2 , K3 , K4 ,S1,S2,Sf|"%(top_pll_A_cap,top_pll_B_cap)) + fullstring += line_separator + + for ln in lanes: + c = Pam4Reg if lane_mode_list[ln].lower() == 'pam4' else NrzReg + if fw_loaded(print_en=0): + [lane_mode,lane_speed]=fw_lane_speed(ln)[ln] + gEncodingMode[gSlice][ln][0] = lane_mode + gEncodingMode[gSlice][ln][1] = lane_speed + else: # avoid crash if FW not loaded + get_lane_mode(ln) + lane_mode = gEncodingMode[gSlice][ln][0] + lane_speed= int(gEncodingMode[gSlice][ln][1]) + + if lane_mode.upper()=='OFF': # Lane is OFF + fullstring += ("\n#|S%d_%s| %3s|"%(slice, lane_name_list[ln], lane_speed)) + fullstring += (" | | | | | | | | | | | |") + + else: # Lane is active, in PAM4 or NRZ mode + adapt_cnt = fw_adapt_cnt(ln)[ln] + readapt_cnt = fw_readapt_cnt(ln)[ln] + linklost_cnt = fw_link_lost_cnt(ln)[ln] + sd = sig_det(ln)[ln] + rdy = phy_rdy(ln)[ln] + adapt_done = (rreg(c.fw_opt_done_addr) >> ln) & 1 + sd_flag = '*' if ( sd!=1) else ' ' + rdy_flag = '*' if (rdy!=1 or adapt_done!=1) else ' ' + ppm_val = ppm(ln)[ln] + tx_cap = rreg(c.tx_pll_lvcocap_addr,ln) + rx_cap = rreg(c.rx_pll_lvcocap_addr,ln) + chan_est,of,hf = fw_chan_est(ln)[ln] + gChanEst[gSlice][ln] = [chan_est,of,hf] + ctle_val = ctle(lane=ln)[ln] + ctle_1_bit4=rreg([0x1d7,[3]],ln) + ctle_2_bit4=rreg([0x1d7,[2]],ln) + ctle_1 = ctle_map(ctle_val, lane=ln)[ln][0] + (ctle_1_bit4*8) + ctle_2 = ctle_map(ctle_val, lane=ln)[ln][1] + (ctle_2_bit4*8) + #if (lane_mode.upper()=='PAM4' and chan_est < 1.80): ctle_val+=8 + if lane_mode.upper()=='PAM4' and (ctle_1_bit4==1 or ctle_2_bit4==1 or ctle_map(7)[ln][0]==7): ctle_val+=8 + skef_val = skef(lane=ln)[ln][1] + dac_val = dac(lane=ln)[ln] + + delta_val = delta_ph(lane=ln)[0] + edge1,edge2,edge3,edge4 = edge(lane=ln)[ln] + eyes = eye(lane=ln)[ln] + #pre_ber, post_ber = ber(rst=1,lane=ln, t=0.1)[ln] + + fullstring += ("\n#|S%d_%s| %3s|%5d,%5d,%4d |%s%d,%d,%d%s|%3d | %2d,%2d "%(slice, lane_name_list[ln], lane_speed,adapt_cnt,readapt_cnt,linklost_cnt,sd_flag,sd,rdy,adapt_done,rdy_flag,ppm_val,tx_cap,rx_cap)) + fullstring += ("|%5.2f,%2d,%2d " %(chan_est,of,hf)) + fullstring += ("|%2d(%d,%-2d),%3d,%2d " %(ctle_val,ctle_1,ctle_2,dc_gain(lane=ln)[ln][0],dc_gain(lane=ln)[ln][1])) + fullstring += ("|%d |%2d " %(skef_val,dac_val)) + + if lane_mode.upper()=='PAM4': # Lane is in PAM4 mode + f0,f1,f1f0_ratio = pam4_dfe(lane=ln)[ln] + f13_val = f13(lane=ln)[0] + fullstring += ("|%4.0f,%3.0f,%3.0f "%(eyes[0],eyes[1],eyes[2])) + fullstring += ("|%4.2f,%4.2f,%5.2f,%5.2f,%2d " %(f0,f1,f1f0_ratio,f0+f1,f13_val)) + fullstring += ("|%3d,%X%X%X%X| " %(delta_val,edge1,edge2,edge3,edge4)) + [ffe_k1_bin,ffe_k2_bin,ffe_k3_bin,ffe_k4_bin,ffe_s1_bin,ffe_s2_bin,ffe_sf_bin] = ffe_taps(lane=ln)[ln] + fullstring +=('\b%4d,%4d,%4d,%4d,%02X,%02X,%02X| ' %(ffe_k1_bin,ffe_k2_bin,ffe_k3_bin,ffe_k4_bin,ffe_s1_bin,ffe_s2_bin,ffe_sf_bin)) + else: # Lane is in NRZ mode + # hf_0= fw_debug_cmd(section=1, index=250,lane=ln) + # hf_1= fw_debug_cmd(section=1, index=251,lane=ln) + # hf_2= fw_debug_cmd(section=1, index=252,lane=ln) + + # of_0= fw_debug_cmd(section=1, index=255,lane=ln) + # of_1= fw_debug_cmd(section=1, index=256,lane=ln) + # of_2= fw_debug_cmd(section=1, index=257,lane=ln) + + # adc_cal_done_0= fw_debug_cmd(section=1, index=530,lane=ln) + # adc_cal_done_1= fw_debug_cmd(section=1, index=531,lane=ln) + # adc_cal_done_2= fw_debug_cmd(section=1, index=532,lane=ln) + + # read_B0_q_0= fw_debug_cmd(section=1, index=425, lane=ln) + # read_B0_q_1= fw_debug_cmd(section=1, index=426, lane=ln) + # read_B0_q_2= fw_debug_cmd(section=1, index=427, lane=ln) + + # agc_peaking_0= fw_debug_cmd(section=1, index=420, lane=ln) + # agc_peaking_1= fw_debug_cmd(section=1, index=421, lane=ln) + # agc_peaking_2= fw_debug_cmd(section=1, index=422, lane=ln) + + f1,f2,f3 = nrz_dfe(lane=ln)[ln] + fullstring += ("|%4.0f "%(eyes[0])) + fullstring += ("|%4d,%4d,%4d " %(f1,f2,f3)) + fullstring += ("|%3d,%X%X%X%X| " %(delta_val,edge1,edge2,edge3,edge4)) + fullstring += (" | ") + # print('|%2d %2d %2d %2d %2d %2d |' %(hf_0, hf_1, hf_2, of_0, of_1, of_2) ), + # if(hf_0<10 or hf_1<10 or hf_2<10 or of_0<10 or of_1<10 or of_2<10): + # print('\n<<<<< adc_cal_done = %2d %2d %2d <<<<<')%(adc_cal_done_0, adc_cal_done_1, adc_cal_done_2), + # print('\n<<<<< read_B0_q = %2d %2d %2d <<<<<')%(read_B0_q_0, read_B0_q_1, read_B0_q_2), + # print('\n<<<<< agc peaking = %2d %2d %2d <<<<<\n')%(agc_peaking_0, agc_peaking_1, agc_peaking_2), + # nrz_dump_fw(lane=ln) + + + if (ln len(speed_list)-1: speed_index=0 + #lane_speed = speed_list[speed_index] + lane_mode_speed = mode_list[speed_index] + config_code_this_lane= fw_debug_cmd(section=0, index=38, lane=ln) + lane_config = config_list[config_code_this_lane] if config_code_this_lane<0xC0 else config_list[config_code_this_lane & 0xF0] + lane_optic_mode = lane_optic_mode_list[(fw_reg_rd(20) >> ln) & 1] + + if 'OFF' in lane_mode_speed: lane_config = 'None' # overwrite config to 'None' is lane is 'OFF' + + #### GB or BM's status for all lanes is obtained through fw debug command section 0 index 40 + if 'GearBox' in lane_config or 'BitMux' in lane_config: + lane_rdy = lane_status_list[(fw_debug_cmd(section=0, index=40, lane=ln) >> ln) & 1] + #### PHY Mode's status for all lanes is obtained through register 0x98c9 + else: + lane_rdy = lane_status_list[(rreg(c.fw_opt_done_addr) >> ln) & 1] + + + result[ln] = [lane_config,lane_mode_speed,lane_optic_mode,lane_rdy] + + if print_en: print("\n | S%d_%2s | %s | %s | %s | %s |"%(slice,lane_name_list[ln],lane_config.center(21,' '),lane_mode_speed.center(8,' '),lane_optic_mode.center(8,' '),lane_rdy.center(7,' '))), + + if print_en: print (line_separator) + + if not print_en: return result +#################################################################################################### +# +# Set Lanes in PRBS or Functional Mode +# prbs_mode options: 'functional' : disable prbs, used in loopback, retimer or gearbox modes with no FEC +# 'prbs' : enable prbs generator, leaves the prbs pattern unchanged +# 'prbs31 : enable prbs generator, select prbs pattern PRBS31 +# 'prbs23 : enable prbs generator, select prbs pattern PRBS23 (NRZ only) +# 'prbs15 : enable prbs generator, select prbs pattern PRBS15 +# 'prbs13 : enable prbs generator, select prbs pattern PRBS13 (PAM4 only) +# 'prbs9 : enable prbs generator, select prbs pattern PRBS9 +#################################################################################################### +def prbs_mode_select(lane=None, prbs_mode='prbs'): + + lanes = get_lane_list(lane) + if prbs_mode.upper() == 'PRBS': prbs_mode ='PRBS31' + + #global gPrbsEn; gPrbsEn = prbs_mode + + nrz_prbs_pat = ['PRBS9', 'PRBS15', 'PRBS23', 'PRBS31'] + pam4_prbs_pat = ['PRBS9', 'PRBS13', 'PRBS15', 'PRBS31'] + + # if a specific prbs pattern is requested, program the PRBS type register bits + if 'PRBS' in prbs_mode.upper() : + for ln in lanes: + wreg([0x0a0, [9,8]],pam4_prbs_pat.index(prbs_mode.upper()),ln) # PAM4/NRZ TX PRBS Pattern + if gEncodingMode[gSlice][ln][0]=='pam4': + wreg([0x043, [6,5]],pam4_prbs_pat.index(prbs_mode.upper()),ln) # PAM4 RX PRBS Pattern + else: + wreg([0x161,[13,12]], nrz_prbs_pat.index(prbs_mode.upper()),ln) # NRZ RX PRBS Pattern + + for ln in lanes: + get_lane_mode(ln) + ###### Lane is in PAM4 mode #################### + if gEncodingMode[gSlice][ln][0]=='pam4': + wreg([0x0b0,[14]],0,ln) # PAM4 mode, NRZ PRBS Gen clock dis + wreg([0x0b0,[11]],0,ln) # PAM4 mode, NRZ PRBS dis + wreg([0x0b0, [1]],0,ln) # PAM4 mode, NRZ TX dis + wreg([0x0b0, [0]],0,ln) # PAM4 mode, NRZ 10G dis + + #wreg([0x0a0, [6]],0,ln) # PAM4 mode, TX pol flip = 0, leave polarity as it was + #wreg([0x0a0, [5]],0,ln) # PAM4 mode, TX ana pol flip = 0, leave polarity as it was + + ######## Credo PAM4 TX in Functional Mode, used in loopback, retimer and gearbox modes + if 'PRBS' not in prbs_mode.upper(): + wreg([0x0a0,[15]],0,ln)# PAM4 mode, PRBS Gen de-selected + wreg([0x0a0,[14]],0,ln)# PAM4 mode, PRBS Gen clock dis + wreg([0x0a0,[13]],0,ln)# PAM4 mode, PRBS Gen test data dis + wreg([0x0a0,[11]],0,ln)# PAM4 mode, PRBS Gen dis + + #wreg([0x043, [7]],1,ln)# PAM4 mode, PRBS Checker flip = 1, leave polarity as it was + #wreg([0x043,[6,5]],3,ln)# PAM4 mode, PRBS Checker PRBS pattern, done already, see above + wreg([0x043, [4]],1,ln)# PAM4 mode, PRBS Checker powered up + wreg([0x043, [3]],1,ln)# PAM4 mode, PRBS Sync Checker powered up + wreg([0x043, [1]],1,ln)# PAM4 mode, PRBS Sync Checker auto-sync en + #wreg(0x043,0x0ce2,ln) # PAM4 mode, Rx PAM4 FUNCTIONAL MODE | MSB first + + ######## Credo PAM4 TX and RX in PRBS Mode + else: + wreg([0x0a0,[15]],1,ln) # PAM4 mode, PRBS Gen selected + wreg([0x0a0,[14]],1,ln) # PAM4 mode, PRBS Gen clock en + wreg([0x0a0,[13]],1,ln) # PAM4 mode, PRBS Gen test data en + wreg([0x0a0,[11]],1,ln) # PAM4 mode, PRBS Gen en + + #wreg([0x043, [7]],1,ln)# PAM4 mode, PRBS Checker flip = 1, leave polarity as it was + #wreg([0x043,[6,5]],3,ln)# PAM4 mode, PRBS Checker PRBS pattern, done already, see above + wreg([0x043, [4]],1,ln)# PAM4 mode, PRBS Checker powered up + wreg([0x043, [3]],1,ln)# PAM4 mode, PRBS Sync Checker powered up + wreg([0x043, [1]],1,ln)# PAM4 mode, PRBS Sync Checker auto-sync en + + #wreg(0x043,0x0cfa,ln) # PAM4 mode, Rx PAM4 prbs31 checker | MSB first + + ###### Lane is in NRZ mode ####################### + else: + wreg([0x0b0,[14]],1,ln) # NRZ mode, NRZ PRBS Gen clock en + wreg([0x0b0,[11]],1,ln) # NRZ mode, NRZ PRBS en + wreg([0x0b0, [1]],1,ln) # NRZ mode, NRZ TX en + #wreg([0x0b0, [0]],0,ln) # NRZ mode, NRZ TX 10G leave as it was + + #wreg([0x0a0, [6]],1,ln) # NRZ mode, TX pol flip1 = leave as it was + #wreg([0x0a0, [5]],0,ln) # NRZ mode, TX pol flip2 = leave as it was + + ######## Credo NRZ TX in Functional Mode, used in loopback, retimer and gearbox modes + if 'PRBS' not in prbs_mode.upper(): + wreg([0x0a0, [15]],0,ln)# NRZ mode, PRBS Gen de-selected + wreg([0x0a0, [14]],0,ln)# NRZ mode, PRBS Gen clock dis + wreg([0x0a0, [13]],0,ln)# NRZ mode, PRBS Gen test data dis + wreg([0x0a0, [11]],0,ln)# NRZ mode, PRBS Gen dis + #wreg([0x161, [14]],1,ln)# NRZ mode, PRBS Checker flip = 1, leave as it was + #wreg([0x161,[13,12]],3,ln)# NRZ mode, PRBS Checker PRBS pattern, done already, see above + #wreg([0x161, [10]],0,ln)# NRZ mode, PRBS Checker powered off + + #wreg(0x0a0,0x0120,ln) # NRZ mode, TX functional mode + #wreg(0x161,0x7120,ln) # NRZ mode, PRBS Rx checker off, bit 10 + + ######## Credo NRZ TX and RX in PRBS Mode + else: + wreg([0x0a0, [15]],1,ln)# NRZ mode, PRBS Gen selected + wreg([0x0a0, [14]],1,ln)# NRZ mode, PRBS Gen clock en + wreg([0x0a0, [13]],1,ln)# NRZ mode, PRBS Gen test data en + wreg([0x0a0, [11]],1,ln)# NRZ mode, PRBS Gen en + #wreg([0x161, [14]],1,ln)# NRZ mode, PRBS Checker flip = 1, leave as it was + #wreg([0x161,[13,12]],3,ln)# NRZ mode, PRBS Checker PRBS pattern, done already, see above + wreg([0x161, [10]],1,ln)# NRZ mode, PRBS Checker powered up + #wreg(0x161,0x7520,ln) # NRZ mode, PRBS checker up, bit 10 + +#################################################################################################### +def rx_monitor_clear(lane=None, fec_thresh=gFecThresh,mode=None): + global gLaneStats #[per Slice][per lane], [PrbsCount, PrbsCount-1,PrbsCount-2, PrbsRstTime, PrbsLastReadoutTime] + global gSlice + gSlice=sel_slice() + lanes = get_lane_list(lane) + + for ln in lanes: + get_lane_mode(ln) + c = Pam4Reg if gEncodingMode[gSlice][ln][0].upper() == 'PAM4' else NrzReg + + ###### 1. Initialize FEC Analyzer for this lane + if gEncodingMode[gSlice][ln][0].lower() == 'pam4': + fec_ana_init(lane=ln, delay=.1, err_type=2, T=fec_thresh, M=10, N=5440, print_en=0, mode=mode) + else: # Lane is in NRZ mode + fec_ana_init(lane=ln, delay=.1, err_type=2, T=fec_thresh, M=10, N=5280, print_en=0, mode=mode) + + ###### 2. Clear Rx PRBS Counter for this lane + wreg(c.rx_err_cntr_rst_addr, 0, ln) + time.sleep(0.001) + wreg(c.rx_err_cntr_rst_addr, 1, ln) + time.sleep(0.001) + wreg(c.rx_err_cntr_rst_addr, 0, ln) + + ###### 3. Capture Time Stamp for Clearing FEC and PRBS Counters. Used for Calculating BER + prbs_reset_time = time.time() # get the time-stamp for the counter clearing + + ###### 4. Clear Stats for this lane + # prbs1/2/3 eye123 fec1,2 + gLaneStats[gSlice][ln]=[long(0),long(0),long(0),prbs_reset_time, prbs_reset_time,0,0,0,'CLR',0,0] + #[0,0,0,prbs_reset_time, prbs_reset_time,0,0,0,'RDY',0,0,0,0] + return gLaneStats[gSlice] + +#################################################################################################### +def rx_monitor_capture (lane=None): + global gLaneStats #[per Slice][per lane], [PrbsCount, PrbsCount-1,PrbsCount-2, PrbsRstTime, PrbsLastReadoutTime] + global gSlice + gSlice=sel_slice() + lanes = get_lane_list(lane) + + for ln in lanes: + get_lane_mode(ln) + c = Pam4Reg if gEncodingMode[gSlice][ln][0].lower() == 'pam4' else NrzReg + + ###### 1. Capture FEC Analyzer Data for this lane + tei = fec_ana_tei(lane=ln) + teo = fec_ana_teo(lane=ln) + #sei = fec_ana_sei(lane=ln) + #bei = fec_ana_bei(lane=ln) + + ###### 2. Capture PRBS Counter for this lane + cnt1 = long(rreg(c.rx_err_cntr_msb_addr, ln)<<16) + rreg(c.rx_err_cntr_lsb_addr, ln) + cnt = long(rreg(c.rx_err_cntr_msb_addr, ln)<<16) + rreg(c.rx_err_cntr_lsb_addr, ln) + if cnt> ln) & 1 + cnt_n1 = long(gLaneStats[gSlice][ln][0]) # PrevPrbsCount-1 + cnt_n2 = long(gLaneStats[gSlice][ln][1]) # PrevPrbsCount-2 + if gLaneStats[gSlice][ln][3] != 0: #if the PRBS count was cleared at least once before, use the time of last clear + prbs_reset_time = gLaneStats[gSlice][ln][3] + else: + prbs_reset_time = cnt_time #if the PRBS counter was never cleared before, use the current time as the new 'clear time' + link_status = 'RDY' + if(sd==0 or rdy ==0 or adapt_done==0): # check for PHY_RDY first + tei=0xEEEEEEEE + teo=0xEEEEEEEE + cnt=0xEEEEEEEE # return an artificially large number if RDY=0 + cnt_n1 = long(0) # PrevPrbsCount-1 + cnt_n2 = long(0) # PrevPrbsCount-2 + link_status = 'NOT_RDY' + eyes=[-1,-1,-1] + else: # RDY=1, then consider the PRBS count value + eyes=eye(lane=ln)[ln] + # if(cnt < cnt_n1): # check for PRBS counter wrap-around + # cnt = 0xFFFFFFFEL # return an artificially large number if counter rolls over + # cnt_n1 = long(0) # PrevPrbsCount-1 + # cnt_n2 = long(0) # PrevPrbsCount-2 + + + # if RDY=1 and PRBS count value is considered a valid count + gLaneStats[gSlice][ln]=[cnt,cnt_n1,cnt_n2,prbs_reset_time, cnt_time,eyes[0],eyes[1],eyes[2],link_status,tei,teo] + + return gLaneStats[gSlice] + +#################################################################################################### +def rx_monitor_print (lane=None,slice=None): + global gLaneStats #[per Slice][per lane], [PrbsCount, PrbsCount-1,PrbsCount-2, PrbsRstTime, PrbsLastReadoutTime] + myber=99e-1 + global gSlice + gSlice=sel_slice() + + lanes = get_lane_list(lane) + + #Slice=gSlice + get_lane_mode(lanes) + if slice is None: # if slice is not defined used gSlice + slice=gSlice + + skip=" -" + line="\n------------- " + for ln in lanes: + if ln == 8 : + line+="|------- " + else: + line+="-------- " + print (line) + + print("\n Slice_Lane"), + for ln in lanes: print(" S%d_%s" %(slice,lane_name_list[ln])), + + print("\n Encoding"), + for ln in lanes: print("%8s" %(gEncodingMode[gSlice][ln][0].upper())), + print("\nDataRate Gbps"), + for ln in lanes: print("%8.4f" %(gEncodingMode[gSlice][ln][1])), + + print (line) + print("\n Link Status"), + for ln in lanes: print("%8s" %(gLaneStats[gSlice][ln][8])), + print("\n Eye1 (mV)"), + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + print ("%8.0f"%(gLaneStats[gSlice][ln][5])), + else: + print (skip) + print("\n Eye2 (mV)"), + for ln in lanes: + if(gEncodingMode[gSlice][ln][0].upper()== 'PAM4' and gLaneStats[gSlice][ln][8] == 'RDY'): + print ("%8.0f"%(gLaneStats[gSlice][ln][6])), + else: + print (skip) + print("\n Eye3 (mV)"), + for ln in lanes: + if(gEncodingMode[gSlice][ln][0].upper()== 'PAM4' and gLaneStats[gSlice][ln][8] == 'RDY'): + print ("%8.0f"%(gLaneStats[gSlice][ln][7])), + else: + print (skip) + + print (line) + print("\n Elapsed Time"), + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + elapsed_time=gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + if elapsed_time < 1000.0: + print("%6.1f s" % (elapsed_time) ), + else: + print("%6.0f s" % (elapsed_time) ), + else: + print (skip) + + # print("\nPrev PRBS "), + # for ln in lanes: print("%8X " % (gLaneStats[gSlice][ln][1]) ), + #print("\nCurr PRBS "), + print("\n PRBS Cnt"), + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + print("%8X" % (gLaneStats[gSlice][ln][0]) ), + else: + print (skip) + # print("\nDeltaPRBS "), + # for ln in lanes: print("%8X " % (gLaneStats[gSlice][ln][0] - gLaneStats[gSlice][ln][1]) ), + + print("\n PRBS BER"), + for ln in lanes: + curr_prbs_cnt = float(gLaneStats[gSlice][ln][0]) + prbs_accum_time = gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + data_rate = gEncodingMode[gSlice][ln][1] + bits_transferred = float((prbs_accum_time*data_rate*pow(10,9))) + if curr_prbs_cnt==0 or bits_transferred==0: + ber_val = 0 + print("%8d" % (ber_val) ), + myber= ((ber_val) ) + else: + ber_val= curr_prbs_cnt / bits_transferred + if(gLaneStats[gSlice][ln][8] == 'RDY'): + print("%8.1e" % (ber_val) ), + myber= ((ber_val) ) + else: + print (skip) + + + print (line) + #print "\n User has set the FEC Threshold to less than max" + if (gEncodingMode[gSlice][ln][0].lower() == 'pam4' and gFecThresh<15) or\ + (gEncodingMode[gSlice][ln][0].lower() != 'pam4' and gFecThresh<7): + print("\n FEC Thresh"), + for ln in lanes: + print("%8d" % (gFecThresh) ), + + print("\n pre-FEC Cnt"), + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + print("%8X" % (gLaneStats[gSlice][ln][9]) ), + else: + print (skip) + + print("\n Post-FEC Cnt"), + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + print("%8X" % (gLaneStats[gSlice][ln][10]) ), + else: + print (skip) + print("\n pre-FEC BER"), + for ln in lanes: + curr_prbs_cnt = float(gLaneStats[gSlice][ln][9]) + prbs_accum_time = gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + data_rate = gEncodingMode[gSlice][ln][1] + bits_transferred = float((prbs_accum_time*data_rate*pow(10,9))) + if curr_prbs_cnt==0 or bits_transferred==0: + ber_val = 0 + print("%8d" % (ber_val) ), + else: + ber_val= curr_prbs_cnt / bits_transferred + if(gLaneStats[gSlice][ln][8] == 'RDY'): + print("%8.1e" % (ber_val) ), + else: + + print (skip) + print("\n Post-FEC BER"), + for ln in lanes: + curr_prbs_cnt = float(gLaneStats[gSlice][ln][10]) + prbs_accum_time = gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + data_rate = gEncodingMode[gSlice][ln][1] + bits_transferred = float((prbs_accum_time*data_rate*pow(10,9))) + if curr_prbs_cnt==0 or bits_transferred==0: + ber_val = 0 + print("%8d" % (ber_val) ), + else: + ber_val= curr_prbs_cnt / bits_transferred + if(gLaneStats[gSlice][ln][8] == 'RDY'): + print("%8.1e" % (ber_val) ), + else: + print (skip) + + print (line) + + return myber +def rx_monitor_summary (rst=None, slice='all', lane='all', fec_thresh=gFecThresh): + global gLaneStats # [per tile][per group][per lane], [PrbsCount, PrbsCount-1,PrbsCount-2, PrbsRstTime, PrbsLastReadoutTime] + slices = get_slice_list(slice) + lanes = get_lane_list(lane) + get_lane_mode(lanes) + + if rst != None: + print("\n..%sCollecting BER Statistics Summary"%('.Clearing and ' if rst==1 else '.')) + for slc in slices: + sel_slice(slc) + rx_monitor (rst=rst, slice=slc, lane=lanes, fec_thresh=fec_thresh, print_en=0) + else: + print("\n...BER Statistics Summary") + + elapsed_time=gLaneStats[slices[0]][lanes[0]][4] - gLaneStats[slices[0]][lanes[0]][3] + print("\n...Elapsed Time: %1.1f sec" % (elapsed_time)) + + pre_fec_ber_bins = [1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 0 ] + pre_fec_ber_cnt = [] + pre_fec_ber_sl = [] + pre_fec_ber_ln = [] + post_fec_ber_cnt = [] + post_fec_ber_sl = [] + post_fec_ber_ln = [] + lane_not_rdy_cnt = [] + lane_not_rdy_sl = [] + lane_not_rdy_ln = [] + for slc in slices: + lane_not_rdy_cnt.append(0) + post_fec_ber_cnt.append(0) + pre_fec_ber_cnt.append([]) + for bin in range(len(pre_fec_ber_bins)): + pre_fec_ber_cnt[slc].append(0) + + for slc in slices: + for ln in lanes: + if(gLaneStats[slc][ln][8] == 'RDY'): + #### PRBS BER binning + curr_prbs_cnt = float(gLaneStats[slc][ln][0]) + prbs_accum_time = gLaneStats[slc][ln][4] - gLaneStats[slc][ln][3] + data_rate = gEncodingMode[slc][ln][1] + bits_transferred = float((prbs_accum_time * data_rate * pow(10, 9))) + if curr_prbs_cnt == 0 or bits_transferred == 0: + pre_fec_ber_cnt[slc][-1] += 1 # if clean PRBS BER, add to last bin + else: + ber_val = curr_prbs_cnt / bits_transferred + ber_bin = next(x for x, val in enumerate(pre_fec_ber_bins) if ber_val >= val) + pre_fec_ber_cnt[slc][ber_bin] += 1 + if ber_bin == 0: + pre_fec_ber_sl.append(slc) + pre_fec_ber_ln.append(ln) + + #### Non-zero Post-FEC Cnt + if gLaneStats[slc][ln][10] > 0: + post_fec_ber_cnt[slc] += 1 + post_fec_ber_sl.append(slc) + post_fec_ber_ln.append(ln) + #### lane NOT_RDY cnt + else: + lane_not_rdy_cnt[slc] += 1 + lane_not_rdy_sl.append(slc) + lane_not_rdy_ln.append(ln) + + separator="\n +--------------+--------+--------+--------+" + print (separator) + print("\n | Metric | Slice0 | Slice1 | Total |"), + print (separator) + + print("\n | Link Not Rdy |"), + all_slices_cnt=0 + for slc in slices: + print("%4d %s|"%(lane_not_rdy_cnt[slc],'<<' if lane_not_rdy_cnt[slc] !=0 else ' ' )), + all_slices_cnt+=lane_not_rdy_cnt[slc] + print("%4d %s|"%(all_slices_cnt,'<<' if all_slices_cnt !=0 else ' ' )), + for sl_ln in range(len(lane_not_rdy_sl)): + print("[S%d_%s]"%(lane_not_rdy_sl[sl_ln],lane_name_list[lane_not_rdy_ln[sl_ln]])), + if sl_ln > 8: break # show up to 8 bad lanes + + for bin in range(len(pre_fec_ber_bins)): + print("\n | > %1.1e |"%(pre_fec_ber_bins[bin])), + all_slices_cnt=0 + for slc in slices: + print("%4d %s|"%(pre_fec_ber_cnt[slc][bin],'<<' if bin==0 and pre_fec_ber_cnt[slc][bin] !=0 else ' ' )), + all_slices_cnt+=pre_fec_ber_cnt[slc][bin] + print("%4d %s|"%(all_slices_cnt,'<<' if bin==0 and all_slices_cnt !=0 else ' ' )), + if bin==0: + for sl_ln in range(len(pre_fec_ber_sl)): + print("[S%d_%s]"%(pre_fec_ber_sl[sl_ln],lane_name_list[pre_fec_ber_ln[sl_ln]])), + if sl_ln > 8: break # show up to 8 bad lanes + + print("\n | Post-FEC (%2d)|"%gFecThresh), + all_slices_cnt=0 + for slc in slices: + print("%4d %s|"%(post_fec_ber_cnt[slc],'<<' if post_fec_ber_cnt[slc] !=0 else ' ')), + all_slices_cnt+=post_fec_ber_cnt[slc] + print("%4d %s|"%(all_slices_cnt,'<<' if all_slices_cnt !=0 else ' ' )), + for sl_ln in range(len(post_fec_ber_sl)): + print("[S%d_%s]"%(post_fec_ber_sl[sl_ln],lane_name_list[post_fec_ber_ln[sl_ln]])), + if sl_ln > 8: break # show up to 8 bad lanes + print (separator) + +#################################################################################################### +def rx_monitor_log (linecard_num=0,phy_num=0,slice_num=None,lane=None, rst=0, adapt_time=-1, header=1, logfile='rx_monitor_log.txt'): + global gLaneStats #[per Slice][per lane], [PrbsCount, PrbsCount-1,PrbsCount-2, PrbsRstTime, PrbsLastReadoutTime] + if slice_num is None: + slice_num = gSlice + post_fec_ber={} + + + lanes = get_lane_list(lane) + get_lane_mode(lanes) + + rx_monitor_capture(lane=lanes) + + log_file = open(logfile, 'a+') + if header: + ##### First Line of Header + log_file.write("\nLc/Ph/Sl,Adapt, BER"), + for ln in lanes: + log_file.write(",%7s" %(lane_name_list[ln])), # post-FEC BER + for ln in lanes: + log_file.write(",%7s" %(lane_name_list[ln])), # pre-FEC BER + for ln in lanes: + if(gEncodingMode[gSlice][ln][0].upper()== 'PAM4'): + log_file.write(",%4s" %(lane_name_list[ln])), # PAM4 Eye1 + log_file.write(",%4s" %(lane_name_list[ln])), # PAM4 Eye2 + log_file.write(",%4s" %(lane_name_list[ln])), # PAM4 Eye3 + else: + log_file.write(",%4s" %(lane_name_list[ln])), # NRZ Eye + + ##### Second Line of Header + log_file.write("\nLc/Ph/Sl, Time, Time"), + for ln in lanes: + log_file.write(",Fec-BER"), # post-FEC BER + for ln in lanes: + log_file.write(",Raw-BER"), # pre-FEC BER + for ln in lanes: + if(gEncodingMode[gSlice][ln][0].upper()== 'PAM4'): + log_file.write(",Eye1"), # PAM4 Eye1 + log_file.write(",Eye2" ), # PAM4 Eye2 + log_file.write(",Eye3" ), # PAM4 Eye3 + else: + log_file.write(", Eye"), # NRZ Eye + + + ##### Third Line is data, Linecard/Phy/Slice + log_file.write("\n%2d/%2d/%2d" %(linecard_num,phy_num,slice_num)), + log_file.write(",%5.1f"%(adapt_time)), + ber_time=gLaneStats[gSlice][lanes[0]][4] - gLaneStats[gSlice][lanes[0]][3] + log_file.write(",%5.0f"% (ber_time) ), # BER Collection time + + ##### Third Line is data, post-FEC BER + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + curr_prbs_cnt = float(gLaneStats[gSlice][ln][10]) + prbs_accum_time = gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + data_rate = gEncodingMode[gSlice][ln][1] + bits_transferred = float((prbs_accum_time*data_rate*pow(10,9))) + + if curr_prbs_cnt==0 or bits_transferred==0: + ber_val = 0 + log_file.write(",%7d" % (ber_val) ), # post-FEC BER + else: + ber_val= curr_prbs_cnt / bits_transferred + log_file.write(",%7.1e" % (ber_val) ),# post-FEC BER + post_fec_ber[ln] = ber_val + else: # Lane's PHY RDY = 0 + log_file.write(", -"), # post-FEC BER + + ##### Third Line is data, pre-FEC BER + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + curr_prbs_cnt = float(gLaneStats[gSlice][ln][0]) + prbs_accum_time = gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + data_rate = gEncodingMode[gSlice][ln][1] + bits_transferred = float((prbs_accum_time*data_rate*pow(10,9))) + if curr_prbs_cnt==0 or bits_transferred==0: + ber_val = 0 + log_file.write(",%7d" % (ber_val) ), # pre-FEC BER + else: + ber_val= curr_prbs_cnt / bits_transferred + log_file.write(",%7.1e" % (ber_val) ), # pre-FEC BER + else: # Lane's PHY RDY = 0 + log_file.write(", -"), # pre-FEC BER + + ##### Third Line is data, EYE MARGINS + for ln in lanes: + if(gLaneStats[gSlice][ln][8] == 'RDY'): + if(gEncodingMode[gSlice][ln][0].upper()== 'PAM4'): + log_file.write (",%4.0f"%(gLaneStats[gSlice][ln][5])), # Eye1 + log_file.write (",%4.0f"%(gLaneStats[gSlice][ln][6])), # Eye2 + log_file.write (",%4.0f"%(gLaneStats[gSlice][ln][7])), # Eye3 + else: + log_file.write (",%4.0f"%(gLaneStats[gSlice][ln][5])), # Eye + else: # Lane's PHY RDY = 0 + if(gEncodingMode[gSlice][ln][0].upper()== 'PAM4'): + log_file.write(", -"), # PAM4 Eye1 + log_file.write(", -"), # PAM4 Eye2 + log_file.write(", -"), # PAM4 Eye3 + else: + log_file.write(", -"), # NRZ Eye + + + if header: + log_file.write("\n") + log_file.close() + return post_fec_ber , ber_time +#################################################################################################### +def rx_monitor(rst=0, lane=None, slice=None, fec_thresh=gFecThresh, print_en=1, returnon = 0, mode='PRBS31'): + + lanes = get_lane_list(lane) + + if (rst>0): + if rst>1: + print("BER Accumulation Time: %1.1f sec"%(float(rst))) + rx_monitor_clear(lane=lanes,fec_thresh=fec_thresh, mode=mode) + if rst>1: + time.sleep(float(rst-(len(lanes)*0.05))) + else: # rst=0 + # in case any of the lanes' PRBS not cleared or FEC Analyzer not initialized, clear its Stats first + for ln in lanes: + if gLaneStats[gSlice][ln][3]==0 or gLaneStats[gSlice][ln][8] != 'RDY': + rx_monitor_clear(lane=ln,fec_thresh=fec_thresh) + #print("\nSlice %d Lane %s RX_MONITOR Initialized First!"%(gSlice,lane_name_list[ln])), + + rx_monitor_capture(lane=lane) + if print_en: + mydata = rx_monitor_print(lane=lane,slice=slice) + if returnon ==1: return mydata +#################################################################################################### +def ber(rst=0,lane=None, t=None,fec_thresh=gFecThresh): + + lanes = get_lane_list(lane) + + if (rst>0): + if rst>1: + print("BER Accumulation Time: %1.1f sec"%(float(rst))) + rx_monitor_clear(lane=lanes,fec_thresh=fec_thresh) + if rst>1: + time.sleep(float(rst-(len(lanes)*0.05))) + else: # rst=0 + # in case any of the lanes' PRBS not cleared or FEC Analyzer not initialized, clear its Stats first + for ln in lanes: + if gLaneStats[gSlice][ln][3]==0 or gLaneStats[gSlice][ln][8] != 'RDY': + rx_monitor_clear(lane=ln,fec_thresh=fec_thresh) + #print("\nSlice %d Lane %s RX_MONITOR Initialized First!"%(gSlice,lane_name_list[ln])), + + if (t!=None): + time.sleep(t) + rx_monitor_capture(lane=lane) + result={} + for ln in lanes: + prbs_accum_time = gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + data_rate = gEncodingMode[gSlice][ln][1] + bits_transferred = float((prbs_accum_time*data_rate*pow(10,9))) + + prbs_err_cnt = float(gLaneStats[gSlice][ln][0]) + #pre_fec_cnt = float(gLaneStats[gSlice][ln][9]) + post_fec_cnt = float(gLaneStats[gSlice][ln][10]) + if(gLaneStats[gSlice][ln][8] != 'RDY'): + prbs_ber = 1 + #pre_fec_ber = 1 + post_fec_ber = 1 + else: + #### PRBS BER + if prbs_err_cnt==0 or bits_transferred==0: + prbs_ber = 0 + else: + prbs_ber= prbs_err_cnt / bits_transferred + #### Pre-FEC BER + #if pre_fec_cnt==0 or bits_transferred==0: + #pre_fec_ber = 0 + #else: + #pre_fec_ber= pre_fec_cnt / bits_transferred + #### Post-FEC BER + if post_fec_cnt==0 or bits_transferred==0: + post_fec_ber = 0 + else: + post_fec_ber= post_fec_cnt / bits_transferred + + result[ln] = prbs_ber, post_fec_ber + return result +#################################################################################################### +def ber(rst=0,lane=None, t=None,fec_thresh=gFecThresh): + + lanes = get_lane_list(lane) + + if (rst>0): + if rst>1: + print("BER Accumulation Time: %1.1f sec"%(float(rst))) + rx_monitor_clear(lane=lanes,fec_thresh=fec_thresh) + if rst>1: + time.sleep(float(rst-(len(lanes)*0.05))) + else: # rst=0 + # in case any of the lanes' PRBS not cleared or FEC Analyzer not initialized, clear its Stats first + for ln in lanes: + if gLaneStats[gSlice][ln][3]==0 or gLaneStats[gSlice][ln][8] != 'RDY': + rx_monitor_clear(lane=ln,fec_thresh=fec_thresh) + #print("\nSlice %d Lane %s RX_MONITOR Initialized First!"%(gSlice,lane_name_list[ln])), + + if (t!=None): + time.sleep(t) + rx_monitor_capture(lane=lane) + result={} + for ln in lanes: + prbs_accum_time = gLaneStats[gSlice][ln][4] - gLaneStats[gSlice][ln][3] + data_rate = gEncodingMode[gSlice][ln][1] + bits_transferred = float((prbs_accum_time*data_rate*pow(10,9))) + + prbs_err_cnt = float(gLaneStats[gSlice][ln][0]) + #pre_fec_cnt = float(gLaneStats[gSlice][ln][9]) + post_fec_cnt = float(gLaneStats[gSlice][ln][10]) + if(gLaneStats[gSlice][ln][8] != 'RDY'): + prbs_ber = 1 + #pre_fec_ber = 1 + post_fec_ber = 1 + else: + #### PRBS BER + if prbs_err_cnt==0 or bits_transferred==0: + prbs_ber = 0 + else: + prbs_ber= prbs_err_cnt / bits_transferred + #### Pre-FEC BER + #if pre_fec_cnt==0 or bits_transferred==0: + #pre_fec_ber = 0 + #else: + #pre_fec_ber= pre_fec_cnt / bits_transferred + #### Post-FEC BER + if post_fec_cnt==0 or bits_transferred==0: + post_fec_ber = 0 + else: + post_fec_ber= post_fec_cnt / bits_transferred + + result[ln] = prbs_ber, post_fec_ber + return result +#################################################################################################### +def ber_test(rst=0,lane=None, t=None, nrz_limit=0, pam4_limit=1e-6 ): + + pre_fec_ber_limit = 0 + post_fec_ber_limit = 0 + result={} + lanes = get_lane_list(lane) + ber_data = ber(lane, rst, t) + for ln in lanes: + pre_fec_ber_limit = nrz_limit if lane_mode_list[ln].lower() == 'nrz' else pam4_limit + if (ber_data[ln][0] > pre_fec_ber_limit) or (ber_data[ln][1] > post_fec_ber_limit): + result[ln]= 'Fail' + else: + result[ln]= 'Pass' + return result +#################################################################################################### +# copy_lane(source_lane, destination_lane) +# +# This function copies one lanes register to another lane, addr by addr +#################################################################################################### +def copy_lane(lane1, lane2): + + first_addr=0x000 + last_addr =0x1FF + + for addr in range(first_addr, last_addr+1, +1): + val=rreg(addr,lane1) + wreg(addr, val,lane2) + + if lane2%2: # destination lane is an ODD lane + set_bandgap(bg_val=7,lane=lane2) + else: # destination lane is an Even lane + set_bandgap(bg_val=2,lane=lane2) + + lr(lane=lane2) + print("\n....Slice %d Lane %s all registers copied to Lane %s "%(gSlice,lane_name_list[lane1],lane_name_list[lane2])) + +#################################################################################################### +# get_top_pll () +# +# reads TOP-PLL registers and computes TOP-PLL Frequencies +# +# returns all parameters for the specified top pll +# +#################################################################################################### +def get_top_pll (): + + top_pll_params = {} + + ext_ref_clk=156.25 + + ## TOP PLL A (0x9500) & TOP PLL B (0x9600) + # top_pll_en_refclk_addr = [0x9500, [7]] + # top_pll_pu_addr = [0x9501, [2]] + # top_pll_div4_addr = [0x9500, [6]] + # top_pll_n_addr = [0x9507, [12,4]] + # top_pll_lvcocap_addr = [0x9501, [12,6]] + # top_pll_refclk_div_addr = [0x9513, [15,7]] + # top_pll_div2_addr = [0x9513, [6]] + + for pll_idx in [0,1]: + div4_en = rregBits(c.top_pll_div4_addr[0]+(pll_idx*0x100) ,c.top_pll_div4_addr[1] ) + div2_bypass = rregBits(c.top_pll_div2_addr[0]+(pll_idx*0x100) ,c.top_pll_div2_addr[1] ) + refclk_div = rregBits(c.top_pll_refclk_div_addr[0]+(pll_idx*0x100) ,c.top_pll_refclk_div_addr[1]) + pll_n = rregBits(c.top_pll_n_addr[0]+(pll_idx*0x100) ,c.top_pll_n_addr[1] ) + pll_cap = rregBits(c.top_pll_lvcocap_addr[0]+(pll_idx*0x100) ,c.top_pll_lvcocap_addr[1]) + + div_by_4 = 1.0 if div4_en==0 else 4.0 + mul_by_2 = 1.0 if div2_bypass==1 else 2.0 + + fvco = (ext_ref_clk * float(pll_n) *2.0 * mul_by_2) / (div_by_4 * float(refclk_div) * 8.0) # in MHz + + top_pll_params[pll_idx] = fvco, pll_cap, pll_n, div4_en, refclk_div, div2_bypass, ext_ref_clk + + return top_pll_params #data_rate, fvco, pll_cap, pll_n, div4, div2, ext_ref_clk +#################################################################################################### +# +# Top PLL Setup Configuration +#################################################################################################### +def set_top_pll(pll_side='both', freq=195.3125): + + global gRefClkFreq; gRefClkFreq=195.3125 + + if pll_side is None: pll_side='both' + if type(pll_side)==int: + if pll_side==0: pll_side='A' + else: pll_side='B' + if type(pll_side)==str: pll_side=pll_side.upper() + + + ##### If FW already loaded and pll_top_cal done, then save the cap values to restore them + #if fw_loaded(print_en=0): + top_pll_A_cap = rreg([0x9501,[12,6]]) + top_pll_B_cap = rreg([0x9601,[12,6]]) + + ##### Top PLL B-side lanes + if pll_side == 'A' or pll_side == 'BOTH': + wreg(0x9500, 0x1aa0) + wreg(0x9500, 0x0aa0) # [12]=0, do not bypass 1p7 regulator + wreg(0x9501, 0x8a5b) # Top PLL A powered down while programming it, bit [2]=0 + wreg(0x9502, 0x03e6) # 0x03b6 + wreg(0x9503, 0x6d86) + wreg(0x9504, 0x7180) + wreg(0x9505, 0x9000) + wreg(0x9506, 0x0000) + wreg(0x9507, 0x0500) + wreg(0x950a, 0x4040) + wreg(0x950b, 0x0000) + wreg(0x950d, 0x0000) + wreg(0x9510, 0xb670) + wreg(0x9511, 0x0000) + wreg(0x9512, 0x7de8) + wreg(0x9513, 0x0840) + + wreg(0x9512, 0xfde8) + wreg(0x9501, 0x8a5f) # Top PLL A on after programming it, bit [2]=1 + + wreg(0x9501, 0x89df) # default top_pll_A_cap = 0x27 + if fw_loaded(print_en=0): # if FW loaded, restore cal'ed value for top_pll_A_cap + wreg([0x9501,[12,6]], top_pll_A_cap) + + if type(freq)==str and freq.upper()=='OFF': + wregBits(0x9501, [2], 0) + + ##### Top PLL B-side lanes + if pll_side == 'B' or pll_side == 'BOTH': + wreg(0x9600, 0x1aa0) + wreg(0x9600, 0x0aa0) # [12]=0, do not bypass 1p7 regulator + wreg(0x9601, 0x8a5b) # Top PLL B powered down while programming it, bit [2]=0 + wreg(0x9602, 0x03e6) # 0x03b6 + wreg(0x9603, 0x6d86) + wreg(0x9604, 0x7180) + wreg(0x9605, 0x9000) + wreg(0x9606, 0x0000) + wreg(0x9607, 0x0500) + wreg(0x960a, 0x4040) + wreg(0x960b, 0x0000) + wreg(0x960d, 0x0000) + wreg(0x9610, 0xb670) + wreg(0x9611, 0x0000) + wreg(0x9612, 0x7de8) + wreg(0x9613, 0x0840) + + wreg(0x9612, 0xfde8) + wreg(0x9601, 0x8a5f) # Top PLL A powered up after programming it, bit [2]=1 + + wreg(0x9601, 0x89df) # default top_pll_B_cap = 0x27 + if fw_loaded(print_en=0): # if FW loaded, restore cal'ed value for top_pll_B_cap + wreg([0x9601,[12,6]], top_pll_B_cap) + + if type(freq)==str and freq.upper()=='OFF': + wregBits(0x9601, [2], 0) + +#################################################################################################### +def set_top_pll_bypass(pll_side='both', freq=195.3125): + + global gRefClkFreq; gRefClkFreq=195.3125 + + if pll_side is None: pll_side='both' + if type(pll_side)==int: + if pll_side==0: pll_side='A' + else: pll_side='B' + if type(pll_side)==str: pll_side=pll_side.upper() + + ##### If FW already loaded and pll_top_cal done, then save the cap values to restore them + if fw_loaded(print_en=0): + top_pll_A_cap = rreg([0x9501,[12,6]]) + top_pll_B_cap = rreg([0x9601,[12,6]]) + + ##### Top PLL B-side lanes + if pll_side == 'A' or pll_side == 'BOTH': + wreg(0x9500, 0x1a20) # Bypass Top PLL A + wreg(0x9500, 0x0a20) # [12]=0, do not bypass 1p7 regulator + #wreg(0x9500, 0x1aa0) + #wreg(0x9500, 0x0aa0) # [12]=0, do not bypass 1p7 regulator + wreg(0x9501, 0x8a5b) # Top PLL A poewred down while programming it, bit [2]=0 + wreg(0x9502, 0x03e6) # 0x03b6 + wreg(0x9503, 0x6d86) + wreg(0x9504, 0x7180) + wreg(0x9505, 0x9000) + wreg(0x9506, 0x0000) + wreg(0x9507, 0x0500) + wreg(0x950a, 0x4040) + wreg(0x950b, 0x0000) + wreg(0x950d, 0x0000) + wreg(0x9510, 0xb670) + wreg(0x9511, 0x0000) + wreg(0x9512, 0x7de8) + wreg(0x9513, 0x0840) + + wreg(0x9512, 0xfde8) + wreg(0x9501, 0x8a5f) # Top PLL A on after programming it, bit [2]=1 + + wreg(0x9501, 0x89df) # default top_pll_A_cap = 0x27 + if fw_loaded(print_en=0): # if FW loaded, restore cal'ed value for top_pll_A_cap + wreg([0x9501,[12,6]], top_pll_A_cap) + + if type(freq)==str and freq.upper()=='OFF': + wregBits(0x9501, [2], 0) + + ##### Top PLL B-side lanes + if pll_side == 'B' or pll_side == 'BOTH': + wreg(0x9600, 0x1a20) + wreg(0x9600, 0x0a20) # [12]=0, do not bypass 1p7 regulator + #wreg(0x9600, 0x1aa0) + #wreg(0x9600, 0x0aa0) # [12]=0, do not bypass 1p7 regulator + wreg(0x9601, 0x8a5b) # Top PLL B powered down while programming it, bit [2]=0 + wreg(0x9602, 0x03e6) # 0x03b6 + wreg(0x9603, 0x6d86) + wreg(0x9604, 0x7180) + wreg(0x9605, 0x9000) + wreg(0x9606, 0x0000) + wreg(0x9607, 0x0500) + wreg(0x960a, 0x4040) + wreg(0x960b, 0x0000) + wreg(0x960d, 0x0000) + wreg(0x9610, 0xb670) + wreg(0x9611, 0x0000) + wreg(0x9612, 0x7de8) + wreg(0x9613, 0x0840) + + wreg(0x9612, 0xfde8) + wreg(0x9601, 0x8a5f) # Top PLL A powered up after programming it, bit [2]=1 + + wreg(0x9601, 0x89df) # default top_pll_B_cap = 0x27 + if fw_loaded(print_en=0): # if FW loaded, restore cal'ed value for top_pll_B_cap + wreg([0x9601,[12,6]], top_pll_B_cap) + + if type(freq)==str and freq.upper()=='OFF': + wregBits(0x9601, [2], 0) + +############################################################################## +def fec_reset(fec_list=[0,1,2,3,4,5,6,7]): + + for fec_idx in fec_list: + wreg([0x9857, [fec_idx]], 1) # FEC_x enabled + time.sleep(0.01) + wreg([fec_class3[fec_idx]+0x80,[7,6]], 0x3) # Reset FEC x + time.sleep(0.01) + wreg([fec_class3[fec_idx]+0x80,[11,8]], 0xf) # FEC_A: TX forced to value 1, RX forced to reset + wreg([fec_class3[fec_idx]+0x80,[11,8]], 0xf) # FEC_B: TX forced to value 1, RX forced to reset + wreg([0x9857, [fec_idx]], 0) # FEC_x disabled + + #wreg(0x9858, 0x0000) # clear FEC-to-SerdesLanes Mapping + + +#################################################################################################### +# +# Top PLL Setup Configuration +#################################################################################################### +def set_bandgap(bg_val=None, lane=None): + + lanes = get_lane_list(lane) + + if bg_val!=None: + for lane in lanes: + if type(bg_val) == int: + bg_val = max(0, min(bg_val, 7)) + wregBits(0x0ff,[12],1,lane) # power up TX BG + wregBits(0x1ff,[12],1,lane) # power up RX BG + wregBits(0x0ff,[15,13],bg_val,lane) + wregBits(0x1ff,[15,13],bg_val,lane) + elif bg_val.upper()=='OFF': # power down BG + wregBits(0x0ff,[12],0,lane) + wregBits(0x1ff,[12],0,lane) + else: #if bg_val.upper()=='ON': # power up BG, leave BG value as is + wregBits(0x0ff,[12],1,lane) + wregBits(0x1ff,[12],1,lane) + + if bg_val is None: + tx_bg_pu =[] + rx_bg_pu =[] + tx_bg_val =[] + rx_bg_val =[] + for lane in range(0,len(lane_name_list)): + tx_bg_pu.append (rreg([0x0ff, [12]],lane)) # TX BG powered up/down? + rx_bg_pu.append (rreg([0x1ff, [12]],lane)) # RX BG powered up/down? + tx_bg_val.append(rreg([0x0ff,[15,13]],lane)) # TX BG value + rx_bg_val.append(rreg([0x1ff,[15,13]],lane)) # RX BG value + + print ("Lanes :",lanes) + print ("TX BG PU :",tx_bg_pu) + print ("RX BG PU :",rx_bg_pu) + print ("TX BG Val:",tx_bg_val) + print ("RX BG Val:",rx_bg_val) + +#################################################################################################### +# Program Clock Output Test Points (CLKOUT0 +/- DIFF, CLKOUT1 single-ended or CLKOUT2 single-ended) +# +# +#################################################################################################### +def set_clock_out(clkout='???', clkdiv=32, lane=0,print_en=0): + + CLKOUT_REG = [0x98D5,0x98D6,0x98D7,0x98D8,0x98D9] + clkout_div_list=[32,64,128,256,512,1024,2048,4096] + if clkdiv in clkout_div_list: + div_index = clkout_div_list.index(clkdiv) + else: + div_index=0 + clkdiv=clkout_div_list[div_index] + + ###### CLKOUT0 Differential output pins + if clkout.lower() == '0': + wreg([CLKOUT_REG[0],[ 3, 0]],lane) # select target lane's clock to send to clock out 0 + wreg([CLKOUT_REG[1],[ 12]],1) # enable clock out 0 mux + wreg([CLKOUT_REG[1],[ 2, 0]],div_index) # select clock out 0 divider + wreg([CLKOUT_REG[3],[14,13]],3) # enable clock out main driver + wreg([CLKOUT_REG[3],[11, 8]],0xF) # enable clock out 0 driver + wreg([CLKOUT_REG[4],[13, 0]],0x3FFF) # power up bandgap for clock out driver + pll_params = get_lane_pll(lane) + data_rate=pll_params[lane][0][0] + fvco=pll_params[lane][0][1] + fclkout=float(1000*fvco/float(clkdiv)) + print("\n...Turned On CLKOUT0 Diff pins, PLL Lane: %d, ClkOutDivider: %d, BitRate: %2.5f Gbps, PLL: %2.5f GHz, FclkOut0: %2.5f MHz"%(lane,clkdiv,data_rate,fvco,fclkout)) + + ###### CLKOUT1 single-ended output pin + elif clkout.lower() == '1': + wreg([CLKOUT_REG[0],[ 7, 4]],lane) # select target lane's clock to send to clock out 1 + wreg([CLKOUT_REG[1],[ 13]],1) # enable clock out 1 mux + wreg([CLKOUT_REG[1],[ 5, 3]],div_index) # select clock out 1 divider + wreg([CLKOUT_REG[3],[14,13]],3) # enable clock out main driver + wreg([CLKOUT_REG[3],[ 7, 4]],0xF) # enable clock out 1 driver + wreg([CLKOUT_REG[4],[13, 0]],0x3FFF) # power up bandgap for clock out driver + pll_params = get_lane_pll(lane) + data_rate=pll_params[lane][0][0] + fvco=pll_params[lane][0][1] + fclkout=float(1000*fvco/float(clkdiv)) + print("\n...Turned On CLKOUT1 pin, PLL Lane: %d, ClkOutDivider: %d, BitRate: %2.5f Gbps, PLL: %2.5f GHz, FclkOut1: %2.5f MHz"%(lane,clkdiv,data_rate,fvco,fclkout)) + ###### CLKOUT2 single-ended output pin + elif clkout.lower() == '2': + wreg([CLKOUT_REG[0],[11, 8]],lane) # select target lane's clock to send to clock out 2 + wreg([CLKOUT_REG[1],[ 14]],1) # enable clock out 2 mux + wreg([CLKOUT_REG[1],[ 8, 6]],div_index) # select clock out 2 divider + wreg([CLKOUT_REG[3],[14,13]],3) # enable clock out main driver + wreg([CLKOUT_REG[3],[ 3, 0]],0xF) # enable clock out 2 driver + wreg([CLKOUT_REG[4],[13, 0]],0x3FFF) # power up bandgap for clock out driver + pll_params = get_lane_pll(lane) + data_rate=pll_params[lane][0][0] + fvco=pll_params[lane][0][1] + fclkout=float(1000*fvco/float(clkdiv)) + print("\n...Turned On CLKOUT2 pin, PLL Lane: %d, ClkOutDivider: %d, BitRate: %2.5f Gbps, PLL: %2.5f GHz, FclkOut2: %2.5f MHz"%(lane,clkdiv,data_rate,fvco,fclkout)) + elif clkout.lower() == 'off': + wreg(CLKOUT_REG[0],0x0000) # back to the default lane 0 for all clock out pins + wreg(CLKOUT_REG[1],0x0000) # disable all clock out mux'es + wreg(CLKOUT_REG[2],0x0000) # default + wreg(CLKOUT_REG[3],0x0000) # disable clock out main driver + wreg(CLKOUT_REG[4],0x0000) # power down bandgap for clock out driver + print("\n...Turned Off ALL Three Clock Output Pins!") + else: + print("\n...Usage:") + print("\n set_clock_out (clkout='0', clkdiv=32, lane=0)"), + print("\n set_clock_out (clkout='1', clkdiv=32, lane=0)"), + print("\n set_clock_out (clkout='2', clkdiv=32, lane=0)"), + print("\n set_clock_out ('OFF') ") + print("\n...Parameters:") + print("\n clkout : selects clock-out pin to program"), + print("\n '0' :Outout to differential clock-out pins CKOP/CKON "), + print("\n '1' :Output to Single-ended clock-out pin CLK_OUT1 "), + print("\n '2' :Output to Single-ended clock-out pin CLK_OUT2 "), + print("\n 'off' :Turn OFF all three clock-out pins") + print("\n clkdiv : selects clock-out divider (from target lane's PLL) "), + print("\n choices: 32,64,128,256,1024,2048 or 4096 ") + print("\n lane : selects target lane's PLL as source for clock-out pin"), + print("\n choices: : 0 to 15") + + if print_en: reg([0x98D5,0x98D6,0x98D7,0x98D8,0x98D9]) +#################################################################################################### +# Read On-Chip Temperature Sensor by FIRMWARE +# +# FW Register 170 contain die temp value. It is updated by FW every few mSec +# +#################################################################################################### +def fw_temp_sensor(print_en=1): + + Yds = 237.7 + Kds = 79.925 + value = fw_reg_rd(170) # FW REG 170 contains temp sensor readback value by FW + realVal = value*Yds/4096-Kds + if print_en: print('FW Temp Sensor: %3.1f C'%(realVal)), + else: return realVal +#################################################################################################### +# Read On-Chip Temperature Sensor +# +#################################################################################################### +def temp_sensor_fast(sel=0): + + base = 0xb000 + Yds = 237.7 + Kds = 79.925 + addr= [base+0x39,base+0x3a,base+0x3b,base+0x3c] + MdioWr(base+0x37, 0x2d) # set write ack. Do this to make the first read correct + MdioWr(base+0x37, 0x0d) # set read with ack + #time.sleep(1) + rdy = MdioRd(base+0x38)&0x01 + time1=time.time() + #time2=time.time() + while(rdy==0): # wait for rdy + rdy = MdioRd(base+0x38)&0x01 + time2=time.time() + if (time2-time1)>=2: + print ('TSensor Read-back Timed Out!') + break + + value = MdioRd(addr[sel]) + realVal = value*Yds/4096-Kds + #print('TempSensor: %3.1f C'%(realVal)), + #print('tempsensor%d: %d,realVal:%f'%(sel,value,realVal)) + MdioWr(base+0x37, 0x2d) #write ack + return realVal +#################################################################################################### +# Read On-Chip Temperature Sensor +# +#################################################################################################### +def temp_sensor(print_en=True): + temp_sensor_start() + value1=temp_sensor_read() + if print_en: print('Device TempSensor: %3.1f C'%(value1)), + return value1 + +#################################################################################################### +# Set up On-Chip Temperature Sensor (to be read later) +# +#################################################################################################### +def temp_sensor_start(): + base = 0xB000 + #MdioWr(0x81f7,0x4d80) #set tst0 value + MdioWr(base+0x3e, 0x10d) #set clock + time.sleep(0.1) + MdioWr(base+0x37, 0x0) #reset sensor + time.sleep(0.1) + MdioWr(base+0x37, 0xc) #set no ack +#################################################################################################### +# Read back On-Chip Temperature Sensor (after it's been set up aready) +# +#################################################################################################### +def temp_sensor_read(): + base = 0xB000 + sense_addr= base+0x39 + Yds = 237.7 + Kds = 79.925 + + rdy = MdioRd(base+0x38)>>8 + while(rdy==0): # wait for rdy + rdy = MdioRd(base+0x38)>>8 + value1 = MdioRd(sense_addr)*Yds/4096-Kds + #print('%3.1f C'%(value1)), + return value1 +#################################################################################################### +# background_cal() # returns status of current gLane +# background_cal(lane=11) # returns status of current gLane +# background_cal('en', lane=11) # enable for lane 11 (B0) +# background_cal('dis',lane=11) # disable for lane 11 (B0) +# background_cal() # returns status of current gLane +# background_cal() # returns status of current gLane +#################################################################################################### +def background_cal (enable=None,lane=None,print_en=1): + + lanes = get_lane_list(lane) + + get_lane_mode(lanes) + background_cal_status=[] + lane_cntr=0 + for ln in lanes: + if gEncodingMode[gSlice][ln][0]=='pam4': # Lane is in PAM4 mode + c=Pam4Reg + else: + print("\nSlice %d Lane %s (NRZ) Background Cal: ***>> Lane is in NRZ Mode (No Background Cal!)\n"%(gSlice,lane_name_list[lane])) + return + + # Asked to enable or disable background cal + if enable!=None: + #### Clear BP2, Toggle BP1 and Continue to BP1 at state 0x12 + bp2(0,0x0,lane=ln) + bp1(0,0x0,lane=ln) + sm_cont_01(lane=ln) + bp1(1,0x12,lane=ln) + wait_for_bp1_timeout=0 + # Wait for BP1 state 0x12 to be reached + while True: + if bp1(lane=ln)[ln][-1]: #BP1 state 0x12 is reached + break + else: + wait_for_bp1_timeout+=1 + if wait_for_bp1_timeout>5000: + if(print_en):print("\nSlice %d Lane %s (PAM4) Background Cal: ***>> Timed out waiting for BP1\n"%(gSlice,lane_name_list[ln])) + #save_setup('background_cal_timeout.txt') + break + + if enable=='en' or enable==1: # asked to enable background cal + wreg ([0x4, [0]], 1, ln) + wreg (0x077, 0x4e5c, ln) + wreg (0x078, 0xe080, ln) + wreg (c.rx_iter_s6_addr, 6, ln) + wreg (c.rx_mu_ow_addr, 3, ln) + else: # asked to disable background cal + wreg (c.rx_iter_s6_addr, 1, ln) + wreg (c.rx_mu_ow_addr, 0, ln) + #wreg (c.rx_iter_s6_addr, 1, ln) + #wreg (c.rx_mu_ow_addr, 0, ln) + + bp1(0,0x12,lane=ln) # clear BP1 + sm_cont_01(lane=ln) # toggle SM Continue + + else: + print_en=1 + + # return Status of background cal for this lane + if(print_en):print("\nSlice %d Lane %s (PAM4) Background Cal: "%(gSlice,lane_name_list[ln])) + + background_cal_status.append(rreg(c.rx_mu_ow_addr,ln) & 0x01) + if background_cal_status[lane_cntr] == 0: + if(print_en):print ("OFF") + else: + if(print_en):print ("ON") + lane_cntr+=1 # next lane, if applicable + + return background_cal_status +#################################################################################################### +# +# DC_GAIN +#################################################################################################### +def dc_gain2(ctle_gain1=None, ctle_gain2=None, ffe_gain1=None, ffe_gain2=None, lane=None): + + if ctle_gain1=='?': + print("\n ***> Usage: dc_gain(ctle_gain1, ffe_gain1, ctle_gain2, ffe_gain2, lane#)") + ctle_gain1=None; ctle_gain2=None; ffe_gain1=None; ffe_gain2=None; lane=None + print("\n ***> Current settings shown below:") + + if lane is None: lane=gLane + if type(lane)==int: lanes=[lane] + elif type(lane)==list: lanes=list(lane) + elif type(lane)==str and lane.upper()=='ALL': + lanes=range(0,len(lane_name_list)) + + for lane in lanes: + ## Convert from binary to Gray and write dc gain to registers + if ctle_gain1 !=None: + ctle_gain1_gray = Bin_Gray(ctle_gain1) + wreg(c.rx_agcgain1_addr, ctle_gain1_gray, lane) + + if ctle_gain2 !=None: + ctle_gain2_gray = Bin_Gray(ctle_gain2) + wreg(c.rx_agcgain2_addr, ctle_gain2_gray, lane) + + if ffe_gain1 !=None: + ffe_gain1_gray = Bin_Gray(ffe_gain1) + wreg(c.rx_ffe_sf_msb_addr, ffe_gain1_gray, lane) + + if ffe_gain2 !=None: + ffe_gain2_gray = Bin_Gray(ffe_gain2) + wreg(c.rx_ffe_sf_lsb_addr, ffe_gain2_gray, lane) + + ##read DC gain from register and convert to binary from gray code + ctle_gain1_bin = Gray_Bin (rreg(c.rx_agcgain1_addr, lane)) + ctle_gain2_bin = Gray_Bin (rreg(c.rx_agcgain2_addr, lane)) + ffe_gain1_bin = Gray_Bin (rreg(c.rx_ffe_sf_msb_addr, lane)) + ffe_gain2_bin = Gray_Bin (rreg(c.rx_ffe_sf_lsb_addr, lane)) + + return ctle_gain1_bin, ctle_gain2_bin, ffe_gain1_bin, ffe_gain2_bin +#################################################################################################### +# +# set or get CTLE PEAKING index selection +#################################################################################################### +def ctle2(val = None, lane = None): + lanes = get_lane_list(lane) + + for lane in lanes: + if val != None: + wreg(c.rx_agc_ow_addr, val, lane) + wreg(c.rx_agc_owen_addr, 0x1, lane) + + val = rreg(c.rx_agc_ow_addr, lane) + + return val +#################################################################################################### +# +# set or get CTLE PEAKING 1/2 settings +#################################################################################################### +def ctle_map2(sel = None, val1 = None, val2 = None, lane = None): + + lanes = get_lane_list(lane) + + for lane in lanes: + if not None in (sel, val1, val2): + if sel != 2 and sel != 5: + val = (val1<<3) + val2 + if sel == 0: + map0 = (rreg(c.rx_agc_map0_addr, lane) | 0xfc00) & (val<<10 | 0x3ff) + wreg(c.rx_agc_map0_addr, map0, lane) + elif sel == 1: + map0 = (rreg(c.rx_agc_map0_addr, lane) | 0x03f0) & (val<<4 | 0xfc0f) + wreg(c.rx_agc_map0_addr, map0, lane) + elif sel == 3: + map1 = (rreg(c.rx_agc_map1_addr, lane) | 0x3f00) & (val<<8 | 0xc0ff) + wreg(c.rx_agc_map1_addr, map1, lane) + elif sel == 4: + map1 = (rreg(c.rx_agc_map1_addr, lane) | 0x00fc) & (val<<2 | 0xff03) + wreg(c.rx_agc_map1_addr, map1, lane) + elif sel == 6: + map2 = (rreg(c.rx_agc_map2_addr, lane) | 0x0fc0) & (val<<6 | 0xf03f) + wreg(c.rx_agc_map2_addr, map2, lane) + elif sel == 7: + map2 = (rreg(c.rx_agc_map2_addr, lane) | 0x003f) & (val | 0xffc0) + wreg(c.rx_agc_map2_addr, map2, lane) + elif sel == 2: + val = (val1<<1) + (val2 & 0x4) + map0 = (rreg(c.rx_agc_map0_addr, lane) | 0x000f) & (val | 0xfff0) + wreg(c.rx_agc_map0_addr, map0, lane) + val = val2 & 0x3 + map1 = (rreg(c.rx_agc_map1_addr, lane) | 0xc000) & (val | 0x3fff) + wreg(c.rx_agc_map1_addr, map1, lane) + else:# sel == 5: + val = val1 & 0x6 + map1 = (rreg(c.rx_agc_map1_addr, lane) | 0x3) & (val | 0xfffc) + wreg(c.rx_agc_map1_addr, map1, lane) + val = ((val1 & 0x1)<<3) + val2 + map2 = (rreg(c.rx_agc_map2_addr, lane) | 0xf) & (val | 0x0fff) + wreg(c.rx_agc_map2_addr, map2, lane) + + # Read CTLE Peaking table values for each/this lane + map0 = rreg(c.rx_agc_map0_addr, lane) + map1 = rreg(c.rx_agc_map1_addr, lane) + map2 = rreg(c.rx_agc_map2_addr, lane) + agc = { 0: [map0>>13, (map0>>10) & 0x7], + 1: [(map0>>7) & 0x7, (map0>>4) & 0x7], + 2: [(map0>>1) & 0x7, ((map0 & 0x1)<<2) + (map1>>14)], + 3: [(map1>>11) & 0x7, (map1>>8) & 0x7], + 4: [(map1>>5) & 0x7, (map1>>2) & 0x7], + 5: [((map1 & 0x3)<<1) + (map2>>15), (map2>>12) & 0x7], + 6: [(map2>>9) & 0x7, (map2>>6) & 0x7], + 7: [(map2>>3) & 0x7, map2 & 0x7] + } + + if sel is None: + for key in agc.keys(): + print (key, agc[key]) + else: + return agc[sel] +#################################################################################################### +def sel_ctle_map(IL='ALL', lane=None): + + lanes = get_lane_list(lane) + + for lane in lanes: + if IL == 'SR' or IL == 'ALL' : + ctle_map(0,1,2,lane) + ctle_map(1,2,3,lane) + ctle_map(2,3,3,lane) + ctle_map(3,3,4,lane) + ctle_map(4,3,6,lane) + ctle_map(5,4,5,lane) + ctle_map(6,5,6,lane) + ctle_map(7,7,7,lane) + elif IL == 'MR': + wreg(0x048,0x2518,lane) # PAM4 mode, ctle_map + wreg(0x049,0x79eb,lane) # PAM4 mode, ctle_map + wreg(0x04a,0xbf3f,lane) # PAM4 mode, ctle_map, CTLE7=(7,7) + elif IL == 'VSR': + wreg(0x048,0x2518,lane) # PAM4 mode, ctle_map + wreg(0x049,0x79eb,lane) # PAM4 mode, ctle_map + wreg(0x04a,0xbf3f,lane) # PAM4 mode, ctle_map, CTLE7=(7,7) + + +#################################################################################################### +# +# Set or get f1over3 +# +# (1) f13() get f1over3 value of gLane +# (1) f13('all') get f1over3 values of all lanes +# (2) f13(2) set f1over3 value of gLane to 2 +# (3) f13(10, [0,15]) set f1over3 values of lanes 0 and 15 to the same value of 10 +# (4) f13(10, 'all') set delta values of all lanes to the same value of 10 +# +# returns: a list of f1over3 values, for the lane numbers passed +#################################################################################################### +def f13(val=None, lane=None): + + lanes = get_lane_list(lane) + + if type(val)==str and val.upper()=='ALL': + lanes=range(0,len(lane_name_list)) + val=None + + val_list_out=[]# return values goes in here + for lane in lanes: + if val!=None: + val_to_write = (val<0) and (val+0x80) or val + wreg(c.rx_f1over3_addr, val_to_write, lane) + #if(print_en):print ('\nF1o3 write %d, read back %d' % (val, f13())), + + f1o3 = rreg(c.rx_f1over3_addr, lane) + val_list_out.append((f1o3>0x40) and (f1o3-0x80) or f1o3) + + return val_list_out + +#################################################################################################### +# +# GET DFE Taps when FW not loaded +#################################################################################################### +def sw_pam4_dfe(lane=None, print_en=0): + global gPam4_En; gPam4_En=1 + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + get_lane_mode(ln) + if lane_mode_list[ln] != 'pam4': + result[ln] = -1,-1,-1 + else: # PAM4 + ths_list = [] + for val in range(12): + wreg(c.rx_pam4_dfe_sel_addr, val, ln) + time.sleep(0.01) + readout = rreg(c.rx_pam4_dfe_rd_addr, ln) + readout2 = rreg(c.rx_pam4_dfe_rd_addr, ln) + if readout == readout2: + this_ths = ((float(readout)/2048.0)+1.0) % 2.0 - 1.0 + if print_en: print(" %2d 0x%04X %6.3f"%(val,readout,this_ths)) + else: + readout = rreg(c.rx_pam4_dfe_rd_addr, ln) + this_ths = ((float(readout)/2048.0)+1.0) % 2.0 - 1.0 + if print_en: print("*%2d 0x%04X %6.3f"%(val,readout,this_ths)) + ths_list.append(this_ths) + + f0 = (-3/16)*((ths_list[0]-ths_list[2])+(ths_list[3]-ths_list[5])+(ths_list[6]-ths_list[8])+(ths_list[9]-ths_list[11])) + f1 = (-3/20)*((ths_list[0]+ths_list[1]+ths_list[2]-ths_list[9]-ths_list[10]-ths_list[11])+(1/3)*(ths_list[3]+ths_list[4]+ths_list[5]-ths_list[6]-ths_list[7]-ths_list[8])) + f1_f0 = 0 if f0==0 else f1/f0 + result[ln] = f0, f1, f1_f0 + + return result +#################################################################################################### +# +# GET DFE Taps by the FW +#################################################################################################### +def fw_pam4_dfe(lane=None,print_en=0): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + get_lane_mode(ln) + if lane_mode_list[ln] != 'pam4': + result[ln] = -1,-1,-1 + else: # PAM4 + readout = BE_info_signed(ln, 10, 1, 12) + ths_list = [] + for val in range(12): + ths_list.append(((float(readout[val])/2048.0)+1.0) % 2.0 - 1.0) + if print_en: print("%2d 0x%04X %6.3f"%(val,readout,result)) + + f0 = (-3/16)*((ths_list[0]-ths_list[2])+(ths_list[3]-ths_list[5])+(ths_list[6]-ths_list[8])+(ths_list[9]-ths_list[11])) + f1 = (-3/20)*((ths_list[0]+ths_list[1]+ths_list[2]-ths_list[9]-ths_list[10]-ths_list[11])+(1/3)*(ths_list[3]+ths_list[4]+ths_list[5]-ths_list[6]-ths_list[7]-ths_list[8])) + f1_f0 = 0 if f0==0 else f1/f0 + result[ln] = f0, f1, f1_f0 + + return result +#################################################################################################### +# +# GET DFE Taps by the FW if loaded, or by software +#################################################################################################### +def pam4_dfe(lane=None,print_en=0): + result = {} + if fw_loaded(print_en=0): + result = fw_pam4_dfe(lane,print_en) + else: + result = sw_pam4_dfe(lane,print_en) + return result +#################################################################################################### +# +# GET DFE Taps, NRZ or PAM4 +#################################################################################################### +def dfe(lane=None,print_en=0): + lanes = get_lane_list(lane) + result = {} + for ln in lanes: + get_lane_mode(ln) + if lane_mode_list[ln] == 'pam4': + result[ln] = pam4_dfe(ln,print_en) + else: # NRZ + result[ln] = nrz_dfe(ln) + + return result +#################################################################################################### +# +# Set or get DELTA Phase +# +# (1) delta_ph() get delta value of gLane +# (1) delta_ph('all') get delta values of all lanes +# (2) delta_ph(2) set delta value of gLane to 2 +# (3) delta_ph(10, [0,15]) set delta values of lanes 0 and 15 to the same value of 10 +# (4) delta_ph(10, 'all') set delta values of all lanes to the same value of 10 +# +# returns: a list of delta values, for the lane numbers passed +#################################################################################################### +def delta_ph(val=None, lane=None): + + lanes = get_lane_list(lane) + + if type(val)==str and val.upper()=='ALL': + lanes=range(0,len(lane_name_list)) + val=None + + val_list_out=[]# return values goes in here + for ln in lanes: + get_lane_mode(ln) + this_lane_mode = gEncodingMode[gSlice][ln][0] + c = NrzReg if this_lane_mode == 'nrz' else Pam4Reg + ######### PAM4 Mode + if this_lane_mode.upper()=='PAM4': + if val!=None: + delta_to_write= (val<0) and (val+0x80) or val + wreg(c.rx_delta_owen_addr, 1, ln) + wreg(c.rx_delta_ow_addr, delta_to_write, ln) + + delta_val= rreg(c.rx_delta_ow_addr, ln) + #val_list_out.append((delta_val>0x40) and (delta_val-0x80) or delta_val) + + ######### NRZ Mode + else: + if val!=None: + wreg(c.rx_delta_addr, val, ln) + delta_val = rreg(c.rx_delta_addr, ln) + + val_list_out.append((delta_val>0x40) and (delta_val-0x80) or delta_val) + + return val_list_out + +#################################################################################################### +# Initialize FEC Analyzer function +# +# This is a per-lane function +#################################################################################################### +def fec_ana_init(lane=None, delay=.1, err_type=2, T=gFecThresh, M=10, N=5440, print_en=1, mode=None): + lanes = get_lane_list(lane) + + FEC_ANA_BASE_ADDR = 0x1C0 + global gFecThresh + + if T!=None: gFecThresh=T + + for ln in lanes: + thresh=T + if gEncodingMode[gSlice][ln][0].lower() != 'pam4': + if thresh>7: thresh=7 ## if lane is in NRZ mode, max T is 7 + + #err_type: tei ctrl teo ctrl + wreg(FEC_ANA_BASE_ADDR+0x9, 0x6202,lane=ln) #set PRBS mode: force reload + + #wreg(FEC_ANA_BASE_ADDR+0x8, ( rreg(FEC_ANA_BASE_ADDR+0x8,lane=ln) | 0x0018), lane=ln) #set PRBS mode:PRBS31 + if mode == 'PRBS31': + #print("\n PRBS31") + wreg(FEC_ANA_BASE_ADDR+0x8, ( rreg(FEC_ANA_BASE_ADDR+0x8,lane=ln) | 0x0018), lane=ln) #set PRBS mode:PRBS31 + elif mode == 'PRBS13': + #print("\n PRBS13") + wreg(FEC_ANA_BASE_ADDR+0x8, ( rreg(FEC_ANA_BASE_ADDR+0x8,lane=ln) | 0x0008), lane=ln) #set PRBS mode:PRBS13 + elif mode == 'PRBS9': + #print("\n PRBS9") + wreg(FEC_ANA_BASE_ADDR+0x8, ( rreg(FEC_ANA_BASE_ADDR+0x8,lane=ln) | 0x0000), lane=ln) #set PRBS mode:PRBS9 + elif mode == 'PRBS15': + #print("\n PRBS15") + wreg(FEC_ANA_BASE_ADDR+0x8, ( rreg(FEC_ANA_BASE_ADDR+0x8,lane=ln) | 0x0010), lane=ln) #set PRBS mode:PRBS15 + + wreg(FEC_ANA_BASE_ADDR+0x0, ((rreg(FEC_ANA_BASE_ADDR+0x0,lane=ln) & 0xFFF0) | M),lane=ln) #set M = 10 + wreg(FEC_ANA_BASE_ADDR+0x4, N,lane=ln) #set N = 5440 + wreg(FEC_ANA_BASE_ADDR+0x5, (rreg(FEC_ANA_BASE_ADDR+0x5,lane=ln) & 0xf007) | ((thresh<<7)+(thresh<<3)),lane=ln) + wreg(FEC_ANA_BASE_ADDR+0x1, 0x000b, lane=ln) #reset FEC_counter + wreg(FEC_ANA_BASE_ADDR+0x1, 0x0003, lane=ln) #release the reset + wreg(FEC_ANA_BASE_ADDR+0xc, err_type,lane=ln) #set TEO error type = 2 means bits in error + wreg(FEC_ANA_BASE_ADDR+0xb, err_type,lane=ln) #set TEi error type = 2 means bits in error + if print_en: print ('\n....Lane %s: FEC Analyzer Initialized' %(lane_name_list[ln])) + + #time.sleep(delay) +#################################################################################################### +def fec_ana_read(lane=None): + lanes = get_lane_list(lane) + + print ('\n....FEC Analyzer Status....'), + print ('\nLane, RAW Errors, Uncorr Frames, Uncorr Symbols, Uncorr PRBS'), + for ln in lanes: + tei = fec_ana_tei(lane=ln) + teo = fec_ana_teo(lane=ln) + #sei = fec_ana_sei(lane=ln) + #bei = fec_ana_bei(lane=ln) + #print ('\n%4s, %10d, %13d, %14d, %11d'%(lane_name_list[ln],tei,teo,sei,bei)), + print ('\n%4s, %10d, %13d'%(lane_name_list[ln],tei,teo)), + +#################################################################################################### +def fec_ana_tei(lane=None): + FEC_ANA_BASE_ADDR = 0x1C0 + if lane is None: lane=gLane + + wreg(FEC_ANA_BASE_ADDR+0xD,4,lane) #set reading data of TEi low 16 bit + tei_l = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + wreg(FEC_ANA_BASE_ADDR+0xD,5,lane) #set reading data of TEi high 16 bit + tei_h = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + tei = tei_h*65536+tei_l #combinate the data + #print '\n....Lane %s: TEi counter: %d' %(lane_name_list[lane],tei), + return tei + +def fec_ana_teo(lane=None): + FEC_ANA_BASE_ADDR = 0x1C0 + if lane is None: lane=gLane + wreg(FEC_ANA_BASE_ADDR+0xD,6,lane ) #set reading data of TEo low 16 bit + teo_l = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + wreg(FEC_ANA_BASE_ADDR+0xD,7,lane) #set reading data of TEo high 16 bit + teo_h = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + teo = teo_h*65536+teo_l#combinate the data + #print '\n....Lane %s: TEo counter: %d' %(lane_name_list[lane],teo), + return teo + +def fec_ana_sei(lane=None): + FEC_ANA_BASE_ADDR = 0x1C0 + if lane is None: lane=gLane + wreg(FEC_ANA_BASE_ADDR+0xD,0,lane) #set reading data of SEi low 16 bit + sei_l = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + wreg(FEC_ANA_BASE_ADDR+0xD,1 ) #set reading data of SEi high 16 bit + sei_h = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + sei = sei_h*65536+sei_l#combinate the data + #print '\n....Lane %s: SEi counter: %d' %(lane_name_list[lane],sei), + return sei + +def fec_ana_bei(lane=None): + FEC_ANA_BASE_ADDR = 0x1C0 + if lane is None: lane=gLane + wreg(FEC_ANA_BASE_ADDR+0xD,2,lane) #set reading data of BEi low 16 bit + bei_l = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + wreg(FEC_ANA_BASE_ADDR+0xD,3 ,lane) #set reading data of BEi high 16 bit + bei_h = rreg(FEC_ANA_BASE_ADDR+0x7,lane)#read data + bei = bei_h*65536+bei_l#combinate the data + #print '\n....Lane %s: BEi counter: %d' %(lane_name_list[lane],bei), + return bei + +def fec_ana_hist_DFE(lane=None): + lanes = get_lane_list(lane) + f0=[] + f1=[] + ratio=[] + for ln in lanes: + #ln = lane_offset/(0x200) + f0.append(pam4_dfe(lane=ln)[ln][0]) + f1.append(pam4_dfe(lane=ln)[ln][1]) + ratio.append(pam4_dfe(lane=ln)[ln][2]) + print ('A%d: DFE %4.2f, %4.2f, %4.2f'%(ln, f0[ln], f1[ln], ratio[ln])) + #fmt = 'A%d: DFE %4.2f, %4.2f, %4.2f'%(ln, f0[ln], f1[ln], ratio[ln]) + #file.obj.write(fmt) + lane_hist_file_ptr = open('S%s_%s_data.txt'%(gSlice,lane_name_list[ln]),'a') + lane_hist_file_ptr.write("%s\n%s\n"%(f0[ln],f1[ln])) + lane_hist_file_ptr.close() + + return f0, f1, ratio + +def fec_ana_hist(hist_time=10,lane=None, slice=None, pass_fail_bin=6, file_name='fec_ana_histogram_all.txt'): + + #per_lane_data_files_en=0 # en/dis to save individual files per lanes + #pass_fail_result_print_en=1 + + lanes = get_lane_list(lane) + slices = get_slice_list(slice) + + ### FEC Analyzer Parameters + FEC_ANA_BASE_ADDR = 0x1C0 + num_groups=4 + bins_per_group=4 + + ### Create empty list for Hist Data + hist_slice_lane_bin=[] # list to contain each lane's hist counts + hist_pass_fail_list=[] # list to conatian each lane's pass-fail status + for slc in range(2): + hist_slice_lane_bin.append([]) + hist_pass_fail_list.append([]) + for ln in range(16): + hist_slice_lane_bin[slc].append([]) + hist_pass_fail_list[slc].append([]) + hist_pass_fail_list[slc][ln] = 0 + for bin in range(16): + hist_slice_lane_bin[slc][ln].append([]) + + ### Header for Histogram Data + timestr = time.strftime("%Y%m%d_%H%M%S") + fmt=('\n\n...FEC Analyzer Histogram, %d sec per bin, Slice%s '%(hist_time,'s' if len(slices)>1 else '')) + fmt+= str(slices) + fmt+= ', TimeStamp [%s]'%timestr + print (fmt) + hist_file_ptr = open(file_name, 'a') + hist_file_ptr.write(fmt) + hist_file_ptr.close() + + ### Start Histogram Collection for all target slices/lanes + print("\n...Histogram Collection in Progress...Error"), + for bin_grp in range(num_groups): + print("Bins[%d,%d,%d,%d]:"%(bin_grp*4,bin_grp*4+1,bin_grp*4+2,bin_grp*4+3)), + + ### Initialize FEC Analyzers for all target slices/lanes + for slc in slices: + sel_slice(slc) + if len(slices)>1: print("S%d%s"%(slc,' -' if slc==slices[0] else ',')), + #fec_ana_hist_DFE(lanes) + #fec_ana_hist_one_bin_grp_setup(bin_grp,fec_ana_err_type, fec_ana_T,fec_ana_M,fec_ana_N,lanes) # setup the FEC + for ln in lanes: + if gEncodingMode[slc][ln][0].upper() == 'PAM4': + fec_ana_err_type=0 + fec_ana_T=15 + fec_ana_M=10 + fec_ana_N=5440 + else: + fec_ana_err_type=0 + fec_ana_T=7 + fec_ana_M=10 + fec_ana_N=5280 + wreg([FEC_ANA_BASE_ADDR+0x5,[12]],1,ln) #reset Histogram + wreg([FEC_ANA_BASE_ADDR+0x5,[12]],0,ln) #reset Histogram + wreg([FEC_ANA_BASE_ADDR+0x5,[2,0]], bin_grp, ln) #select which group of histogram to read + wreg( FEC_ANA_BASE_ADDR+0x9, 0x6202,ln) #set PRBS mode: force reload + wreg( FEC_ANA_BASE_ADDR+0x8, (rreg(FEC_ANA_BASE_ADDR+0x8,ln) | 0x0018),ln) #set PRBS mode:PRBS31 + wreg( FEC_ANA_BASE_ADDR+0x0, ((rreg(FEC_ANA_BASE_ADDR+0x0,ln) & 0xFFF0) | fec_ana_M),ln) #set M = 10 + wreg( FEC_ANA_BASE_ADDR+0x4, fec_ana_N,ln) #set N = 5440 + wreg( FEC_ANA_BASE_ADDR+0x5, (rreg(FEC_ANA_BASE_ADDR+0x5,ln) & 0xf007) | ((fec_ana_T<<7)+(fec_ana_T<<3)) ,ln) #set T = 2 + wreg( FEC_ANA_BASE_ADDR+0x1, 0x000b,ln) #reset FEC_counter + wreg( FEC_ANA_BASE_ADDR+0x1, 0x0003,ln) #release the reset + wreg( FEC_ANA_BASE_ADDR+0xc, fec_ana_err_type,ln) #set TEO error type + wreg( FEC_ANA_BASE_ADDR+0xb, fec_ana_err_type,ln) #set TEi error type + + + ### Wait Time for Histogram Data Collection + time.sleep(hist_time) + + ### Capture FEC Analyzers Histogram for all target slices/lanes + for slc in slices: + sel_slice(slc) + for ln in lanes: + for bin in range(bins_per_group): + wreg(FEC_ANA_BASE_ADDR+0xD, 12+bin*2 ,ln) # set reading data of histogram 0 lower 16 bit + histo_lo = rreg(FEC_ANA_BASE_ADDR+0x7,ln) # read data + wreg(FEC_ANA_BASE_ADDR+0xD, 13+bin*2 ,ln) # set reading data of histogram 0 upper 16 bit + histo_hi = rreg(FEC_ANA_BASE_ADDR+0x7,ln) # read data + hist_cnt = (histo_hi*65536+histo_lo) + hist_slice_lane_bin[slc][ln][bin_grp*bins_per_group+bin]=hist_cnt # get the 32-bit data + if (bin_grp*bins_per_group+bin) >= pass_fail_bin and hist_cnt > 0: + hist_pass_fail_list[slc][ln] = 1 + + ### Finished Histogram Collection for all 16 bins. Print/save results + for slc in slices: + sel_slice(slc) + + #### Print Histogram Data for each slice + fmt=("\n\nBin") + for ln in lanes: + fmt+=(" S%d_%s " %(slc,lane_name_list[ln])) + fmt+=("\n---") + for unused in lanes: + fmt+=(" ---------") + for bin_grp in range(num_groups): + for bin in range(bins_per_group): + fmt+= '\n%-3d' %(bin_grp*bins_per_group+bin) + for ln in lanes: + cnt = hist_slice_lane_bin[slc][ln][bin_grp*bins_per_group+bin] + fmt+= " %-9s" %(str(cnt) if cnt!=0 else '.') + ##### Print Pass/Fail Results per lane + fmt+="\n " + for ln in lanes: + fmt+=("%-10s" %('' if hist_pass_fail_list[slc][ln] == 0 else ' **FAIL**')) + print (fmt) + + #### Save Histogram Data for both slices in the 'fec_ana_hist.txt' file + hist_file_ptr = open(file_name,'a') + hist_file_ptr.write(fmt) + hist_file_ptr.close() + + #### Save Histogram Data per-slice per-lane in individual files (if enabled) + # if per_lane_data_files_en: + # for ln in lanes: + # fmt=('\n...FEC Analyzer Histogram Slice %d Lane %s, %d sec per bin, TimeStamp [%s]\n'%(slc,lane_name_list[ln],hist_time,timestr)) + # for bin_grp in range(num_groups): + # for bin in range(bins_per_group): + # fmt+=("%d\n"%hist_slice_lane_bin[slc][ln][bin_grp*bins_per_group+bin]) + # lane_hist_file_ptr = open('fec_ana_hist_S%s_%s.txt'%(gSlice,lane_name_list[ln]),'a') + # lane_hist_file_ptr.write(fmt) + # lane_hist_file_ptr.close() + + return (sum([i.count(1) for i in hist_pass_fail_list])) +#################################################################################################### + +#################################################################################################### +CMD=0x9806 +CMD_DETAIL=0x9807 +REG_DATA=0x9f00 + +def MdioRd(addr): + #print "MdioRd addr 0x%x " % (addr) + libcameo.mdio_read.restype=ctypes.c_ushort + val=libcameo.mdio_read(gSlice,0x1,addr) + #print "MdioRd val 0x%x " % (val) + return val + #chip.MdioRd(addr) + +def MdioWr(addr, value): + #print "MdioWr addr 0x%x value 0x%x" % (addr,value) + libcameo.mdio_write(gSlice,0x1,addr, value) + #chip.MdioWr(addr, value) + + +def MdioRdh(addr): + return "0x%04x" % MdioRd(addr) + +#################################################################################################### +def BE_debug(lane, mode, index): + MdioWr(CMD_DETAIL, index) + cmd = 0xB000 + ((mode&0xf)<<4) + lane + result = fw_cmd(cmd) + if (result!=0x0b00+mode): + return -1 + #raise IOError("Debug command failed with code %04x" % result) + #print "Debug command failed with code %04x" % result + return MdioRd(CMD_DETAIL) +def BE_debug_signed(lane, mode, index): + value = BE_debug(lane, mode, index) + return value if value<0x8000 else value-0x10000 +def BE_debug1(lane, mode, index, length): + return BE_debugs(lane, mode, range(index, index+length)) +def BE_debug1_signed(lane, mode, index, length): + return BE_debugs_signed(lane, mode, range(index, index+length)) +def BE_debug2(lane, mode, index, l1, l2): + return [BE_debugs(lane, mode, range(index+i*l2, index+(i+1)*l2)) + for i in range(l1)] +def BE_debug2_signed(lane, mode, index, l1, l2): + return [BE_debugs_signed(lane, mode, range(index+i*l2, index+(i+1)*l2)) + for i in range(l1)] +def BE_debugs(lane, mode, index): + return [BE_debug(lane, mode, i) for i in index] +def BE_debugs_signed(lane, mode, index): + return [BE_debug_signed(lane, mode, i) for i in index] +def BE_debug32(lane, mode, index): + h = BE_debug(lane, mode, index) + l = BE_debug(lane, mode, index+1) + return (h<<16)+l +def BE_debug32_signed(lane, mode, index): + value = BE_debug32(lane, mode, index) + return value if value<0x80000000 else value-0x100000000 + + +def BE_info(lane, mode, index, size): + MdioWr(CMD_DETAIL, index) + mode |= 8 + cmd = 0xB000 + ((mode&0xf)<<4) + lane + result = fw_cmd(cmd) + if (result!=0x0b00+mode): + #result=-1 + return [-1 for i in range(size)] + #raise IOError("Info command failed with code %04x" % result) + return [MdioRd(REG_DATA+i) for i in range(size)] + +def BE_info_signed(lane, mode, index, size): + return [x if x<0x8000 else x-0x10000 for x in BE_info(lane, mode, index, size)] + +def pam4_info_fw(lane): + ISI = BE_info_signed(lane, 10, 0, 16) + ths = BE_info_signed(lane, 10, 1, 12) + ffe_accu = BE_info(lane, 10, 2, 8) + ffe_accu = [(ffe_accu[i]<<16) + ffe_accu[i+1] for i in range(0, 8, 2)] + ffe_accu = [x if x<0x80000000 else x-0x100000000 for x in ffe_accu] + ffe_accu = [x/32768.0 for x in ffe_accu] + ffe = BE_info_signed(lane, 10, 3, 7) + ffe_flips = BE_debugs(lane, 2, range(660, 664)) + print ("ISI =", ISI) + print ("ths =", ths) + print ("FFE_accu =", ffe_accu) + print ("FFE: K =", ffe[0:4], ", S = [%d %d], nbias = %d" % (ffe[5], ffe[6], ffe[4])) + print ("FFE: K Pol flips=", ffe_flips[0:4]) + + +def dump_fw(lane): + exit_codes = BE_debugs(lane, 0, range(100, 100+16)) + print ("exit codes =", [hex(x) for x in exit_codes]) + +def nrz_dump_fw(lane): + agcgain1_dc1 = BE_debugs(lane, 1, range(80, 80+9)) + agcgain2_dc1 = BE_debugs(lane, 1, range(100, 100+9)) + index_dc1 = BE_debugs(lane, 1, range(140, 140+9)) + of_cnt_dc1 = BE_debugs(lane, 1, range(120, 120+9)) + print ("-----------------FIRST DAC SEARCH------------------") + print ("|init agcgains|index number|of_cnt|result agcgains|") + for i in range(8) : + print ("| (%3d, %3d) | %3d |%5d | (%3d, %3d) |"%(agcgain1_dc1[i], agcgain2_dc1[i], index_dc1[i], of_cnt_dc1[i], agcgain1_dc1[i+1], agcgain2_dc1[i+1])) + print ("---------------------------------------------------") + + of_cnt_ca1 = BE_debugs(lane, 1, range(330, 330+8)) + of_thre_ca1 = BE_debugs(lane, 1, range(300, 300+8)) + hf_cnt_ca1 = BE_debugs(lane, 1, range(390, 390+8)) + hf_thre_ca1 = BE_debugs(lane, 1, range(360, 360+8)) + + of_cnt_ca2 = BE_debugs(lane, 1, range(338, 338+8)) + of_thre_ca2 = BE_debugs(lane, 1, range(308, 308+8)) + hf_cnt_ca2 = BE_debugs(lane, 1, range(398, 398+8)) + hf_thre_ca2 = BE_debugs(lane, 1, range(368, 368+8)) + + of_cnt_ca3 = BE_debugs(lane, 1, range(346, 346+8)) + of_thre_ca3 = BE_debugs(lane, 1, range(316, 316+8)) + hf_cnt_ca3 = BE_debugs(lane, 1, range(406, 406+8)) + hf_thre_ca3 = BE_debugs(lane, 1, range(376, 376+8)) + + print ("----------------------CHANNEL ANALYZER-----------------------") + print ("| CA1 | CA2 | CA3 |") + print ("|of_cnt of hf_cnt hf|of_cnt of hf_cnt hf|of_cnt of hf_cnt hf|") + for i in range(8) : + print ("|%5d %2d %5d %2d |%5d %2d %5d %2d |%5d %2d %5d %2d |"%(of_cnt_ca1[i], of_thre_ca1[i], hf_cnt_ca1[i], hf_thre_ca1[i], of_cnt_ca2[i], of_thre_ca2[i], hf_cnt_ca2[i], hf_thre_ca2[i], of_cnt_ca3[i], of_thre_ca3[i], hf_cnt_ca3[i], hf_thre_ca3[i])) + print ("-------------------------------------------------------------") + + ctle = BE_debugs(lane, 1, range(505, 505+4)) + dfe_ctle1 = [BE_debug_signed(lane, 1, 510+i) for i in range(3)] + dfe_ctle2 = [BE_debug_signed(lane, 1, 513+i) for i in range(3)] + dfe_ctle3 = [BE_debug_signed(lane, 1, 516+i) for i in range(3)] + dfe_ctle4 = [BE_debug_signed(lane, 1, 519+i) for i in range(3)] + print ("-------CTLE FINE SEARCH--------") + print ("| ctle |%4d|%4d|%4d|%4d|"%(ctle[0], ctle[1], ctle[2], ctle[3])) + print ("| dfe F1 |%4d|%4d|%4d|%4d|"%(dfe_ctle1[0], dfe_ctle2[0], dfe_ctle3[0], dfe_ctle4[0])) + print ("| dfe F2 |%4d|%4d|%4d|%4d|"%(dfe_ctle1[1], dfe_ctle2[1], dfe_ctle3[1], dfe_ctle4[1])) + print ("| dfe F3 |%4d|%4d|%4d|%4d|"%(dfe_ctle1[2], dfe_ctle2[2], dfe_ctle3[2], dfe_ctle4[2])) + print ("-------------------------------") + + agcgain1_dc2 = BE_debugs(lane, 1, range(89, 89+9)) + agcgain2_dc2 = BE_debugs(lane, 1, range(109, 109+9)) + index_dc2 = BE_debugs(lane, 1, range(149, 149+9)) + of_cnt_dc2 = BE_debugs(lane, 1, range(129, 129+9)) + print ("----------------SECOND DAC SEARCH------------------") + print ("|init agcgains|index number|of_cnt|result agcgains|") + for i in range(8) : + print ("| (%3d, %3d) | %3d |%5d | (%3d, %3d) |"%(agcgain1_dc2[i], agcgain2_dc2[i], index_dc2[i], of_cnt_dc2[i], agcgain1_dc2[i+1], agcgain2_dc2[i+1])) + print ("---------------------------------------------------") + + debug_states = BE_debugs(lane, 1, range(160, 160+8)) + print ("stats = [") + for i in range(8) : + print ("%2d "%(debug_states[i])) + print ("]") + +def pam4_dump_fw_linear_fit(lane): + pam4_state = BE_debug(lane, 2, 0) + error_exit = False + if pam4_state==0xeeef: + error_exit = True + pam4_state = BE_debug(lane, 0, 3) + try: + adapt_mode = BE_debug(lane, 2, 3) + except CoreException: + adapt_mode = 0 + if adapt_mode==0: + print ("Auto adapt mode") + elif adapt_mode==1: + print ("Factory fixed setting mode") + elif adapt_mode==2: + print ("User fixed setting mode") + else: + print ("Unknown adapt mode") + return + + agcgain1 = BE_debug(lane, 2, 23) + agcgain2 = BE_debug(lane, 2, 24) + agcgain1_dc1 = BE_debug(lane, 2, 8) + agcgain2_dc1 = BE_debug(lane, 2, 9) + final_of = BE_debug(lane, 2, 4) + final_hf = BE_debug(lane, 2, 5) + + dc_search_agcgain = BE_debug2(lane, 2, 300, 2, 15) + ratio = BE_debug(lane, 2, 2) + agc_index = BE_debug(lane, 2, 1) + restart_count = BE_debug(lane, 2, 7) + #delta = BE_debug_signed(lane, 2, 27) + delta_times0 = BE_debug_signed(lane, 2, 35)+1 + delta_dump0 = [BE_debug_signed(lane, 2, 110+i) for i in range(10)] + fm1_dump0 = [BE_debug_signed(lane, 2, 150+i) for i in range(10)] + ctle = BE_debug(lane, 2, 33) + next_f13 = BE_debug(lane, 2, 34) + dc_search_agcgain[0] = [(x>>8, x&0xff) for x in dc_search_agcgain[0]] + dc_search_agcgain[1] = [(x>>8, x&0xff) for x in dc_search_agcgain[1]] + + ctle_isi = BE_debug2_signed(lane, 2, 330, 2, 4) + ctle_record = BE_debug1_signed(lane, 2, 340, 2) + ctle_freq_accu = BE_debug_signed(lane, 2, 200) + ctle_freq_accu1 = BE_debug_signed(lane, 2, 201) + # dump_lf=False + # if dump_lf: + # lf_dmp_size = 2 + # else: + # lf_dmp_size = 7 + lf_dmp_size = 7 + smart_check_result = BE_debug2_signed(lane, 2, 350, lf_dmp_size, 5) + smart_check_ths = BE_debug2_signed(lane, 2, 700, lf_dmp_size, 12) + #smart_check1_ths = BE_debug2_signed(lane, 2, 800, lf_dmp_size, 12) + lf_result = BE_debug2_signed(lane, 2, 400, lf_dmp_size, 5) + + # if dump_lf: + # force_ths = BE_debug2_signed(lane, 2, 900, lf_dmp_size, 12) + # plus_margin = BE_debug2_signed(lane, 2, 1000, lf_dmp_size, 12) + # minus_margin = BE_debug2_signed(lane, 2, 1100, lf_dmp_size, 12) + em_debug = BE_debug2_signed(lane, 2, 470, lf_dmp_size, 3) + ffe_adapt = BE_debug2_signed(lane, 2, 600, 1, 4) + nbias_adapt = BE_debug1_signed(lane, 2, 640, 1) + if error_exit: + print ("Error exited") + print ("PAM4 state = 0x%04x" % pam4_state) + print ("restart count = %d" % restart_count) + if adapt_mode!=0: + fixed_f13 = BE_debug_signed(lane, 2, 40) + fixed_CTLE = BE_debug(lane, 2, 41) + fixed_Kp = BE_debug(lane, 2, 42) + fixed_agcgain = BE_debugs(lane, 2, range(43, 45)) + fixed_delta = BE_debug_signed(lane, 2, 45) + fixed_skef = BE_debug(lane, 2, 46) + fixed_edge = BE_debug(lane, 2, 47) + fixed_kf = BE_debug(lane, 2, 48) + fixed_sf = BE_debug(lane, 2, 49) + ctle_temp = BE_debugs(lane, 2, range(50, 53)) + fixed_ffe = BE_debugs_signed(lane, 2, range(53, 53+7)) + # Reconstruct CTLE table + fixed_ctle_all = (ctle_temp[0]<<32) | (ctle_temp[1]<<16) | ctle_temp[2] + fixed_ctle_table = [(fixed_ctle_all>>(i*6))&0x3f for i in range(7, -1, -1)] + fixed_ctle_table = [(i>>3, i&7) for i in fixed_ctle_table] + print ("Fixed settings:") + print (" F1/3 = %d" % fixed_f13) + print (" CTLE = %d" % fixed_CTLE) + print (" Kp = %d" % fixed_Kp) + print (" agcgain = %d, %d" % (fixed_agcgain[0], fixed_agcgain[1])) + print (" delta = %d" % fixed_delta) + print (" Skef = %d (%s)" % (fixed_skef&7, "enabled" if fixed_skef&8 else "disabled")) + print (" Edge = 0x%04x" % fixed_edge) + print (" Kf = %d, Sf = %d" % (fixed_kf, fixed_sf)) + print (" CTLE table =", fixed_ctle_table) + print (" FFE: K1=%d, K2=%d, K3=%d, K4=%d, S1=%d, S1=%d, nbias=%d" % (fixed_ffe[0], + fixed_ffe[1], fixed_ffe[2], fixed_ffe[3], fixed_ffe[4], fixed_ffe[5], fixed_ffe[6])) + if adapt_mode<1: + print ("AGCgain = %d, %d" % (agcgain1, agcgain2)) + print ("=== DC search 1 ===") + print (" agcgain record =", dc_search_agcgain[0]) + print (" AGCgain after DC search1 = %d, %d" % (agcgain1_dc1, agcgain2_dc1)) + print ("=== Channel analyzer === ") + print (" OF =", final_of) + print (" HF =", final_hf) + print (" Ratio = %d (%5.3f)" % (ratio, ratio/256.0)) + print (" CTLE search index = %d" % (agc_index)) + print ("=== DC search 2 === ") + print (" agcgain record =", dc_search_agcgain[1]) + print ("=== Smart check and linear fit ===") + print (" smart_chk=", smart_check_result) + print (" smart_check_ths=", smart_check_ths) + #print " smart_check1_ths=", smart_check1_ths + print (" LF_result =", lf_result) + # if dump_lf: + # print (" force_ths=", force_ths) + # print (" plus_margin=", plus_margin) + # print (" minus_margin=", minus_margin) + print (" EM_debug =", em_debug) + print (" Final F1/3 init = %d" % next_f13) + print ("=== CTLE search ===") + print (" CTLE before search =", ctle_record[0]) + print (" CTLE search ISI1 =", ctle_isi[0]) + print (" Freq accu before CTLE search =", ctle_freq_accu) + print (" Freq accu after CTLE search =", ctle_freq_accu1) + if (ctle_record[1]!=-1): + print (" CTLE after search 1 =", ctle_record[1]) + print (" CTLE search ISI2 =", ctle_isi[1]) + else: + print (" CTLE search2 is skipped") + print (" Final CTLE =", ctle) + print ("=== Delta search ===") + print (" Searched %d times. Search process:" % (delta_times0), delta_dump0) + print (" F(-1) =", fm1_dump0) + + print ("FFE adapt:") + for i in range(1): + print ("FFE adapt iteration %d: [%d, %d, %d, %d], nbias=%d" % (i, + ffe_adapt[i][0], ffe_adapt[i][1], ffe_adapt[i][2], ffe_adapt[i][3], nbias_adapt[i])) + + + # timers + timers = BE_debugs(lane, 2, range(10, 18)) + t0 = timers[1] + timers = [x-t0 for x in timers] + timers = [timers[0]] + [x if x>=0 else x+65536 for x in timers[1:]] + start_time, sd_time, ca_done_time, dc_search_time, link_time, ctle_search_time, delta_search_time, done_time = timers + print ("Timers: ") + print ("Start time: %d" % start_time) + print ("SD time: %d" % sd_time) + print ("CA done: %d" % ca_done_time) + print ("DC search: %d" % dc_search_time) + print ("Initial link: %d" % link_time) + print ("CTLE search: %d" % ctle_search_time) + print ("Delta search1: %d" % delta_search_time) + print ("Done: %d" % done_time) + +def pam4_dump_chip(lane): + #dac_val, en = dac_pam4(lane) + dac_val = dac(lane)[lane] + #ctle_val = ctle_pam4(lane) + ctle_val = ctle(lane)[lane] + #agcgain1, agcgain2 = agcgain(lane) + agcgain1, agcgain2, g3,g4 = dc_gain(lane)[lane] + + f1over3 = f13(lane)[lane] + print ("DAC = %d%s" % (dac_val, " (forced)" if en else "")) + print ("CTLE = %d" % ctle_val) + print ("AGCgain = %d, %d" % (agcgain1, agcgain2)) + print ("F1/3 = %d" % f1over3) +#################################################################################################### +def fw_adapt_dump(lane=None): + lanes = get_lane_list(lane) + for ln in lanes: + get_lane_mode(ln) + #c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + if lane_mode_list[ln] == 'pam4': + print("\n...Lane %d: PAM4 Adaptation Info...."%ln) + pam4_dump_fw_linear_fit(ln) + else: + print("\n...Lane %d: NRZ Adaptation Info...."%ln) + nrz_dump_fw(ln) +#################################################################################################### +def fw_info_dump(lane=None): + lanes = get_lane_list(lane) + for ln in lanes: + get_lane_mode(ln) + #c = Pam4Reg if lane_mode_list[ln] == 'pam4' else NrzReg + if lane_mode_list[ln] == 'pam4': + print("\n...Lane %d: PAM4 ISI and FFE Info\n"%ln) + pam4_info_fw(ln) + else: + print("\n*** Lane %d: ISI and FFE Info Available for PAM4 Lane Only! ***\n"%ln) +#################################################################################################### End of FW DUMP + +def bitmux_status(print_en=True, fifo_check_en=1): + bitmux_return_status=True + if fifo_check_en: # [Acceptable range for each FIFO pointer] + buf_ptr_min_limit = [1, 13] + buf_ptr_max_limit = [1, 13] + buf_ptr_del_limit = [0, 10] + else: + buf_ptr_min_limit = [0, 15] + buf_ptr_max_limit = [0, 15] + buf_ptr_del_limit = [0, 10] + + buf_type = ['--Split-->',' -->',' ---','<--Merge--'] + if print_en: print("\n -- BitMux Buffers: Min,Curr,Max,Delta") + for a_side_buf in range(0,4): + wreg([0x984d,[14,12]], a_side_buf) + for b_side_buf in range(4,8): + wreg([0x984d,[10,8]], b_side_buf) + buf_ptr_min = rreg([0x984e, [11,8]]) + buf_ptr_max = rreg([0x984e, [7,4]]) + buf_ptr_cur = rreg([0x984e,[15,12]]) + buf_ptr_del = buf_ptr_max - buf_ptr_min + + buf_ptr_min_status = 1 if buf_ptr_min_limit[0] <= buf_ptr_min <= buf_ptr_min_limit[1] else -1 + buf_ptr_max_status = 1 if buf_ptr_max_limit[0] <= buf_ptr_max <= buf_ptr_max_limit[1] else -1 + buf_ptr_del_status = 1 if buf_ptr_del_limit[0] <= buf_ptr_del <= buf_ptr_del_limit[1] else -1 + #buf_ptr_cur_status = 1 if buf_ptr_del_limit[0] <= buf_ptr_cur <= buf_ptr_del_limit[1] else -1 + status_flag = '<<' if buf_ptr_min_status<0 or buf_ptr_max_status<0 or buf_ptr_del_status<0 else ' ' + if status_flag=='<<': + bitmux_return_status=False + if print_en: print("\n A%d %s B%d :"%(a_side_buf,buf_type[b_side_buf-4],a_side_buf*2+(b_side_buf%2))), + if print_en: print("%3d %3d %3d %3d"%(buf_ptr_min,buf_ptr_cur,buf_ptr_max, buf_ptr_del)), + if print_en: print("%s"%(status_flag)), + if print_en: print("") + + return bitmux_return_status + +def fw_bitmux_status(print_en=True, fifo_check_en=1): + return_status=True + return_retries_config=0 + return_retries_runtime=0 + if fifo_check_en: # [Acceptable range for each FIFO pointer] + buf_ptr_min_limit = [2, 13] + buf_ptr_max_limit = [2, 13] + buf_ptr_del_limit = [1, 10] + else: + buf_ptr_min_limit = [0, 15] + buf_ptr_max_limit = [0, 15] + buf_ptr_del_limit = [0, 10] + + buf_type = ['--Split-->',' -->',' ---','<--Merge--'] + for a_side_buf in range(0,4): + + bitmux_state = BE_debug(a_side_buf, 4, 0) # Bitmux state (5 means 'Done with bitmux config') + bitmux_retries_config = BE_debug(a_side_buf, 4, 24) # Bitmux FIFO retry counter during bitmux config + bitmux_retries_runtime = BE_debug(a_side_buf, 4, 25) # Bitmux FIFO retry counter after bitmux config (runtime FIFO check) + + print("\n FW BitMux Buffers: Min,Max,Delta [Min,Max,Delta]"), + bitmux_state_char = '=' if bitmux_state==5 else '->' + print(",State%s %d" % (bitmux_state_char,bitmux_state)), + bitmux_retry_char = '=' if (bitmux_retries_config==0 and bitmux_retries_runtime==0) else '->' + print(",Retries%s %d %d" % (bitmux_retry_char, bitmux_retries_config,bitmux_retries_runtime)), + if bitmux_retries_config > return_retries_config: + return_retries_config = bitmux_retries_config + if bitmux_retries_runtime > return_retries_runtime: + return_retries_runtime = bitmux_retries_runtime + + for b_side_buf in range(4,8): + buf_ptr_max = BE_debug(a_side_buf, 4, (b_side_buf)+6) + buf_ptr_min = BE_debug(a_side_buf, 4, (b_side_buf)+10) + #buf_ptr_cur = 0 + buf_ptr_del = buf_ptr_max - buf_ptr_min + + buf_ptr_max_during_config = BE_debug(a_side_buf, 4, (b_side_buf)+26) + buf_ptr_min_during_config = BE_debug(a_side_buf, 4, (b_side_buf)+30) + buf_ptr_del_during_config = buf_ptr_max_during_config - buf_ptr_min_during_config + + buf_ptr_min_status = 1 if buf_ptr_min_limit[0] <= buf_ptr_min <= buf_ptr_min_limit[1] else -1 + buf_ptr_max_status = 1 if buf_ptr_max_limit[0] <= buf_ptr_max <= buf_ptr_max_limit[1] else -1 + buf_ptr_del_status = 1 if buf_ptr_del_limit[0] <= buf_ptr_del <= buf_ptr_del_limit[1] else -1 + #buf_ptr_cur_status = 1 if buf_ptr_del_limit[0] <= buf_ptr_cur <= buf_ptr_del_limit[1] else -1 + status_flag = '<<' if buf_ptr_min_status<0 or buf_ptr_max_status<0 or buf_ptr_del_status<0 else ' ' + + print("\n A%d %s B%d :"%(a_side_buf,buf_type[b_side_buf-4],a_side_buf*2+(b_side_buf%2))), + print("%3d %3d %3d "%(buf_ptr_min,buf_ptr_max,buf_ptr_del)), + print("[%3d %3d %3d ] "%(buf_ptr_min_during_config,buf_ptr_max_during_config, buf_ptr_del_during_config)), + print("%s"%(status_flag)), + if status_flag=='<<': + return_status=False + + + print("") + + return return_status, return_retries_config, return_retries_runtime +################################################################################################### +# +# GET ISI Residual Taps for NRZ +#################################################################################################### +def sw_nrz_isi(lane=None,print_en=0): + isi_tap_range=range(0,16) + lanes = get_lane_list(lane) + result={} + #fw_pause_en=1 + + # if fw_pause_en: + # if fw_loaded(print_en=0): + # fw_reg(addr=8,data=0x0000, print_en=0) # pause serdes FW + + for ln in lanes: + bp1_ori = rregBits(0x17d, [12, 8],ln) + bp1_en_ori = rregBits(0x17d, [15],ln) + wregBits(0x17d, [12, 8], 24,ln) + tap_list = [] + # wregBits(0x17d, [15], 0, ln) + # wregBits(0x10c, [15], 0, ln) + # wregBits(0x10c, [15], 1, ln) + + wregBits(0x17d, [15], 0, ln) + wregBits(0x10c, [15], 0, ln) + wregBits(0x10c, [15], 1, ln) + + for i in isi_tap_range: + wregBits(0x165, [4,1],i,ln) + time.sleep(0.01) + wregBits(0x17d, [15], 1, ln) + + wait_for_bp1_timeout=0 + while True: + if rregBits(0x18f, [15],ln): + break + else: + wait_for_bp1_timeout+=1 + if wait_for_bp1_timeout>5000: + if print_en==2:print (" Get Tap Value >>>>> Timed out 2 waiting for BP1") + break + plus = (rregBits(0x127, [3,0],ln)<<8) + rregBits(0x128, [15,8],ln) + minus = (rregBits(0x128, [7,0],ln)<<4) + rregBits(0x129, [15,12],ln) + + if (plus>2047): plus = plus - 4096 + if (minus>2047): minus = minus - 4096 + diff_margin = plus - minus + diff_margin_f = ((float(diff_margin & 0x0fff)/2048)+1)%2-1 + + if print_en==2: print ("\n%8d, %8d, %8d, %11d, %11.4f " % (i, plus, minus, diff_margin, diff_margin_f)) + tap_list.append(diff_margin) + + # wregBits(0x17d, [15], 0, ln) + # wregBits(0x10c, [15], 0, ln) + # wregBits(0x10c, [15], 1, ln) + + wregBits(0x17d, [15], 0, ln) + wregBits(0x10c, [15], 0, ln) + wregBits(0x10c, [15], 1, ln) + + wregBits(0x17d, [12, 8], bp1_ori, ln) + wregBits(0x17d, [15], bp1_en_ori, ln) + result[ln] = tap_list + + # if fw_pause_en: + # if fw_loaded(print_en=0): + # fw_reg(addr=8,data=0xffff, print_en=0) # un-pause serdes FW + return result +#################################################################################################### +def read_plus_minus_margin_nrz(lane=None): + lanes = get_lane_list(lane) + result = {} + for lane in lanes: + plus_0 = rregBits(0x11a,[15,4],lane) + plus_1 = (rregBits(0x11a,[3,0],lane)<<8)+rregBits(0x11b,[15,8],lane) + plus_2 = (rregBits(0x11b,[7,0],lane)<<4)+rregBits(0x11c,[15,12],lane) + plus_3 = rregBits(0x11c,[11,0],lane) + plus_4 = rregBits(0x11d,[15,4],lane) + plus_5 = (rregBits(0x11d,[3,0],lane)<<8)+rregBits(0x11e,[15,8],lane) + plus_6 = (rregBits(0x11e,[7,0],lane)<<4)+rregBits(0x11f,[15,12],lane) + plus_7 = rregBits(0x11f,[11,0],lane) + if plus_0 > 2047: plus_0 = plus_0 - 4096 + if plus_1 > 2047: plus_1 = plus_1 - 4096 + if plus_2 > 2047: plus_2 = plus_2 - 4096 + if plus_3 > 2047: plus_3 = plus_3 - 4096 + if plus_4 > 2047: plus_4 = plus_4 - 4096 + if plus_5 > 2047: plus_5 = plus_5 - 4096 + if plus_6 > 2047: plus_6 = plus_6 - 4096 + if plus_7 > 2047: plus_7 = plus_7 - 4096 + plus_margin = [plus_0,plus_1,plus_2,plus_3,plus_4,plus_5,plus_6,plus_7] + minus_0 = rregBits(0x120,[15,4],lane) + minus_1 = (rregBits(0x120,[3,0],lane)<<8)+rregBits(0x121,[15,8],lane) + minus_2 = (rregBits(0x121,[7,0],lane)<<4)+rregBits(0x122,[15,12],lane) + minus_3 = rregBits(0x122,[11,0],lane) + minus_4 = rregBits(0x123,[15,4],lane) + minus_5 = (rregBits(0x123,[3,0],lane)<<8)+rregBits(0x124,[15,8],lane) + minus_6 = (rregBits(0x124,[7,0],lane)<<4)+rregBits(0x125,[15,12],lane) + minus_7 = rregBits(0x125,[11,0],lane) + if minus_0 > 2047: minus_0 = minus_0 - 4096 + if minus_1 > 2047: minus_1 = minus_1 - 4096 + if minus_2 > 2047: minus_2 = minus_2 - 4096 + if minus_3 > 2047: minus_3 = minus_3 - 4096 + if minus_4 > 2047: minus_4 = minus_4 - 4096 + if minus_5 > 2047: minus_5 = minus_5 - 4096 + if minus_6 > 2047: minus_6 = minus_6 - 4096 + if minus_7 > 2047: minus_7 = minus_7 - 4096 + minus_margin = [minus_0,minus_1,minus_2,minus_3,minus_4,minus_5,minus_6,minus_7] + #print 'plus_margin=', plus_margin + #print 'minus_margin=',minus_margin + result[lane] = plus_margin, minus_margin + #else: + if result != {}: return result + +#################################################################################################### +def v_sensor(on_chip_sensor=1, print_en=1): + # function used to measure voltage + # if on chip sensor deactivated, use external multimeter (currently commented out) + Vsensor_base_addr = 0xB000 + + if on_chip_sensor==0: # Use Bench Multimeter connected to laptop through GPIB/USB + #v=mm.v + v=-1 + return v*1000 + #pass + else: # Use On-Chip Voltage Sensor + + chip.MdioWr((Vsensor_base_addr + 0x3f),0x010d) + chip.MdioWr((Vsensor_base_addr + 0xf6),0x1040) #sel[6:3]=8,pd[12]=1 + time.sleep(0.1) + chip.MdioWr((Vsensor_base_addr + 0xf6),0x0040) #sel[6:3]=8,pd[12]=0 + time.sleep(0.1) + chip.MdioWr((Vsensor_base_addr + 0xf6),0x0040) + time.sleep(0.1) + chip.MdioWr((Vsensor_base_addr + 0xf6),0x0440) #sel[6:3]=8,pd[12]=0;rstn[10]=1 + time.sleep(0.1) + chip.MdioWr((Vsensor_base_addr + 0xf6),0x0c40) #sel[6:3]=8,pd[12]=0;rstn[10]=1,run[11]=1 + time.sleep(0.1) + + k = 1 + for i in range(0,k): + chip.MdioWr((Vsensor_base_addr + 0xf6),0x0c40+(i<<3)) #sel[6:3]=8,pd[12]=0;rstn[10]=1,run[11]=1 + time.sleep(0.3) + rdatah = chip.MdioRd(Vsensor_base_addr + 0xf5) + rdatah = (rdatah& 0x0fff) + #if print_en: print "Voltage sensor register data:0x%04x" % (rdatah) + + rdata = ((rdatah+1.0)/ 256.0) * 1.224 + if print_en: + print ("On-Chip Vsense Voltage: %4.0f mV" % (rdata*1000.0)) + else: + return rdata*1000 + + +def Retimer_temp(): + for RT_address in range(0,10): + #chip.disconnect() + #chip.connect(dev_addr=1,phy_addr=RT_address,usb_sel=0) + temperature = temp_sensor(print_en=True) + print("SLice %2d temperature is %2.1f"%(RT_address,temperature)) + +def test_init(): # Add by Klaus + + for RT_address in range(0,10): + print("SLice "+ str(RT_address)) + #chip.disconnect() + #chip.connect(dev_addr=1,phy_addr=RT_address,usb_sel=0) + rx_monitor(rst=1) + +############################################################################## +# FW Exit Code Lane information +# +############################################################################## +def exit_codes(lane=range(16)): + #s=sel_slice(slice) + lanes = get_lane_list(lane) + + + print ("\n===================================================================================================="), + print ("\nLane | Exit Codes => "), + + for ln in lanes: + print ('\n %3d'%ln), + #lane_mode = s.get_lane_mode(ln) + #if s.lane_mode_list[ln] == 'pam4': + for index in range(100, 116): + exit_code = fw_debug_cmd(0, index, ln) # index=100 is the oldest record, 115 is newest + print ('-> %04X' % (exit_code)), + print ("\n====================================================================================================") + +def rxm(rst=0, fec_thresh=gFecThresh): + sel_slice(0);temp_sensor_fast();rx_monitor(rst=rst, fec_thresh=fec_thresh);sel_slice(1);rx_monitor(rst=rst, fec_thresh=fec_thresh) + +def kpp(val=None,val2=None): + sel_slice(0); + if val2!=None: ted(val2,print_en=0) + kp(val); + sel_slice(1); + if val2!=None: ted(val2,print_en=0) + kp(val) + +def regg(addr,val=None,lane=None,print_en=1): + reg(addr,val,lane,slice=[0,1],print_en=print_en) + +def auto_poll(): + sel_slice(0);auto_pol();sel_slice(1);auto_pol() + +def ser(): + sel_slice(0);fw_serdes_params();sel_slice(1);fw_serdes_params() + +def fecc(print_en=1): + sel_slice(0) + slice0= fec_status(print_en=print_en) + sel_slice(1) + slice1 = fec_status(print_en=print_en) + if not print_en: return slice0, slice1 + +def plll(tgt_pll=None, datarate=None, fvco=None, cap=None, n=None, div4=None, div2=None, refclk=None, frac_en=None, frac_n=None, lane=None): + sel_slice(0);pll(tgt_pll, datarate, fvco, cap, n, div4, div2, refclk, frac_en, frac_n, lane) + sel_slice(1);pll(tgt_pll, datarate, fvco, cap, n, div4, div2, refclk, frac_en, frac_n, lane) + +def lrr(): + sel_slice(0);lr();fw_adapt_wait(max_wait=12);sel_slice(1);lr();fw_adapt_wait(max_wait=12) + #sel_slice(0);fw_adapt_wait();sel_slice(1);fw_adapt_wait() + +def hist(hist_time=1, lane='all', slice=[0,1]): + #start_time=time.time() + result = fec_ana_hist(hist_time=hist_time,lane=lane,slice=slice) + #stop_time=time.time() + #print("\n...Total Histogram time: %2.2f sec"%(stop_time-start_time)) + print("\n\n...Lanes Failed: %d\n"%(result)) + +def fw_stop(): + fw_reg_wr(128,0) + +def fw_start(): + fw_reg_wr(128,0xFFFF) +def cameo_400G_card_8(): + libcameo.cameo_switch_phy_id(1,8) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,8) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) +def cameo_400G_card_7(): + libcameo.cameo_switch_phy_id(1,7) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,7) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) +def cameo_400G_card_6(): + libcameo.cameo_switch_phy_id(1,6) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,6) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + +def cameo_400G_card_5(): + libcameo.cameo_switch_phy_id(1,5) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,5) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=7) +def cameo_400G_card_4(): + libcameo.cameo_switch_phy_id(1,4) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,4) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=7) + +def cameo_400G_card_3(): + libcameo.cameo_switch_phy_id(1,3) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,3) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=7) + +def cameo_400G_card_2(): + libcameo.cameo_switch_phy_id(1,2) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,2) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) +def cameo_400G_card_1(): + libcameo.cameo_switch_phy_id(1,1) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,1) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=2) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=6) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=7) + + + +def cameo_eq_setting_400G(card): + global gCameo400G_EQ + max_count = 32 + count = 0 + for first_col in gCameo400G_EQ: + for item in first_col: + if item['card'] == card : + cameo_change_chip_card(item['chip'],card) + sel_slice(item['slice']) + tx_taps(tap1=item['tap1'],tap2=item['tap2'] ,tap3=item['tap3'] ,tap4=item['tap4'],tap5=item['tap5'],lane=item['lane']) + count = count + 1 + if count == max_count: + return +def cameo_100G_card_8(): + libcameo.cameo_switch_phy_id(1,8) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,8) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + + libcameo.cameo_switch_phy_id(3,8) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,8) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_100G_card_7(): + libcameo.cameo_switch_phy_id(1,7) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,7) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + + libcameo.cameo_switch_phy_id(3,7) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,7) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_100G_card_6(): + libcameo.cameo_switch_phy_id(1,6) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,6) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + + libcameo.cameo_switch_phy_id(3,6) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,6) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_100G_card_5(): + libcameo.cameo_switch_phy_id(1,5) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,5) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(3,5) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,5) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_100G_card_4(): + libcameo.cameo_switch_phy_id(1,4) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,4) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + + libcameo.cameo_switch_phy_id(3,4) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,4) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=18,tap4=9,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_100G_card_3(): + libcameo.cameo_switch_phy_id(1,3) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,3) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + + libcameo.cameo_switch_phy_id(3,3) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,3) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-4,tap3=19,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_100G_card_2(): + libcameo.cameo_switch_phy_id(1,2) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,2) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(3,2) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,2) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_100G_card_1(): + libcameo.cameo_switch_phy_id(1,1) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(2,1) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + + + libcameo.cameo_switch_phy_id(3,1) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + libcameo.cameo_switch_phy_id(4,1) + + + sel_slice(1) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) + + + sel_slice(0) + + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=0) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=1) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=2) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=3) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=4) + tx_taps(tap1=0,tap2=-3,tap3=20,tap4=8,tap5=0,lane=5) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=6) + tx_taps(tap1=0,tap2=0 ,tap3=0 ,tap4=0,tap5=0,lane=7) +def cameo_eq_setting_100G(card): + global gCameo100G_EQ + max_count = 64 + count = 0 + for first_col in gCameo100G_EQ: + for item in first_col: + if item['card'] == card : + cameo_change_chip_card(item['chip'],card) + sel_slice(item['slice']) + tx_taps(tap1=item['tap1'],tap2=item['tap2'] ,tap3=item['tap3'] ,tap4=item['tap4'],tap5=item['tap5'],lane=item['lane']) + count = count + 1 + if count == max_count: + return + + +def cameo_main_100G(card,A_lanes=[0,1,4,5],gearbox_type='100G-1', fec_b_bypass=False): + #gSlice=0 + #slices=[0,1] + global gCard + gCard = card + cameo_drv_open() + + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + + if (mdio_status == MDIO_CONNECTED): + sel_slice(0) + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. %d\n" % num) + fw_load(gFwFileName,slice=[0,1]) + + sel_slice(0) + soft_reset() + sel_slice(1) + soft_reset() + config_baldeagle_gearbox(slice=[0,1], A_lanes=A_lanes,gearbox_type=gearbox_type, gearbox_by_fw=True, fec_b_bypass=fec_b_bypass) + else: + print ("Failed to access MDIO") + + cameo_eq_setting_100G(card); + cameo_drv_close() + res = cameo_get_result(card,'GearBox100G') + cameo_write_result (card,res) + return res +def cameo_main_50G_gearbox(card): + #gSlice=0 + #slices=[0,1] + global gCard + gCard = card + cameo_drv_open() + + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + + if (mdio_status == MDIO_CONNECTED): + sel_slice(0) + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded. %d\n" % num) + fw_load(gFwFileName,slice=[0,1]) + + sel_slice(0) + soft_reset() + sel_slice(1) + soft_reset() + config_baldeagle_gearbox(slice=[0,1], A_lanes=[0,1,4,5],gearbox_type='50G', gearbox_by_fw=True, fec_b_bypass=False) + else: + print ("Failed to access MDIO") + + cameo_eq_setting_100G(card); + cameo_drv_close() + res = cameo_get_result(card,'GearBox50G') + cameo_write_result (card,res) + return res +def cameo_main_400G(card,mode='retimer_pam4'): + gSlice=0 + #slices=[0,1] + global gCard + gCard = card + cameo_drv_open() + + for num in range(1,3): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + sel_slice(0) + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded.\n") + fw_load(gFwFileName,slice=[0,1]) + sel_slice(0) + soft_reset() + sel_slice(1) + soft_reset() + config_baldeagle(slice=[0,1], mode='retimer_pam4',input_mode='ac',lane=None,cross_mode=False) + RxPolarityMap.append([]); RxPolarityMap[0]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] + TxPolarityMap.append([]); TxPolarityMap[0]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] + RxPolarityMap.append([]); RxPolarityMap[1]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] + TxPolarityMap.append([]); TxPolarityMap[1]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] + sel_slice(0) + for ln in gLane: + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + sel_slice(1) + for ln in gLane: + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + + else: + print ("Failed to access MDIO") + + cameo_eq_setting_400G(card) + cameo_drv_close() + res = cameo_get_result(card,'RetimerPam4') + cameo_write_result (card,res) + return res +def cameo_main_loopback(card,mode='LoopbackPam4',speed='100G'): + gSlice=0 + #slices=[0,1] + global gCard + gCard = card + cameo_drv_open() + + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + sel_slice(0) + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded.\n") + fw_load(gFwFileName,slice=[0,1]) + sel_slice(0) + soft_reset() + sel_slice(1) + soft_reset() + config_baldeagle(slice=[0,1], mode='LoopbackPam4',input_mode='ac',lane=None,cross_mode=False) + + sel_slice(0) + if speed == '400G': + print("\n*** 400G change polarity mapping\n") + RxPolarityMap.append([]); RxPolarityMap[0]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] + TxPolarityMap.append([]); TxPolarityMap[0]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] + RxPolarityMap.append([]); RxPolarityMap[1]=[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0] + TxPolarityMap.append([]); TxPolarityMap[1]=[1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1] + sel_slice(0) + for ln in gLane: + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + sel_slice(1) + for ln in gLane: + pol(TxPolarityMap[gSlice][ln],RxPolarityMap[gSlice][ln],ln,0) + + if speed == '400G': + cameo_eq_setting_400G(card) + elif speed == '100G': + cameo_eq_setting_100G(card) + cameo_drv_close() + #return cameo_get_result(card,'RetimerPam4') +def cameo_main_10Gx2_retimer(card): + #gSlice=0 + #slices=[0,1] + global gCard + gCard = card + cameo_drv_open() + + for num in range(1,5): + cameo_change_chip_card(num,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + sel_slice(0) + if not fw_loaded(print_en=0): + print("\n*** No FW Loaded.\n") + fw_load(gFwFileName,slice=[0,1]) + sel_slice(0) + soft_reset() + sel_slice(1) + soft_reset() + config_baldeagle(slice=[0,1], mode='nrz-retimer-10G',input_mode='ac',lane=None,cross_mode=False) + else: + print ("Failed to access MDIO") + + cameo_eq_setting_100G(card) + cameo_drv_close() + res = cameo_get_result(card,'RetimerNrz') + cameo_write_result (card,res) + return res +def cameo_rx_monitor(card): + cameo_drv_open() + slice=[0,1] + slices = get_slice_list(slice) + for chip in range(1,5): + cameo_change_chip_card(chip,card) + mdio_status = get_mdio_status() + + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + print("+-------------------------------+" ) + print("| Card %02d Chip %02d Sl %02d |" % (card,chip,slice_num)) + print("+-------------------------------+" ) + rx_monitor() + cameo_drv_close() +def cameo_get_result(card,mode): + cameo_drv_open() + slice=[0,1] + slices = get_slice_list(slice) + check_result = True + card_exist = False + for chip in range(1,5): + cameo_change_chip_card(chip,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + card_exist = True + if card_exist is True: + if mode.upper() == 'GEARBOX100G': + config_lane = [0,1,4,5,8,9,10,11,12,13,14,15] + elif mode.upper() == 'GEARBOX50G': + config_lane = [0,1,4,5,8,9,10,11,12,13,14,15] + elif mode.upper() == 'RETIMERPAM4': + config_lane = get_lane_list('all') + elif mode.upper() == 'RETIMERNRZ': + config_lane = get_lane_list('all') + else: + print ("Invalid mode! Mode should be RetimerPam4,GearBox100G,GearBox50G, RetimerNrz") + return False + for chip in range(1,5): + cameo_change_chip_card(chip,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + result = fw_slice_params(lane=config_lane,slice=None,print_en=0) + if not fw_loaded(print_en=0): + #print ("\n...Error in 'fw_slice_params': Slice %d has no FW!"%slice_num), + check_result = False + else: + for ln in config_lane: + #print result[ln] + #print("+-------------------------------+" ) + #print result[ln][0] + #print result[ln][3] + #print '\n' + if mode.upper() not in result[ln][0].upper() : + check_result = False + else: + check_result = False + cameo_change_chip_card(1,card) + #fw_slice_params(lane=config_lane,slice=0,print_en=1) + cameo_drv_close() + #print check_result + return check_result +def optic_mode_print(lane=None): + + optic_fw_reg_addr = 20 + #optic_mode_reg_val = fw_reg_rd(optic_fw_reg_addr) + + #optic_en_list = ['ON','EN','OPTIC'] + #optic_dis_list = ['OFF','DIS','COPPER'] + mode_list= ['dis','EN'] + + #lanes = get_lane_list(lane) + result = {} + + print("-----------------------------------"), + print(" FW Optic Mode Status Per Lane"), + print(" -----------------------------------"), + print("\n Lane:"), + + for ln in range(16): + print(" %4s" %(lane_name_list[ln])), + + for ln in range(16): # Read relavant Registers + lane_optic_mode =(fw_reg_rd(optic_fw_reg_addr) >> ln) & 1 + result[ln]=lane_optic_mode + + + print("\n FW Optic Mode :"), + for ln in range(16): + print(" %4s" %(mode_list[result[ln]])), +# +# Reg 20 is optical mode register +# Bit0 = lane0 +# 0xFF00 is lane 8-15 +# tx_taps do not need to change by mode. +# +def cameo_set_Bside_optical_mode(card): + + cameo_drv_open() + slice=[0,1] + slices = get_slice_list(slice) + + for chip in range(1,5): + cameo_change_chip_card(chip,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + print("\n\n") + print("Card %02d Chip %02d Sl %02d" % (card,chip,slice_num)) + if fw_loaded(print_en=0): + fw_reg_wr(20,0xFF00) + lane_reset() + optic_mode_print() + cameo_drv_close() +def cameo_set_Bside_copper_mode(card): + + cameo_drv_open() + slice=[0,1] + slices = get_slice_list(slice) + for chip in range(1,5): + cameo_change_chip_card(chip,card) + mdio_status = get_mdio_status() + if (mdio_status == MDIO_CONNECTED): + for slice_num in slices: + sel_slice(slice_num) + print("\n\n") + print("Card %02d Chip %02d Sl %02d" % (card,chip,slice_num)) + if fw_loaded(print_en=0): + fw_reg_wr(20,0x0000) + lane_reset() + optic_mode_print() + cameo_drv_close() +def cameo_write_result(card,result): + + if result is True: + result_str = "Card " + str(card) + " : Init Success.\n" + else: + result_str = "Card " + str(card) + " : Init Failed.\n" + + resultfilename = "card_" + str(card) + "_status" + f = open(resultfilename,'w') + f.write(result_str) + f.close +def cameo_lib_set_taps(card,speed): + max_count = 64 + count = 0 + #MAX_LANE_NUM = 16 + #MAX_PARAM_NUM = 5 + # if speed == '400g': + # MAX_CHIP = 2 + # elif speed == '100g': + # MAX_CHIP = 4 + for first_col in gCameo100G_EQ: + for item in first_col: + if item['card'] == card : + cameo_change_chip_card(item['chip'],card) + sel_slice(item['slice']) + tx_taps(tap1=item['tap1'],tap2=item['tap2'] ,tap3=item['tap3'] ,tap4=item['tap4'],tap5=item['tap5'],lane=item['lane']) + count = count + 1 + if count == max_count: + return + + # for i in range(MAX_LANE_NUM): + # for j in range(MAX_PARAM_NUM): + +#################################################################################################### +#################################################################################################### +# +# END of all Bald Eagle Scripts +# +# Every time executing this file: +# Call the following functions first to establish basic connection +# or to define certain global reference parameters +# +#################################################################################################### +#################################################################################################### +if __name__ == '__main__': + filename = ' ' + #filename=sys.argv[0] + if len(sys.argv)>1: + var1=sys.argv[1] + if len(sys.argv)>2: + var2=sys.argv[2] + if len(sys.argv)>3: + var3=sys.argv[3] + + if len(sys.argv) == 3 and var1 =='fw_load': +# gFwFileName = fw_path + '/BE2.fw.2.18.43.bin' + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_fw_load_2_card(card) + elif len(sys.argv) == 3 and var1 =='rx_monitor': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_rx_monitor(card) + elif len(sys.argv) == 3 and var1 =='fw_unload': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_fw_unload(card) + elif len(sys.argv) == 2 and var1 =='fw_status': + cameo_fw_load_status_all() + elif len(sys.argv) == 2 and var1 =='fw_unload': + cameo_fw_unload_all() + elif len(sys.argv) == 3 and var1 == '100G': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_100G(card) + elif len(sys.argv) == 3 and var1 == '100G-LT': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_100G(card,gearbox_type='100G-1-LT') + elif len(sys.argv) == 3 and var1 == '400G': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_400G(card) + elif len(sys.argv) == 3 and var1 == '400G-LT': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_400G(card,mode='retimer_pam4-LT') + elif len(sys.argv) == 3 and var1 == 'optical_mode': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_set_Bside_optical_mode(card) + elif len(sys.argv) == 3 and var1 == 'copper_mode': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_set_Bside_copper_mode(card) + elif len(sys.argv) == 3 and var1 == '10G_retimer': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_10Gx2_retimer(card) + elif len(sys.argv) == 3 and var1 == '50G_gearbox': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_50G_gearbox(card) + elif len(sys.argv) == 3 and var1 == 'lb_100G': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_loopback(card) + elif len(sys.argv) == 3 and var1 == 'lb_400G': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + cameo_main_loopback(card,mode='LoopbackPam4',speed='400G') + elif len(sys.argv) == 4 and var1 == 'result': + card=int(var2) + if card>8 or card<1: + print ("card must be 1-8") + get_result = cameo_get_result(card,var3) + print (get_result) + else: + print ("usage: %s fw_load [card]" % filename) + print (" %s 100G [card]" % filename) + print (" %s 400G [card]" % filename) + print (" %s fw_status" % filename) + print (" %s fw_unload" % filename) + print (" %s fw_unload [card]" % filename) + print (" %s rx_monitor [card]" % filename) + print (" %s optical_mode [card]" % filename) + print (" %s copper_mode [card]" % filename) + print (" %s 10G_retimer [card]" % filename) + print (" %s 50G_gearbox [card]" % filename) + print (" %s lb_100G [card]" % filename) + print (" %s lb_400G [card]" % filename) + print (" %s result [card] [mode]" % filename) + + + +#################################################################################################### +#################################################################################################### diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_eagle_reg.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_eagle_reg.py new file mode 100755 index 0000000000..d478a5d13b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_eagle_reg.py @@ -0,0 +1,239 @@ +## global +chip_name = 'Bald_Eagle' +chip_rst_addr = [0x9802, [11,0]] +chip_soft_rst_val = 0x888 +chip_logic_rst_val = 0x777 +chip_cpu_rst_val = 0xAAA +chip_reg_rst_val = 0x999 + +### Firmware related registers +fw_load_magic_word_addr = [0x9805, [15,0]] +fw_load_magic_word = 0x6A6A + +fw_unload_addr = [0x9805, [15,0]] +fw_unload_word = 0xFFF0 + +fw_cmd_addr = [0x9806, [15,0]] +fw_cmd_detail_addr = [0x9807, [15,0]] +fw_cmd_status_addr = [0x98C7, [15,0]] +fw_opt_done_addr = [0x98C9, [15,0]] + +fw_hash_read_en_addr = [0x9806, [15,0]] +fw_hash_word_hi_addr = [0x9806, [7,0]] +fw_hash_word_lo_addr = [0x9807, [15,0]] +fw_hash_read_en = 0xF000 +fw_hash_read_status = 0x0F00 + +fw_crc_read_en_addr = [0x9806, [15,0]] +fw_crc_word_addr = [0x9807, [15,0]] +fw_crc_read_en = 0xF001 +fw_crc_read_status = 0x0F00 + +fw_date_read_en_addr = [0x9806, [15,0]] +fw_date_word_addr = [0x9807, [15,0]] +fw_date_read_en = 0xF002 +fw_date_read_status = 0x0F00 + +fw_ver_read_en_addr = [0x9806, [15,0]] +fw_ver_word_hi_addr = [0x9806, [7,0]] +fw_ver_word_lo_addr = [0x9807, [15,0]] +fw_ver_read_en = 0xF003 +fw_ver_read_status = 0x0F00 + +fw_watchdog_timer_addr = [0x98C6, [15,0]] + +fw_halt_addr = [0x9805, [15,0]] +fw_halt_en = 0xD000 +fw_halt_status = 0x0D00 + +fw_config_lane_off = 0x9000 +fw_config_lane_active = 0x8000 +fw_config_lane_status = 0x0800 + +fw_debug_info_cmd = 0xb000 +fw_debug_info_status = 0x0b00 + +## TOP PLL A (0x9500) & TOP PLL B (0x9600) +top_pll_en_refclk_addr = [0x9500, [7]] +top_pll_pu_addr = [0x9501, [2]] +top_pll_div4_addr = [0x9500, [6]] +top_pll_n_addr = [0x9507, [12,4]] +top_pll_lvcocap_addr = [0x9501, [12,6]] +top_pll_refclk_div_addr = [0x9513, [15,7]] +top_pll_div2_addr = [0x9513, [6]] + +## Eagle PLL RX +rx_pll_pu_addr = [0x1FD, [0]] +rx_pll_div4_addr = [0x1FF, [6]] +rx_pll_n_addr = [0x1FD, [15,7]] +rx_pll_lvcocap_addr = [0x1F5, [15,9]] +rx_pll_div2_addr = [0x1F5, [8]] +rx_pll_frac_n_addr = [0x1F1, [15,0]] +rx_pll_frac_order_addr = [0x1F0, [15,14]] +rx_pll_frac_en_addr = [0x1F0, [13]] + +rx_en_vcominbuf_addr = [0x1e7, [11]] +rx_vagccom_addr = [0x1e7, [10,8]] +rx_vagccom2_addr = [0x1e7, [7,5]] +rx_vgavdsat_addr = [0x1e6, [15,12]] +rx_vrefagcreg_addr = [0x1e6, [5,3]] +rx_vref2agcreg_addr = [0x1e6, [2,0]] +rx_vcomrefsel_ex_addr = [0x1dd, [9]] +rx_skef_en_addr = [0x1dd, [8]] +rx_skef_degen_addr = [0x1dd, [7,5]] +rx_skef_addcap_addr = [0x1dd, [4,2]] +rx_agcgain1_addr = [0x1d4, [15,9]] # 7-bit gray coded +rx_agcgain2_addr = [0x1d4, [8,4]] # 5-bit gray coded + +## Eagle ana reg +tx_pll_pu_addr = [0x0FE, [0]] +tx_pll_div2_addr = [0x0FF, [1]] +tx_pll_div4_addr = [0x0FF, [0]] +tx_pll_n_addr = [0x0fe, [15,7]] +tx_pll_lvcocap_addr = [0x0db, [14,8]] +tx_pll_frac_n_addr = [0x0D8, [15,0]] +tx_pll_frac_order_addr = [0x0D7, [15,14]] +tx_pll_frac_en_addr = [0x0D7, [13]] + +rx_edge1_addr = [0x0ed, [15,12]] +rx_edge2_addr = [0x0ed, [11,8]] +rx_edge3_addr = [0x0ed, [7,4]] +rx_edge4_addr = [0x0ed, [3,0]] + +## Phoenix + Eagle tx digital top +tx_test_patt_sc_addr = [0x0a0, [15]] +tx_prbs_clk_en_addr = [0x0a0, [14]] +tx_test_patt_en_addr = [0x0a0, [13]] +tx_prbs_en_addr = [0x0a0, [11]] +tx_prbs_1b_err_addr = [0x0a0, [10]] +tx_prbs_patt_sel_addr = [0x0a0, [9,8]] # nrz:00=prbs9, 01=prbs15, 10=prbs23, 11=prbs31 # pam4:00=prbs9, 01=prbs13, 10=prbs15, 11=prbs31 +tx_pol_addr = [0x0a0, [5]] # analog output flip +tx_patt_mode_addr = [0x0a0, [3,2]] # 00=pattern_mem, 01=jp03b, 10=linear pattern +tx_test_patt4_addr = [0x0A1, [15,0]] # msb +tx_test_patt3_addr = [0x0A2, [15,0]] +tx_test_patt2_addr = [0x0A3, [15,0]] +tx_test_patt1_addr = [0x0A4, [15,0]] # lsb +tx_tap1_addr = [0x0A5, [15,8]] +tx_tap2_addr = [0x0A7, [15,8]] +tx_tap3_addr = [0x0A9, [15,8]] +tx_tap4_addr = [0x0ab, [15,8]] +tx_tap5_addr = [0x0ad, [15,8]] +tx_tap6_addr = [0x0b1, [15,12]] +tx_tap7_addr = [0x0b1, [11,8]] +tx_tap8_addr = [0x0b1, [7,4]] +tx_tap9_addr = [0x0b1, [3,0]] +tx_tap10_addr = [0x0b2, [15,12]] +tx_tap11_addr = [0x0b2, [11,8]] +tx_taps_sum_limit = 31 +tx_msb_swap_addr = [0x0af, [10]] +tx_gray_en_addr = [0x0af, [9]] +tx_precoder_en_addr = [0x0af, [8]] +tx_taps_hf_addr = [0x0af, [5,1]] +tx_prbs_1b_err_nrz_addr = [0x0b0, [10]] + +## PAM4 / NRZ / NRZ-HalfRate Parameters +## Need these 6 in both Eagle/Phoenix Register definition files +rx_pam4_en_addr = [0x041,[15]] +tx_prbs_clk_en_nrz_addr = [0x0b0,[14]] +tx_prbs_en_nrz_addr = [0x0b0,[11]] +tx_nrz_mode_addr = [0x0b0, [1]] +tx_mode10g_en_addr = [0x0b0, [0]] +rx_mode10g_addr = [0x179, [0]] +rx_ted_en_addr = [0x079, [13]] + +## Eagle state machine +rx_cntr_target_addr = [0x102, [15,4]] +rx_delta_adapt_en_addr = [0x101, [14]] +rx_timer_meas_s6_addr = [0x108, [7,4]] +rx_em_en_addr = [0x109, [15]] +rx_max_eye_delta_owen_addr = [0x10a, [14]] +rx_delta_owen_addr = [0x10a, [12]] +rx_bp1_en_addr = [0x10b, [15]] +rx_bp1_st_addr = [0x10b, [12,8]] +rx_bp2_en_addr = [0x10b, [7]] +rx_bp2_st_addr = [0x10b, [4,0]] +rx_sm_cont_addr = [0x10c, [15]] +rx_acal_done_ow_addr = [0x10c, [0]] +rx_acal_done_owen_addr = [0x10c, [1]] +rx_bp1_reached_addr = [0x10d, [15]] +rx_bp2_reached_addr = [0x10d, [14]] +rx_state_addr = [0x10d, [12,8]] +rx_delta_addr = [0x10d, [6,0]] +rx_state_cntr_addr = [0x112, [15,0], 0x113, [15,0]] +rx_fixed_patt_plus_margin_addr = [0x127, [3,0], 0x128, [15,8]] +rx_fixed_patt_minus_margin_addr = [0x128, [7,0], 0x129, [15,12]] +rx_max_eye_margin_addr = [0x129, [11,0]] +rx_em_addr = [0x12a, [11,0]] +rx_max_eye_delta_addr = [0x12b, [14,8]] +rx_f1_addr = [0x12b, [6,0]] +rx_f2_addr = [0x12c, [14,8]] +rx_f3_addr = [0x12c, [6,0]] +rx_kp_addr = [0x12e, [14,12]] +rx_kf_addr = [0x12e, [8,7]] +rx_sd_addr = [0x12e, [3]] +rx_rdy_addr = [0x12e, [2]] +rx_kp_owen_addr = [0x13b, [15]] +rx_kp_ow_addr = [0x13b, [14,12]] +rx_ktheta_owen_addr = [0x13b, [10]] +rx_ktheta_ow_addr = [0x13b, [9,8]] +rx_kf_owen_addr = [0x13b, [7]] +rx_kf_ow_addr = [0x13b, [6,5]] +rx_acal_clk_en_owen_addr = [0x145, [15]] +rx_acal_clk_en_ow_addr = [0x145, [7]] +rx_acal_start_ow_addr = [0x144, [7]] +rx_acal_start_owen_addr = [0x144, [15]] +rx_of_period_addr = [0x14a, [11,7]] +rx_hf_period_addr = [0x14c, [12,8]] +rx_of_ths_addr = [0x14a, [6,0]] +rx_hf_ths_addr = [0x14c, [6,0]] +rx_of_cntr_upper_limit_addr = [0x148, [15,0]] +rx_of_cntr_lower_limit_addr = [0x149, [15,0]] +rx_hf_cntr_target_addr = [0x14b, [15,0]] +rx_agc_ow_addr = [0x14e, [13,11]] +rx_agc_owen_addr = [0x14d, [15]] +rx_delta_ow_addr = [0x15f, [6,0]] +rx_dac_ow_addr = [0x14f, [15,12]] +rx_dac_owen_addr = [0x14c, [7]] +rx_max_eye_delta_ow_addr = [0x15f, [14,8]] +rx_dac_addr = [0x17f, [15,12]] +rx_restart_cntr_addr = [0x17f, [4,0]] +rx_lane_rst_addr = [0x181, [11]] + + +# rx_fixed_patt_b0_addr = [0x7, [2,1]] +# rx_fixed_patt_dir_addr = [0x7, [0]] +# rx_iter_s6_addr = [0x9, [3,0]] +# rx_margin_patt_dis_owen_addr = [0x21, [3]] +# rx_margin_patt_dis_ow_addr = [0x21, [2]] +# rx_plus_margin_addr = [0x32, [15,4]] +# rx_minus_margin_addr = [0x32, [3,0], 0x33, [15,8]] +# rx_c_plus_margin_addr = [0x33, [7,0], 0x34, [15,12]] +# rx_c_minus_margin_addr = [0x34, [11,0]] +# rx_pam4_tap_addr = [0x40,[6,0]] +# rx_mu_ow_addr = [0x87, [10,9]] +# rx_mu_owen_addr = [0x87, [11]] +# rx_pam4_dfe_sel_addr = [0x88, [7,4]] # Ths_q_sel +# rx_pam4_dfe_rd_addr = [0x2f, [15,4]] # read_Ths_q + +## Eagle RX digital top +rx_err_cntr_rst_addr = [0x161, [15]] # use sync err cntr +rx_pol_addr = [0x161, [14]] # firmware flip [8], customer flip [7] +rx_prbs_checker_pu_addr = [0x161, [10]] # use sync checker +rx_prbs_mode_addr = [0x161, [13,12]] +rx_theta_update_mode_addr = [0x165, [7,5]] +rx_fixed_patt_mode_addr = [0x165, [4,1]] +rx_err_cntr_msb_addr = [0x166, [15,0]] +rx_err_cntr_lsb_addr = [0x167, [15,0]] +rx_freq_accum_addr = [0x173, [10,0]] +rx_top_rotator_en_addr = [0x175, [15]] +rx_agc_map0_addr = [0x176, [15,0]] # highest peaking +rx_agc_map1_addr = [0x177, [15,0]] +rx_agc_map2_addr = [0x178, [15,0]] # lowest peaking +rx_bb_en_addr = [0x179, [6]] +rx_patt_cnt_addr = [0x174, [15,0]] + +# ## FFE related registers +rx_ffe_sf_msb_addr = [0x1e1, [15,12]] +rx_ffe_sf_lsb_addr = [0x1e1, [7,4]] + +rx_f1over3_addr = [0x004,[11,5]] \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_eagle_reg.pyc b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/credo_baldeagle/python_wheel/baldeagle_eagle_reg.pyc deleted file mode 100644 index a6e5aab9519df09c0782381b4a7faf8f30025024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8360 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 diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/Makefile b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/Makefile index e509f75c25..93493b027a 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/Makefile +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/Makefile @@ -1 +1,4 @@ obj-m := x86-64-cameo-esc600-128q.o nct7511.o mcp3425_smbus.o at24_smbus.o zrh2800k2.o tps40425.o powr1014.o phy_cpld640.o lscpcie2.o +x86-64-cameo-esc600-128q-objs := x86-64-cameo-esc600-128q-common.o x86-64-cameo-esc600-128q-sys.o \ +x86-64-cameo-esc600-128q-led.o x86-64-cameo-esc600-128q-fan.o x86-64-cameo-esc600-128q-power.o \ +x86-64-cameo-esc600-128q-thermal.o \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/pmbus.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/pmbus.h index 4efa2bd4f6..8811564915 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/pmbus.h +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/pmbus.h @@ -341,12 +341,12 @@ enum pmbus_sensor_classes { #define PMBUS_HAVE_STATUS_VMON BIT(19) enum pmbus_data_format { linear = 0, direct, vid }; -enum vrm_version { vr11 = 0, vr12, vr13 }; +enum vrm_version { vr11 = 0, vr12, vr13, imvp9, amd625mv }; struct pmbus_driver_info { int pages; /* Total number of pages */ enum pmbus_data_format format[PSC_NUM_CLASSES]; - enum vrm_version vrm_version; + enum vrm_version vrm_version[PMBUS_PAGES]; /* vrm version per page */ /* * Support one set of coefficients for each sensor type * Used for chips providing data in direct mode. diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.c new file mode 100644 index 0000000000..11166a68eb --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.c @@ -0,0 +1,382 @@ +/* An hwmon driver for Cameo ESC600-128Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esc600-128q.h" +#include "x86-64-cameo-esc600-128q-common.h" + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x30, 0x31, 0x32, I2C_CLIENT_END }; +static int debug = 0; + + +/* i2c_client Declaration */ +struct i2c_client *Cameo_CPLD_30_client; //0x30 CPLD ,XO2-2000HC-4FTG256C +struct i2c_client *Cameo_CPLD_31_client; //0x31 CPLD ,XO2-7000HC-4TG144C +struct i2c_client *Cameo_CPLD_33_client; //0x33 I/O Board CPLD ,XO2-640 +struct i2c_client *Cameo_CPLD_35_client; //0x35 CPLD ,XO2-2000HC-4FTG256C +struct i2c_client *Cameo_Extpand_20_client; //0x20 I/O Extpander ,PCA9534PW +struct i2c_client *Cameo_Extpand_21_client; //0x21 I/O Extpander ,PCA9534PW +struct i2c_client *Cameo_BMC_14_client; //0x14 BMC ,Aspeed +/* end of i2c_client Declaration */ + +/* register offset define */ +#define BMC_EN_REG 0xA3 +/* end of register offset define */ + +/* common function */ +int bmc_enable(void) +{ + if ((i2c_smbus_read_byte_data(Cameo_CPLD_31_client, BMC_EN_REG) & BIT_0_MASK) == 0x01) + { + return ENABLE; + } + else + { + return DISABLE; + } +} + +int read_8bit_temp(u8 sign,u8 value) +{ + int result = 0; + if(sign) + { + //printf("read_8bit_temp UP %d\n", value & 0x80); + value = ~(value)+1; + result = value; + return result; + } + else + { + //printf("read_8bit_temp DOWN %d\n", value & 0x80); + result = value; + return result; + } +} + +/* end of common function*/ + +static int Cameo_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + struct Cameo_i2c_data *Cameo_CPLD_30_data; //0x30 CPLD ,XO2-2000HC-4FTG256C + struct Cameo_i2c_data *Cameo_CPLD_31_data; //0x31 CPLD ,XO2-7000HC-4TG144C + struct Cameo_i2c_data *Cameo_CPLD_33_data; //0x33 I/O Board CPLD ,XO2-640 + struct Cameo_i2c_data *Cameo_CPLD_35_data; //0x35 CPLD ,XO2-2000HC-4FTG256C + struct Cameo_i2c_data *Cameo_Extpand_20_data; //0x20 I/O Extpander ,PCA9534PW + struct Cameo_i2c_data *Cameo_Extpand_21_data; //0x21 I/O Extpander ,PCA9534PW + struct Cameo_i2c_data *Cameo_BMC_14_data; //0x14 BMC ,Aspeed + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + { + status = -EIO; + goto exit; + } + Cameo_CPLD_30_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_30_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_31_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_31_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_33_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_33_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_35_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_35_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_Extpand_20_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_Extpand_20_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_Extpand_21_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_Extpand_21_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_BMC_14_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_BMC_14_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(Cameo_CPLD_30_client, Cameo_CPLD_30_data); + i2c_set_clientdata(Cameo_CPLD_31_client, Cameo_CPLD_31_data); + i2c_set_clientdata(Cameo_CPLD_33_client, Cameo_CPLD_33_data); + i2c_set_clientdata(Cameo_CPLD_35_client, Cameo_CPLD_35_data); + i2c_set_clientdata(Cameo_Extpand_20_client, Cameo_Extpand_20_data); + i2c_set_clientdata(Cameo_Extpand_21_client, Cameo_Extpand_21_data); + i2c_set_clientdata(Cameo_BMC_14_client , Cameo_BMC_14_data); + + mutex_init(&Cameo_CPLD_30_data->update_lock); + mutex_init(&Cameo_CPLD_31_data->update_lock); + mutex_init(&Cameo_CPLD_33_data->update_lock); + mutex_init(&Cameo_CPLD_35_data->update_lock); + mutex_init(&Cameo_Extpand_20_data->update_lock); + mutex_init(&Cameo_Extpand_21_data->update_lock); + mutex_init(&Cameo_BMC_14_data->update_lock); + + Cameo_CPLD_30_data->valid = 0; + mutex_init(&Cameo_CPLD_30_data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ESC600_SYS_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESC600_LED_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESC600_FAN_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESC600_THERMAL_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESC600_POWER_group); + if (status) + { + goto exit_free; + } + + Cameo_CPLD_30_data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(Cameo_CPLD_30_data->hwmon_dev)) + { + status = PTR_ERR(Cameo_CPLD_30_data->hwmon_dev); + goto exit_remove; + } + dev_info(&client->dev, "%s: '%s'\n", dev_name(Cameo_CPLD_30_data->hwmon_dev), client->name); + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ESC600_SYS_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_LED_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_FAN_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_THERMAL_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_POWER_group); + +exit_free: + kfree(Cameo_CPLD_30_data); + +exit: + return status; +} + +static int Cameo_i2c_remove(struct i2c_client *client) +{ + struct Cameo_i2c_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ESC600_SYS_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_LED_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_FAN_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_THERMAL_group); + sysfs_remove_group(&client->dev.kobj, &ESC600_POWER_group); + + kfree(data); + return 0; +} + +static const struct i2c_device_id Cameo_i2c_id[] = +{ + { "Cameo_CPLD_30", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, Cameo_i2c_id); + +static struct i2c_driver Cameo_i2c_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = + { + .name = "ESC_600_i2c", + }, + .probe = Cameo_i2c_probe, + .remove = Cameo_i2c_remove, + .id_table = Cameo_i2c_id, + .address_list = normal_i2c, +}; + +/*0x30 CPLD ,XO2-2000HC-4FTG256C*/ +static struct i2c_board_info Cameo_CPLD_30_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_30", 0x30), + .platform_data = NULL, + }, +}; + +/*0x31 CPLD ,XO2-7000HC-4TG144C*/ +static struct i2c_board_info Cameo_CPLD_31_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_31", 0x31), + .platform_data = NULL, + }, +}; +/*0x33 I/O Board CPLD ,XO2-640*/ +static struct i2c_board_info Cameo_CPLD_33_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_33", 0x33), + .platform_data = NULL, + }, +}; +/*0x35 CPLD ,XO2-2000HC-4FTG256C*/ +static struct i2c_board_info Cameo_CPLD_35_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_35", 0x35), + .platform_data = NULL, + }, +}; +/*0x20 I/O Extpander ,PCA9534PW*/ +static struct i2c_board_info Cameo_Extpand_20_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_Extpand_20", 0x20), + .platform_data = NULL, + }, +}; +/*0x21 I/O Extpander ,PCA9534PW*/ +static struct i2c_board_info Cameo_Extpand_21_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_Extpand_21", 0x21), + .platform_data = NULL, + }, +}; +/*0x14 BMC ,Aspeed*/ +static struct i2c_board_info Cameo_BMC_14_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_BMC_14", 0x14), + .platform_data = NULL, + }, +}; + +static int __init Cameo_i2c_init(void) +{ + int ret; + int cmp; + char keyword[] = "SMBus I801"; + char buf1[128]; + struct i2c_adapter *i2c_adap; + struct file *fp; + mm_segment_t fs; + loff_t pos; + + printk("Open file...\n"); + fp = filp_open("/sys/class/i2c-dev/i2c-0/name", O_RDONLY , 0644); + if (IS_ERR(fp)) { + printk("Open file FAILED\n"); + return -1; + } + + fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_read(fp, buf1, sizeof(buf1), &pos); + printk("Detect %s\n", buf1); + cmp = strncmp(keyword, buf1, sizeof(keyword)-1); + set_fs(fs); + + filp_close(fp, NULL); + + if(cmp == 0) + { + i2c_adap = i2c_get_adapter(0); + printk("SMBus I801 is at bus 0\n"); + } + else + { + i2c_adap = i2c_get_adapter(1); + printk("SMBus I801 is at bus 1\n"); + } + + if (i2c_adap == NULL) + { + printk("ERROR: i2c_get_adapter FAILED!\n"); + return -1; + } + Cameo_CPLD_30_client = i2c_new_device(i2c_adap, &Cameo_CPLD_30_info[0]); + Cameo_CPLD_31_client = i2c_new_device(i2c_adap, &Cameo_CPLD_31_info[0]); + Cameo_CPLD_33_client = i2c_new_device(i2c_adap, &Cameo_CPLD_33_info[0]); + Cameo_CPLD_35_client = i2c_new_device(i2c_adap, &Cameo_CPLD_35_info[0]); + Cameo_Extpand_20_client = i2c_new_device(i2c_adap, &Cameo_Extpand_20_info[0]); + Cameo_Extpand_21_client = i2c_new_device(i2c_adap, &Cameo_Extpand_21_info[0]); + Cameo_BMC_14_client = i2c_new_device(i2c_adap, &Cameo_BMC_14_info[0]); + + if (Cameo_CPLD_30_info == NULL || Cameo_CPLD_31_info == NULL || Cameo_CPLD_33_info == NULL + || Cameo_CPLD_35_info == NULL || Cameo_Extpand_20_info == NULL || Cameo_Extpand_21_info == NULL || Cameo_BMC_14_info == NULL) + { + printk("ERROR: i2c_new_device FAILED!\n"); + return -1; + } + + i2c_put_adapter(i2c_adap); + ret = i2c_add_driver(&Cameo_i2c_driver); + printk(KERN_ALERT "ESC600-128Q i2c Driver Version: %s\n", DRIVER_VERSION); + printk(KERN_ALERT "ESC600-128Q i2c Driver INSTALL SUCCESS\n"); + return ret; +} + +static void __exit Cameo_i2c_exit(void) +{ + i2c_unregister_device(Cameo_CPLD_30_client); + i2c_unregister_device(Cameo_CPLD_31_client); + i2c_unregister_device(Cameo_CPLD_33_client); + i2c_unregister_device(Cameo_CPLD_35_client); + i2c_unregister_device(Cameo_Extpand_20_client); + i2c_unregister_device(Cameo_Extpand_21_client); + i2c_unregister_device(Cameo_BMC_14_client); + i2c_del_driver(&Cameo_i2c_driver); + printk(KERN_ALERT "ESC600-128Q i2c Driver UNINSTALL SUCCESS\n"); +} + +MODULE_AUTHOR("Cameo Inc."); +MODULE_DESCRIPTION("Cameo ESC600-128Q i2c Driver"); +MODULE_LICENSE("GPL"); +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Enable debugging (0-1)"); + +module_init(Cameo_i2c_init); +module_exit(Cameo_i2c_exit); diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.h new file mode 100644 index 0000000000..39e5ab15e9 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-common.h @@ -0,0 +1,25 @@ +/* register offset define */ +#define ENABLE 1 +#define DISABLE 0 + +#define PASSED 1 +#define FAILED 0 + +#define TRUE 1 +#define FALSE 0 + +#define ABNORMAL 1 +#define NORMAL 0 + +#define BIT_0_MASK 0x01 +#define BIT_1_MASK 0x02 +#define BIT_2_MASK 0x04 +#define BIT_3_MASK 0x08 +#define BIT_4_MASK 0x10 +#define BIT_5_MASK 0x20 +#define BIT_6_MASK 0x40 +#define BIT_7_MASK 0x80 +/* end of register offset define */ + +int bmc_enable(void); +int read_8bit_temp(u8 sign,u8 value); \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.c new file mode 100644 index 0000000000..f27d2197a8 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.c @@ -0,0 +1,358 @@ +/* An hwmon driver for Cameo esc600-128Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esc600-128q.h" +#include "x86-64-cameo-esc600-128q-common.h" +#include "x86-64-cameo-esc600-128q-fan.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_35_client; //0x35 CPLD ,XO2-2000HC-4FTG256C +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t fan_ctrl_mode_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_BMC_14_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == FANCTRL_MODE) + { + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, FANCTRL_MODE_REG); + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s0x%x\n", buf, status); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t fan_ctrl_rpm_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_BMC_14_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == FANCTRL_RPM) + { + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, FANCTRL_RPM_REG); + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s0x%x\n", buf, status); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, FAN_STAT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_4_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_5_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_6_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_7_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_PRESENT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, FAN_PRESENT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_POWER_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, FAN_POWER_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_4_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_5_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_6_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_7_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_direct_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_DIRECT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, FAN_DIRECT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = IN; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = OUT; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = OUT; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = OUT; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = OUT; + } + break; + } + if(result != OUT) + { + return sprintf(buf, "%s%d\n", buf, IN); + } + return sprintf(buf, "%s%d\n", buf, IN); +} + +ssize_t fan_rpm_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int fan_offset = 0; + u8 target_register = 0x00; + u16 fan_speed = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *target_client = NULL; + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + target_client = Cameo_BMC_14_client; + target_register = 0xe0; + } + else + { + target_client = Cameo_CPLD_35_client; + target_register = 0xa3; + } + + switch (attr->index) + { + case FAN_1_RPM: + fan_offset = 0; + break; + case FAN_2_RPM: + fan_offset = 1; + break; + case FAN_3_RPM: + fan_offset = 2; + break; + case FAN_4_RPM: + fan_offset = 3; + break; + } + + // read high byte + status = i2c_smbus_read_byte_data(target_client, target_register+(fan_offset*2)+1); + fan_speed = status; + if(status < 0) + { + fan_speed = 0; + } + // read low byte + status = i2c_smbus_read_byte_data(target_client, target_register+(fan_offset*2)); + fan_speed = ((fan_speed<<8) + status)*30; + if(status < 0) + { + fan_speed = 0; + } + + sprintf(buf, "%s%d\n", buf, fan_speed); + return sprintf(buf, "%s\n",buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.h new file mode 100644 index 0000000000..1f6a9ecdc2 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-fan.h @@ -0,0 +1,15 @@ +/* register offset define */ +#define FANCTRL_RPM_REG 0x06 +#define FANCTRL_MODE_REG 0x07 +#define FAN_STAT_REG 0xa1 +#define FAN_POWER_REG 0xa2 +#define FAN_PRESENT_REG 0xa1 +#define FAN_DIRECT_REG 0xa2 +#define BMC_FAN_STAT_REG 0xe9 +#define BMC_FAN_POWER_REG 0xea +#define BMC_FAN_PRESENT_REG 0xe9 +#define BMC_FAN_DIRECT_REG 0xea + +#define OUT 1 +#define IN 0 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.c new file mode 100644 index 0000000000..8956de649e --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.c @@ -0,0 +1,518 @@ +/* An hwmon driver for Cameo esc600-128Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esc600-128q.h" +#include "x86-64-cameo-esc600-128q-common.h" +#include "x86-64-cameo-esc600-128q-led.h" + +/* i2c_client Declaration */ +extern struct i2c_client *Cameo_CPLD_31_client; //0x31 CPLD ,XO2-7000HC-4TG144C +extern struct i2c_client *Cameo_CPLD_33_client; //0x33 I/O Board CPLD ,XO2-640 +/* end of i2c_client Declaration */ + +/* implement i2c_function */ +ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int res = 0x1; + int i; + int led_a_status = 0; + int led_g_status = 0; + int led_b_status = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_CTRL_REG); + sprintf(buf, ""); + + for (i = 1; i <= 3; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_a_status = ENABLE; + } + else + { + led_a_status = DISABLE; + } + } + res = res << 1; + if( i == (attr->index + 1) ) + { + if (status & res) + { + led_g_status = ENABLE; + } + else + { + led_g_status = DISABLE; + } + } + res = res << 1; + } + res = 0x1; + + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_BLINK_REG); + for (i = 1; i <= 3; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_b_status = ENABLE; + } + else + { + led_b_status = DISABLE; + } + } + res = res << 1; + } + if(led_a_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s2\n", buf); + } + else if(led_a_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s1\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s4\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s3\n", buf); + } + else + { + sprintf(buf, "%s0\n", buf); + } + + return sprintf(buf, "%s", buf); +} + +ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int led_value = -EPERM; + int blk_value = -EPERM; + int result = -EPERM; + int offset = 0; + u16 i; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + led_value = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_CTRL_REG); + blk_value = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_BLINK_REG); + if (attr->index != 0) + { + i = simple_strtol(buf, NULL, 10); + if(attr->index == 1) + { + offset = 0; + } + else + { + offset = 2*((attr->index)-1); + } + switch(i) + { + case SWITCH_LED_OFF: //i=0 + led_value &= ~(0x03 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_N: //i=1 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_B: //i=2 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_N: //i=3 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_B: //i=4 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + default: + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + return count; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, LED_CTRL_REG, led_value); + result |= i2c_smbus_write_byte_data(Cameo_CPLD_33_client, LED_BLINK_REG, blk_value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t switch_led_4_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int res = 0x1; + int i; + int led_a_status = 0; + int led_g_status = 0; + int led_b_status = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_4_CTRL_REG); + sprintf(buf, ""); + + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_a_status = ENABLE; + } + else + { + led_a_status = DISABLE; + } + } + res = res << 1; + if( i == (attr->index + 1) ) + { + if (status & res) + { + led_g_status = ENABLE; + } + else + { + led_g_status = DISABLE; + } + } + res = res << 1; + } + res = 0x1; + + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_4_BLINK_REG); + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_b_status = ENABLE; + } + else + { + led_b_status = DISABLE; + } + } + res = res << 1; + } + if(led_a_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s2\n", buf); + } + else if(led_a_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s1\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s4\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s3\n", buf); + } + else + { + sprintf(buf, "%s0\n", buf); + } + + return sprintf(buf, "%s", buf); +} + +ssize_t switch_led_4_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int led_value = -EPERM; + int blk_value = -EPERM; + int result = -EPERM; + int offset = 0; + u16 i; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + led_value = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_4_CTRL_REG); + blk_value = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_4_BLINK_REG); + if (attr->index != 0) + { + i = simple_strtol(buf, NULL, 10); + if(attr->index == 1) + { + offset = 0; + } + else + { + offset = 2*((attr->index)-1); + } + switch(i) + { + case SWITCH_LED_OFF: //i=0 + led_value &= ~(0x03 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_N: //i=1 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_B: //i=2 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_N: //i=3 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_B: //i=4 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + default: + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + return count; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, LED_4_CTRL_REG, led_value); + result |= i2c_smbus_write_byte_data(Cameo_CPLD_33_client, LED_4_BLINK_REG, blk_value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t switch_led_5_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int res = 0x1; + int i; + int led_a_status = 0; + int led_g_status = 0; + int led_b_status = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_5_CTRL_REG); + sprintf(buf, ""); + + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_a_status = ENABLE; + } + else + { + led_a_status = DISABLE; + } + } + res = res << 1; + if( i == (attr->index + 1) ) + { + if (status & res) + { + led_g_status = ENABLE; + } + else + { + led_g_status = DISABLE; + } + } + res = res << 1; + } + res = 0x1; + + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_5_BLINK_REG); + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_b_status = ENABLE; + } + else + { + led_b_status = DISABLE; + } + } + res = res << 1; + } + if(led_a_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s2\n", buf); + } + else if(led_a_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s1\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s4\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s3\n", buf); + } + else + { + sprintf(buf, "%s0\n", buf); + } + + return sprintf(buf, "%s", buf); +} + +ssize_t switch_led_5_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int led_value = -EPERM; + int blk_value = -EPERM; + int result = -EPERM; + int offset = 0; + u16 i; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + led_value = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_5_CTRL_REG); + blk_value = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, LED_5_BLINK_REG); + if (attr->index != 0) + { + i = simple_strtol(buf, NULL, 10); + if(attr->index == 1) + { + offset = 0; + } + else + { + offset = 2*((attr->index)-1); + } + switch(i) + { + case SWITCH_LED_OFF: //i=0 + led_value &= ~(0x03 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_N: //i=1 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_B: //i=2 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_N: //i=3 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_B: //i=4 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + default: + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + return count; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, LED_5_CTRL_REG, led_value); + result |= i2c_smbus_write_byte_data(Cameo_CPLD_33_client, LED_5_BLINK_REG, blk_value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t led_fiber_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == LED_FIBER) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, LED_FIBER_REG) & BIT_0_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} +ssize_t led_fiber_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, LED_CTRL_REG); + if (attr->index == LED_FIBER) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | LED_FIBER_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_31_client, LED_FIBER_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & LED_FIBER_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_31_client, LED_FIBER_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.h new file mode 100644 index 0000000000..4e5ba820d7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-led.h @@ -0,0 +1,18 @@ +/* register offset define */ +#define LED_CTRL_REG 0xa1 +#define LED_BLINK_REG 0xa2 +#define LED_4_CTRL_REG 0xa3 +#define LED_4_BLINK_REG 0xa4 +#define LED_5_CTRL_REG 0xa5 +#define LED_5_BLINK_REG 0xa6 +#define LED_CTRL_REG 0xa1 +#define LED_BLINK_REG 0xa2 +#define LED_FIBER_REG 0xa0 +#define LED_FIBER_ENABLE 0x01 +#define LED_FIBER_DISABLE 0xfe +#define SWITCH_LED_OFF 0 +#define SWITCH_LED_A_N 1 +#define SWITCH_LED_A_B 2 +#define SWITCH_LED_G_N 3 +#define SWITCH_LED_G_B 4 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.c new file mode 100644 index 0000000000..510bbe37ba --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.c @@ -0,0 +1,1095 @@ +/* An hwmon driver for Cameo esc600-128Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esc600-128q.h" +#include "x86-64-cameo-esc600-128q-common.h" +#include "x86-64-cameo-esc600-128q-power.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_35_client; //0x35 for Power CPLD +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* convert function */ +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} +/* end of convert function */ + +/* implement i2c_function */ +ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_PSU_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, PSU_STAT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = TRUE; + switch (attr->index) + { + case 1: + if(status & BIT_4_MASK) + { + result = FALSE; + } + break; + case 2: + if(status & BIT_5_MASK) + { + result = FALSE; + } + break; + case 3: + if(status & BIT_6_MASK) + { + result = FALSE; + } + break; + case 4: + if(status & BIT_7_MASK) + { + result = FALSE; + } + break; + } + if(result != TRUE) + { + return sprintf(buf, "%s%d\n", buf, FALSE); + } + return sprintf(buf, "%s%d\n", buf, TRUE); +} +ssize_t psu_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_PSU_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, PSU_STAT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = FALSE; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = TRUE; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = TRUE; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = TRUE; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = TRUE; + } + break; + } + if(result != TRUE) + { + return sprintf(buf, "%s%d\n", buf, FALSE); + } + return sprintf(buf, "%s%d\n", buf, TRUE); +} +ssize_t psu_vin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_VIN_REG); + break; + case PSU2_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_VIN_REG); + break; + case PSU3_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_VIN_REG); + break; + case PSU4_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_VIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t psu_iin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_IIN_REG); + break; + case PSU2_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_IIN_REG); + break; + case PSU3_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_IIN_REG); + break; + case PSU4_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_IIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t psu_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0; + int multiplier = 1000; + u16 u16_vmode = 0; + u16 u16_vout = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_VOUT_REG); + break; + case PSU2_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_VOUT_REG); + break; + case PSU3_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_3_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_VOUT_REG); + break; + case PSU4_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_4_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_VOUT_REG); + break; + } + if(u16_vout == 0xffff || u16_vout == -1) + { + return sprintf(buf, "%s0\n", buf); + } + /* vout mode */ + multiplier = 1000; + exponent = two_complement_to_int(u16_vmode & 0x1f, 5, 0x1f); + /* vout */ + result = (exponent >= 0) ? ((u16_vout << exponent)*multiplier) : \ + (u16_vout*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_IOUT_REG); + break; + case PSU2_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_IOUT_REG); + break; + case PSU3_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_IOUT_REG); + break; + case PSU4_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_IOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_temp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_TEMP_1_REG); + break; + case PSU2_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_TEMP_1_REG); + break; + case PSU3_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_TEMP_1_REG); + break; + case PSU4_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_TEMP_1_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_fan_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_FAN_SPEED_REG); + break; + case PSU2_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_FAN_SPEED_REG); + break; + case PSU3_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_FAN_SPEED_REG); + break; + case PSU4_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_FAN_SPEED_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_pout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_POUT_REG); + break; + case PSU2_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_POUT_REG); + break; + case PSU3_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_POUT_REG); + break; + case PSU4_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_POUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_pin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_PIN_REG); + break; + case PSU2_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_PIN_REG); + break; + case PSU3_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_PIN_REG); + break; + case PSU4_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_PIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 u16_val = 0; + char model[I2C_SMBUS_BLOCK_MAX] = {0}; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_1_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + case PSU2_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_2_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + case PSU3_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_3_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + case PSU4_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_4_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + } + if(u16_val != I2C_SMBUS_BLOCK_MAX) + { + return sprintf(buf, "%sERROR\n", buf); + } + if (model[1] < 0x20 || model[1] > 0x7f) + { + return sprintf(buf, "%sERROR\n", buf); + } + sprintf(buf, "%s%s\n", buf, model); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_iout_max_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_MFR_IOUT_MAX_REG); + break; + case PSU2_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_MFR_IOUT_MAX_REG); + break; + case PSU3_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_3_MFR_IOUT_MAX_REG); + break; + case PSU4_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_4_MFR_IOUT_MAX_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_vmode_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 u16_vmode = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); + break; + case PSU2_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); + break; + case PSU3_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_3_VMODE_REG); + break; + case PSU4_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_4_VMODE_REG); + break; + } + if(u16_vmode == 0xffff || u16_vmode == -1) + { + return sprintf(buf, "%s0\n", buf); + } + /* vout mode */ + sprintf(buf, "%s%d\n", buf, u16_vmode); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC_6E_P0_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_6E_P0_VOUT_REG); + break; + case DC_70_P0_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_70_P0_VOUT_REG); + break; + case DC_70_P1_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_70_P1_VOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC_6E_P0_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_6E_P0_IOUT_REG); + break; + case DC_70_P0_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_70_P0_IOUT_REG); + break; + case DC_70_P1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_70_P1_IOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_pout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC_6E_P0_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_6E_P0_POUT_REG); + break; + case DC_70_P0_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_70_P0_POUT_REG); + break; + case DC_70_P1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_70_P1_POUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_11_p0_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_11_vout_table[attr->index][0]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_11_p1_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_11_vout_table[attr->index][1]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_12_p0_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_12_vout_table[attr->index][0]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_12_p1_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_12_vout_table[attr->index][1]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_13_p0_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_13_vout_table[attr->index][0]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_13_p1_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_13_vout_table[attr->index][1]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_11_p0_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_11_iout_table[attr->index][0]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_11_p1_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_11_iout_table[attr->index][1]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_12_p0_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_12_iout_table[attr->index][0]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_12_p1_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_12_iout_table[attr->index][1]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_13_p0_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_13_iout_table[attr->index][0]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_13_p1_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, dc_13_iout_table[attr->index][1]); + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.h new file mode 100644 index 0000000000..20955b70ab --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-power.h @@ -0,0 +1,148 @@ +/* register offset define */ +#define PSU_STAT_REG 0xa0 +#define BMC_PSU_STAT_REG 0xe8 + +#define PSU_1_VIN_REG 0xb0 +#define PSU_1_IIN_REG 0xb1 +#define PSU_1_VOUT_REG 0xb2 +#define PSU_1_IOUT_REG 0xb3 +#define PSU_1_TEMP_1_REG 0xb4 +#define PSU_1_FAN_SPEED_REG 0xb5 +#define PSU_1_POUT_REG 0xb6 +#define PSU_1_PIN_REG 0xb7 +#define PSU_1_MFR_MODEL_REG 0xfa +#define PSU_1_MFR_IOUT_MAX_REG 0xb9 +#define PSU_1_VMODE_REG 0xd8 + +#define PSU_2_VIN_REG 0xba +#define PSU_2_IIN_REG 0xbb +#define PSU_2_VOUT_REG 0xbc +#define PSU_2_IOUT_REG 0xbd +#define PSU_2_TEMP_1_REG 0xbe +#define PSU_2_FAN_SPEED_REG 0xbf +#define PSU_2_POUT_REG 0xc0 +#define PSU_2_PIN_REG 0xc1 +#define PSU_2_MFR_MODEL_REG 0x9a +#define PSU_2_MFR_IOUT_MAX_REG 0xc3 +#define PSU_2_VMODE_REG 0xd9 + +#define PSU_3_VIN_REG 0xc4 +#define PSU_3_IIN_REG 0xc5 +#define PSU_3_VOUT_REG 0xc6 +#define PSU_3_IOUT_REG 0xc7 +#define PSU_3_TEMP_1_REG 0xc8 +#define PSU_3_FAN_SPEED_REG 0xc9 +#define PSU_3_POUT_REG 0xca +#define PSU_3_PIN_REG 0xcb +#define PSU_3_MFR_MODEL_REG 0x9d +#define PSU_3_MFR_IOUT_MAX_REG 0xcd +#define PSU_3_VMODE_REG 0xda + +#define PSU_4_VIN_REG 0xce +#define PSU_4_IIN_REG 0xcf +#define PSU_4_VOUT_REG 0xd0 +#define PSU_4_IOUT_REG 0xd1 +#define PSU_4_TEMP_1_REG 0xd2 +#define PSU_4_FAN_SPEED_REG 0xd3 +#define PSU_4_POUT_REG 0xd4 +#define PSU_4_PIN_REG 0xd5 +#define PSU_4_MFR_MODEL_REG 0xd6 +#define PSU_4_MFR_IOUT_MAX_REG 0xd7 +#define PSU_4_VMODE_REG 0xdb + +#define DC_6E_P0_VOUT_REG 0x18 +#define DC_70_P0_VOUT_REG 0x1b +#define DC_70_P1_VOUT_REG 0xf1 + +#define DC_6E_P0_IOUT_REG 0x19 +#define DC_70_P0_IOUT_REG 0x1c +#define DC_70_P1_IOUT_REG 0xf2 + +#define DC_6E_P0_POUT_REG 0x1a +#define DC_70_P0_POUT_REG 0x1d +#define DC_70_P1_POUT_REG 0xf3 + +u8 dc_11_vout_table [9][2] = +{ +/* Page0 Page1*/ + {0x00, 0x00}, + {0x30, 0x33}, + {0x40, 0x43}, + {0x50, 0x53}, + {0x60, 0x63}, + {0x70, 0x73}, + {0x80, 0x83}, + {0x90, 0x93}, + {0xa0, 0xa3}, +}; + +u8 dc_12_vout_table [9][2] = +{ +/* Page0 Page1*/ + {0x00, 0x00}, + {0x36, 0x3f}, + {0x46, 0x5f}, + {0x56, 0x7f}, + {0x66, 0x9f}, + {0x76, 0xdd}, + {0x86, 0x0d}, + {0x96, 0xf8}, + {0xa6, 0xfc}, +}; + +u8 dc_13_vout_table [9][2] = +{ +/* Page0 Page1*/ + {0x00, 0x00}, + {0x38, 0x3b}, + {0x48, 0x4b}, + {0x58, 0x5b}, + {0x68, 0x6b}, + {0x78, 0x7b}, + {0x88, 0x8b}, + {0x98, 0x9b}, + {0xa8, 0xab}, +}; + +u8 dc_11_iout_table [9][2] = +{ +/* Page0 Page1*/ + {0x00, 0x00}, + {0x31, 0x34}, + {0x41, 0x44}, + {0x51, 0x54}, + {0x61, 0x64}, + {0x71, 0x74}, + {0x81, 0x84}, + {0x91, 0x94}, + {0xa1, 0xa4}, +}; + +u8 dc_12_iout_table [9][2] = +{ +/* Page0 Page1*/ + {0x00, 0x00}, + {0x37, 0x4e}, + {0x47, 0x6e}, + {0x57, 0x8e}, + {0x67, 0xae}, + {0x77, 0xde}, + {0x87, 0x0e}, + {0x97, 0xf9}, + {0xa7, 0xfd}, +}; + +u8 dc_13_iout_table [9][2] = +{ +/* Page0 Page1*/ + {0x00, 0x00}, + {0x39, 0x3c}, + {0x49, 0x4c}, + {0x59, 0x5c}, + {0x69, 0x6c}, + {0x79, 0x7c}, + {0x89, 0x8c}, + {0x99, 0x9c}, + {0xa9, 0xac}, +}; +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.c new file mode 100644 index 0000000000..163c2f4802 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.c @@ -0,0 +1,2011 @@ +/* An hwmon driver for Cameo esc600-128Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esc600-128q.h" +#include "x86-64-cameo-esc600-128q-common.h" +#include "x86-64-cameo-esc600-128q-sys.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_30_client; //0x30 CPLD ,XO2-2000HC-4FTG256C +extern struct i2c_client *Cameo_CPLD_31_client; //0x31 CPLD ,XO2-7000HC-4TG144C +extern struct i2c_client *Cameo_CPLD_33_client; //0x33 I/O Board CPLD ,XO2-640 +extern struct i2c_client *Cameo_BMC_14_client; //0x14 BMC ,Aspeed +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t cpld_hw_ver_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case 30: + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, CPLD_VER_REG); + break; + case 31: + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, CPLD_VER_REG); + break; + case 33: + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, CPLD_VER_REG); + break; + } + if(status < 0) + { + mutex_unlock(&data->update_lock); + return status; + } + else + { + mutex_unlock(&data->update_lock); + sprintf(buf, "%s0x%x\n", buf, status); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t wdt_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == WDT_EN) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, WDT_EN_REG) & BIT_4_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t wdt_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, WDT_EN_REG); + if (attr->index == WDT_EN) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | WDT_EN_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, WDT_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: wdt_enable_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & WDT_EN_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, WDT_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: wdt_enable_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "wdt_enable_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t eeprom_wp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == EEPROM_WP) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, EEPROM_WP_REG) & BIT_4_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t eeprom_wp_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, EEPROM_WP_REG); + if (attr->index == EEPROM_WP) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | EEPROM_WP_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_31_client, EEPROM_WP_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: eeprom_wp_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & EEPROM_WP_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_31_client, EEPROM_WP_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: eeprom_wp_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "eeprom_wp_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t usb_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == USB_EN) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG) & BIT_0_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t usb_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG); + if (attr->index == USB_EN) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | USB_EN_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, USB_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: usb_enable_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & USB_EN_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, USB_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: usb_enable_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "usb_enable_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t reset_mac_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MAC_RESET_REG); + if (attr->index == RESET) + { + input = simple_strtol(buf, NULL, 10); + if (input == MAC_RESET) + { + value = MAC_RESET; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, MAC_RESET_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: reset_mac_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "reset_mac_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t shutdown_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SHUTDOWN_REG); + if (attr->index == SHUTDOWN_SET) + { + input = simple_strtol(buf, NULL, 10); + if (input == SHUTDOWN) + { + value = status | SHUTDOWN; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, SHUTDOWN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: shutdown_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "shutdown_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t bmc_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == BMC_PRESENT) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, BMC_EN_REG) & BIT_0_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t switch_alarm_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case SW_ALERT_TH0: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALARM_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_ALERT_TH1: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALARM_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_ALERT_TH2: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALARM_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_ALERT_TH3: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALARM_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t switch_alarm_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case SW_ALERT_TH0_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALERT_MASK_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_ALERT_TH1_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALERT_MASK_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_ALERT_TH2_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALERT_MASK_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_ALERT_TH3_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALERT_MASK_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t switch_alarm_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SW_ALERT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + if((input != 0) && (input != 1) ) + { + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "switch_alarm_mask_set wrong Value\n"); + return count; + } + switch (attr->index) + { + case SW_ALERT_TH0_MASK: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + break; + case SW_ALERT_TH1_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + break; + case SW_ALERT_TH2_MASK: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + break; + case SW_ALERT_TH3_MASK: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_31_client, SW_ALERT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t sensor_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case CB_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SENSOR_INT_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SB_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SENSOR_INT_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sersor_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case CB_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SENSOR_INT_MASK_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SB_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SENSOR_INT_MASK_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sersor_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SENSOR_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + switch (attr->index) + { + case CB_INT_MASK: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case SB_INT_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_31_client, SENSOR_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t module_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + u8 status = -EPERM; + u8 result = 0; + int card_num = 0; + int input = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_30_data = i2c_get_clientdata(Cameo_CPLD_30_client); + + if (attr->index == MODULE_RESET) + { + input = simple_strtol(buf, NULL, 10); //get input module number + if(input <= 0 || input > 8) + { + printk(KERN_ALERT "ERROR: module_reset_%d RESET FAILED!\n", input); + } + else + { + mutex_lock(&Cameo_CPLD_30_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_RESET_REG); //to get register 0x30 0xa2 + status &= ~(1 << (input-1)); + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, MODULE_RESET_REG, status); //to set register 0x30 0xa2 + if (result < 0) + { + printk(KERN_ALERT "ERROR: module_reset_%d RESET FAILED!\n", card_num); + } + } + } + mutex_unlock(&Cameo_CPLD_30_data->update_lock); + return count; +} + +ssize_t module_insert_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case MODULE_1_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_0_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_2_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_1_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_3_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_2_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_4_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_3_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_5_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_4_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_6_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_5_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_7_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_6_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_8_PRESENT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_PRESENT_REG) & BIT_7_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t module_power_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case MODULE_1_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_0_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_2_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_1_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_3_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_2_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_4_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_3_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_5_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_4_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_6_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_5_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_7_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_6_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_8_POWER: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_POWER_REG) & BIT_7_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t module_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case MODULE_1_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_0_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_2_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_1_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_3_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_2_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_4_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_3_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_5_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_4_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_6_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_5_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_7_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_6_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case MODULE_8_ENABLE: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG) & BIT_7_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t module_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG); + + input = simple_strtol(buf, NULL, 10); + if((input != 0) && (input != 1) ) + { + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "module_enable_set wrong Value\n"); + return count; + } + switch (attr->index) + { + case MODULE_1_ENABLE: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + break; + case MODULE_2_ENABLE: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + break; + case MODULE_3_ENABLE: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + break; + case MODULE_4_ENABLE: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + break; + case MODULE_5_ENABLE: + if (input == ENABLE) + { + value = status | 0x10; + } + else if (input == DISABLE) + { + value = status & 0xef; + } + break; + case MODULE_6_ENABLE: + if (input == ENABLE) + { + value = status | 0x20; + } + else if (input == DISABLE) + { + value = status & 0xdf; + } + break; + case MODULE_7_ENABLE: + if (input == ENABLE) + { + value = status | 0x40; + } + else if (input == DISABLE) + { + value = status & 0xbf; + } + break; + case MODULE_8_ENABLE: + if (input == ENABLE) + { + value = status | 0x80; + } + else if (input == DISABLE) + { + value = status & 0x7f; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, MODULE_ENABLE_REG, value); + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t switch_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case MODULE_INS_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case MODULE_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case MODULE_POWER_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case THER_SENSOR_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case IO_BOARD_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case FAN_ERROR_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case PHY_POWER_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_6_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_POWER_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_REG) & BIT_7_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t switch_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case MODULE_INS_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case MODULE_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case MODULE_POW_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case THER_SEN_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case IO_BOARD_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case FAN_ERROR_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case PHY_POWER_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_6_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SW_POWER_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG) & BIT_7_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t switch_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + if((input != 0) && (input != 1) ) + { + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "switch_int_mask_set wrong Value\n"); + return count; + } + switch (attr->index) + { + case MODULE_INS_INT_MASK: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + break; + case MODULE_INT_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + break; + case MODULE_POW_INT_MASK: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + break; + case THER_SEN_INT_MASK: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + break; + case IO_BOARD_INT_MASK: + if (input == ENABLE) + { + value = status | 0x10; + } + else if (input == DISABLE) + { + value = status & 0xef; + } + break; + case FAN_ERROR_INT_MASK: + if (input == ENABLE) + { + value = status | 0x20; + } + else if (input == DISABLE) + { + value = status & 0xdf; + } + break; + case PHY_POWER_INT_MASK: + if (input == ENABLE) + { + value = status | 0x40; + } + else if (input == DISABLE) + { + value = status & 0xbf; + } + break; + case SW_POWER_INT_MASK: + if (input == ENABLE) + { + value = status | 0x80; + } + else if (input == DISABLE) + { + value = status & 0x7f; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, SWITCH_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t sfp_select_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == SFP_SELECT) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_SELECT_REG); //to get register 0x33 0x60 + sprintf(buf, ""); + if (status & 0x1) + { + sprintf(buf, "%s%d\n", buf, SFP_PORT_1); + } + else if (status & 0x2) + { + sprintf(buf, "%s%d\n", buf, SFP_PORT_2); + } + else if (status & 0x3) + { + sprintf(buf, "%s%d\n", buf, SFP_PORT_MGM); + } + else + { + sprintf(buf, "%s%d\n", buf, SFP_NON_SELECT); + } + } + return sprintf(buf, "%s", buf); +} + +ssize_t sfp_select_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + u8 status = -EPERM; + u8 value = -EPERM; + u8 result = -EPERM; + u16 i; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_SELECT_REG); //to get register 0x33 0x60 + if (attr->index == SFP_SELECT) + { + i = simple_strtol(buf, NULL, 10); + if (i == 0) + { + value = 0x0; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_SELECT_REG, value); //to set register 0x33 0x60 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_select_set 0 FAILED!\n"); + } + } + else if (i == 1) + { + value = 0x1; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_SELECT_REG, value); //to set register 0x33 0x60 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_select_set 1 FAILED!\n"); + } + } + else if (i == 2) + { + value = 0x2; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_SELECT_REG, value); //to set register 0x33 0x60 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_select_set 2 FAILED!\n"); + } + } + else if (i == 3) + { + value = 0x3; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_SELECT_REG, value); //to set register 0x33 0x60 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_select_set 3 FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "SFP_SELECT set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t sfp_tx_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case SFP_PORT_TX_1: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_TX_REG) & BIT_0_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case SFP_PORT_TX_2: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_TX_REG) & BIT_1_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case SFP_PORT_TX_MGM: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_TX_REG) & BIT_2_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_tx_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + u8 status = -EPERM; + u8 value = -EPERM; + u8 result = -EPERM; + u16 i; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_TX_REG); //to get register 0x33 0xa0 + if (attr->index) + { + i = simple_strtol(buf, NULL, 10); + if (i == SFP_PORT_1_OFF) //i = 1 SFP_PORT_1 OFF + { + value = status | 0x1; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_TX_REG, value); //to set register 0x33 0xa0 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_set PORT_1 OFF FAILED!\n"); + } + } + else if (i == SFP_PORT_1_ON) //i = 2 SFP_PORT_1 ON + { + value = status & 0xfe; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_TX_REG, value); //to set register 0x33 0xa0 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_set PORT_1 ON FAILED!\n"); + } + } + else if (i == SFP_PORT_2_OFF) //i = 3 SFP_PORT_2 OFF + { + value = status | 0x2; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_TX_REG, value); //to set register 0x33 0xa0 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_set PORT_2 OFF FAILED!\n"); + } + } + else if (i == SFP_PORT_2_ON) //i = 4 SFP_PORT_2 ON + { + value = status & 0xfd; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_TX_REG, value); //to set register 0x33 0xa0 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_set PORT_2 ON FAILED!\n"); + } + } + else if (i == SFP_PORT_MGM_OFF) //i = 5 SFP_PORT_MGM OFF + { + value = status | 0x4; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_TX_REG, value); //to set register 0x33 0xa0 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_set MGM OFF FAILED!\n"); + } + } + else if (i == SFP_PORT_MGM_ON) //i = 6 SFP_PORT_MGM ON + { + value = status & 0xfb; + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SFP_TX_REG, value); //to set register 0x33 0xa0 + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_set MGM ON FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "SFP_TX set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t sfp_insert_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case SFP_PORT_RX_1: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_PRESENT_REG) & BIT_0_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case SFP_PORT_RX_2: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_PRESENT_REG) & BIT_1_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case SFP_PORT_RX_MGM: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_PRESENT_REG) & BIT_2_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_rx_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case SFP_PORT_RX_1: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_RX_REG) & BIT_0_MASK) + { + result = FALSE; + } + else + { + result = TRUE; + } + break; + case SFP_PORT_RX_2: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_RX_REG) & BIT_1_MASK) + { + result = FALSE; + } + else + { + result = TRUE; + } + break; + case SFP_PORT_RX_MGM: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_RX_REG) & BIT_2_MASK) + { + result = FALSE; + } + else + { + result = TRUE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sys_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case SFP_LOSS_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_INT_REG) & BIT_0_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + case SFP_ABS_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SFP_INT_REG) & BIT_1_MASK) + { + result = TRUE; + } + else + { + result = FALSE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sys_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case SFP_LOSS_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SYS_INT_MASK_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case SFP_ABS_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SYS_INT_MASK_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sys_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_33_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_33_client, SYS_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + if((input != 0) && (input != 1) ) + { + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + switch (attr->index) + { + case SFP_LOSS_MASK: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + break; + case SFP_ABS_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_33_client, SYS_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t thermal_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case ALERT_TH0_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH1_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH2_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH3_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH4_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH5_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t thermal_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case ALERT_TH0_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH1_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH2_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH3_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH4_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case ALERT_TH5_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t thermal_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_31_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + if((input != 0) && (input != 1) ) + { + mutex_unlock(&data->update_lock); + printk(KERN_ALERT "switch_int_mask_set wrong Value\n"); + return count; + } + switch (attr->index) + { + case ALERT_TH0_INT_MASK: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + break; + case ALERT_TH1_INT_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + break; + case ALERT_TH2_INT_MASK: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + break; + case ALERT_TH3_INT_MASK: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + break; + case ALERT_TH4_INT_MASK: + if (input == ENABLE) + { + value = status | 0x10; + } + else if (input == DISABLE) + { + value = status & 0xef; + } + break; + case ALERT_TH5_INT_MASK: + if (input == ENABLE) + { + value = status | 0x20; + } + else if (input == DISABLE) + { + value = status & 0xdf; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_31_client, THERMAL_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.h new file mode 100644 index 0000000000..a87bcb1fe0 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-sys.h @@ -0,0 +1,64 @@ +/* register offset define */ +#define CPLD_VER_REG 0x20 + +#define WDT_EN_REG 0xa0 +#define WDT_EN_ENABLE 0x10 +#define WDT_EN_DISABLE 0xef + +#define EEPROM_WP_REG 0xa0 +#define EEPROM_WP_ENABLE 0x10 +#define EEPROM_WP_DISABLE 0xef + +#define USB_EN_REG 0xa0 +#define USB_EN_ENABLE 0x01 +#define USB_EN_DISABLE 0xfe + +#define MAC_RESET_REG 0xa1 +#define MAC_RESET 0x00 + +#define SHUTDOWN_REG 0xa1 +#define SHUTDOWN 0x10 + +#define BMC_EN_REG 0xa3 +#define BMC_EN_ENABLE 0x01 +#define BMC_EN_DISABLE 0x00 + +#define SW_ALARM_REG 0xc2 +#define SW_ALERT_MASK_REG 0xc3 + +#define THERMAL_INT_REG 0xc0 +#define THERMAL_INT_MASK_REG 0xc1 + +#define SENSOR_INT_REG 0xd0 +#define SENSOR_INT_MASK_REG 0xd1 + +#define MODULE_RESET_REG 0xa2 +#define MODULE_PRESENT_REG 0xa3 +#define MODULE_POWER_REG 0xa4 +#define MODULE_ENABLE_REG 0xa5 + +#define SWITCH_INT_REG 0xd0 +#define SWITCH_INT_MASK_REG 0xd1 + +#define SFP_SELECT_REG 0x60 +#define SFP_NON_SELECT 0 +#define SFP_PORT_1 1 +#define SFP_PORT_2 2 +#define SFP_PORT_MGM 3 + +#define SFP_TX_REG 0x70 +#define SFP_PRESENT_REG 0x80 +#define SFP_RX_REG 0x90 +#define SFP_INT_REG 0xd0 + +#define SFP_PORT_1_ON 1 +#define SFP_PORT_1_OFF 2 +#define SFP_PORT_2_ON 3 +#define SFP_PORT_2_OFF 4 +#define SFP_PORT_MGM_ON 5 +#define SFP_PORT_MGM_OFF 6 + +#define PSU_INT_REG 0xd0 +#define SYS_INT_MASK_REG 0xd1 + +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.c new file mode 100644 index 0000000000..20d34c8e28 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.c @@ -0,0 +1,171 @@ +/* An hwmon driver for Cameo esc600-128Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esc600-128q.h" +#include "x86-64-cameo-esc600-128q-common.h" +#include "x86-64-cameo-esc600-128q-thermal.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t line_card_temp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + /*LINE_CARD_UP*/ + case LINE_CARD_1_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_1_UP_TEMP_REG); + break; + case LINE_CARD_2_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_2_UP_TEMP_REG); + break; + case LINE_CARD_3_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_3_UP_TEMP_REG); + break; + case LINE_CARD_4_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_4_UP_TEMP_REG); + break; + case LINE_CARD_5_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_5_UP_TEMP_REG); + break; + case LINE_CARD_6_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_6_UP_TEMP_REG); + break; + case LINE_CARD_7_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_7_UP_TEMP_REG); + break; + case LINE_CARD_8_UP_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_8_UP_TEMP_REG); + break; + /*LINE_CARD_DOWN*/ + case LINE_CARD_1_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_1_DN_TEMP_REG); + break; + case LINE_CARD_2_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_2_DN_TEMP_REG); + break; + case LINE_CARD_3_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_3_DN_TEMP_REG); + break; + case LINE_CARD_4_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_4_DN_TEMP_REG); + break; + case LINE_CARD_5_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_5_DN_TEMP_REG); + break; + case LINE_CARD_6_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_6_DN_TEMP_REG); + break; + case LINE_CARD_7_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_7_DN_TEMP_REG); + break; + case LINE_CARD_8_DN_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LINE_CARD_8_DN_TEMP_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case NCT7511_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, NCT7511_TEMP_REG); + break; + case LEFT_BOT_SB_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LEFT_BOT_SB_TEMP_REG); + break; + case CTR_TOP_SB_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, CTR_TOP_SB_TEMP_REG); + break; + case CTR_SB_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, CTR_SB_TEMP_REG); + break; + case LEFT_TOP_CB_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LEFT_TOP_CB_TEMP_REG); + break; + case CTR_CB_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, CTR_CB_TEMP_REG); + break; + case RIGHT_BOT_CB_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, RIGHT_BOT_CB_TEMP_REG); + break; + case LEFT_BOT_CB_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, LEFT_BOT_CB_TEMP_REG); + break; + case IO_BOARD_TEMP: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, IO_BOARD_TEMP_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_max_get(struct device *dev, struct device_attribute *da, char *buf) +{ + sprintf(buf, ""); + /*TBD*/ + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_min_get(struct device *dev, struct device_attribute *da, char *buf) +{ + sprintf(buf, ""); + /*TBD*/ + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_crit_get(struct device *dev, struct device_attribute *da, char *buf) +{ + sprintf(buf, ""); + /*TBD*/ + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_lcrit_get(struct device *dev, struct device_attribute *da, char *buf) +{ + sprintf(buf, ""); + /*TBD*/ + return sprintf(buf, "%s\n", buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.h new file mode 100644 index 0000000000..e8a3f1aa79 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q-thermal.h @@ -0,0 +1,73 @@ +/* register offset define */ +#define LINE_CARD_1_UP_TEMP_REG 0x20 +#define LINE_CARD_2_UP_TEMP_REG 0x22 +#define LINE_CARD_3_UP_TEMP_REG 0x24 +#define LINE_CARD_4_UP_TEMP_REG 0x26 +#define LINE_CARD_5_UP_TEMP_REG 0x28 +#define LINE_CARD_6_UP_TEMP_REG 0x2a +#define LINE_CARD_7_UP_TEMP_REG 0x2c +#define LINE_CARD_8_UP_TEMP_REG 0x2e + +#define LINE_CARD_1_DN_TEMP_REG 0x21 +#define LINE_CARD_2_DN_TEMP_REG 0x23 +#define LINE_CARD_3_DN_TEMP_REG 0x25 +#define LINE_CARD_4_DN_TEMP_REG 0x27 +#define LINE_CARD_5_DN_TEMP_REG 0x29 +#define LINE_CARD_6_DN_TEMP_REG 0x2b +#define LINE_CARD_7_DN_TEMP_REG 0x2d +#define LINE_CARD_8_DN_TEMP_REG 0x2f + +#define NCT7511_TEMP_REG 0x08 +#define LEFT_BOT_SB_TEMP_REG 0x09 +#define CTR_TOP_SB_TEMP_REG 0x10 +#define CTR_SB_TEMP_REG 0x11 +#define LEFT_TOP_CB_TEMP_REG 0x13 +#define CTR_CB_TEMP_REG 0x14 +#define RIGHT_BOT_CB_TEMP_REG 0x15 +#define LEFT_BOT_CB_TEMP_REG 0x16 +#define IO_BOARD_TEMP_REG 0x17 + +#define TEMP_R_B_F_REG 0x10 +#define TEMP_R_B_B_REG 0x11 +#define TEMP_R_B_F_MAX_REG 0x12 +#define TEMP_R_B_F_MIN_REG 0x13 +#define TEMP_R_B_F_CRIT_REG 0x14 +#define TEMP_R_B_F_LCRIT_REG 0x15 +#define TEMP_R_B_B_MAX_REG 0x16 +#define TEMP_R_B_B_MIN_REG 0x17 +#define TEMP_R_B_B_CRIT_REG 0x18 +#define TEMP_R_B_B_LCRIT_REG 0x19 + +#define TEMP_L_B_F_REG 0x20 +#define TEMP_L_B_B_REG 0x21 +#define TEMP_L_B_F_MAX_REG 0x22 +#define TEMP_L_B_F_MIN_REG 0x23 +#define TEMP_L_B_F_CRIT_REG 0x24 +#define TEMP_L_B_F_LCRIT_REG 0x25 +#define TEMP_L_B_B_MAX_REG 0x26 +#define TEMP_L_B_B_MIN_REG 0x27 +#define TEMP_L_B_B_CRIT_REG 0x28 +#define TEMP_L_B_B_LCRIT_REG 0x29 + +#define TEMP_R_T_F_REG 0x30 +#define TEMP_R_T_B_REG 0x31 +#define TEMP_R_T_F_MAX_REG 0x32 +#define TEMP_R_T_F_MIN_REG 0x33 +#define TEMP_R_T_F_CRIT_REG 0x34 +#define TEMP_R_T_F_LCRIT_REG 0x35 +#define TEMP_R_T_B_MAX_REG 0x36 +#define TEMP_R_T_B_MIN_REG 0x37 +#define TEMP_R_T_B_CRIT_REG 0x38 +#define TEMP_R_T_B_LCRIT_REG 0x39 + +#define TEMP_L_T_F_REG 0x40 +#define TEMP_L_T_B_REG 0x41 +#define TEMP_L_T_F_MAX_REG 0x42 +#define TEMP_L_T_F_MIN_REG 0x43 +#define TEMP_L_T_F_CRIT_REG 0x44 +#define TEMP_L_T_F_LCRIT_REG 0x45 +#define TEMP_L_T_B_MAX_REG 0x46 +#define TEMP_L_T_B_MIN_REG 0x47 +#define TEMP_L_T_B_CRIT_REG 0x48 +#define TEMP_L_T_B_LCRIT_REG 0x49 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.c b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.c deleted file mode 100644 index 18fbf781e9..0000000000 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.c +++ /dev/null @@ -1,4545 +0,0 @@ -/* An hwmon driver for Cameo ESC600-128Q i2c Module */ -#pragma GCC diagnostic ignored "-Wformat-zero-length" -#include "x86-64-cameo-esc600-128q.h" - -/* Addresses scanned */ -static const unsigned short normal_i2c[] = { 0x30, 0x31, 0x33, I2C_CLIENT_END }; - -/*function */ -/*0x31 CPLD-1 700HC*/ -#ifdef LED_CTRL_WANTED -/********************************************************************************/ -/* Function Name : led_ctrl_get */ -/* Description : This is the function to get Ctrl LED Reg 0x31 0xa0 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == LED_CTRL) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa0); //to get register 0x31 0xa0 - debug_print((KERN_DEBUG "DEBUG : LED_CTRL status = %x\n",status)); - sprintf(buf, ""); - if (status & res) - { - sprintf(buf, "%sFront port LED is enabled\n", buf); - } - else - { - sprintf(buf, "%sFront port LED is disabled\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : led_ctrl_set */ -/* Description : This is the function to set Ctrl LED Reg 0x31 0xa0 */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = 0; - u8 value = 0; - u8 result = 0; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_3_data = i2c_get_clientdata(Cameo_CPLD_3_client); - - mutex_lock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : led_ctrl_set lock\n")); - if (attr->index == LED_CTRL) - { - i = simple_strtol(buf, NULL, 10); - switch(i) - { - case TURN_ON: - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa0); //to get register 0x31 0xa0 - debug_print((KERN_ALERT "DEBUG : LED_CTRL status = %x\n",status)); - value = status | LED_ON; - debug_print((KERN_ALERT "DEBUG : LED_CTRL value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xa0, value); //to set register 0x31 0xa0 - debug_print((KERN_ALERT "DEBUG : LED_CTRL result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: led_ctrl_set on FAILED!\n"); - } - else - { - debug_print((KERN_ALERT "DEBUG : Fiber LED is Enable\n")); - } - break; - - case TURN_OFF: - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa0); //to get register 0x31 0xa0 - debug_print((KERN_DEBUG "DEBUG : LED_CTRL status = %x\n",status)); - value = status & LED_OFF; - debug_print((KERN_DEBUG "DEBUG : LED_CTRL value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xa0, value); //to set register 0x31 0xa0 - debug_print((KERN_DEBUG "DEBUG : LED_CTRL result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: led_ctrl_set off FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "DEBUG : Fiber LED is Disable\n")); - } - break; - - default: - printk(KERN_ALERT "LED set wrong Value\n"); - } - } - mutex_unlock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : led_ctrl_set unlock\n")); - return count; -} -#endif - -/********************************************************************************/ -/* Function Name : sensor_status_get */ -/* Description : This is the function to get thermal sensor alert */ -/* status 0x31 0xc0 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sensor_status_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc0); //to get register 0x31 0xc0 - debug_print((KERN_DEBUG "DEBUG : sensor_status_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SENSOR_STATUS) - { - for (i = 1; i <= 6; i++) - { - switch(i) - { - case ALERT_TH0: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by ALERT_TH0 (LM63)\n", buf); - } - break; - - case ALERT_TH1: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by ALERT_TH1\n", buf); - } - break; - - case ALERT_TH2: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by ALERT_TH2\n", buf); - } - break; - - case ALERT_TH3: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by ALERT_TH3\n", buf); - } - break; - - case ALERT_TH4: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by ALERT_TH4\n", buf); - } - break; - - case ALERT_TH5: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by ALERT_TH5 (IO Board)\n", buf); - } - break; - } - res = res << 1; - } - if(status == 0xf) - { - sprintf(buf, "%sNo interrupt is triggered\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sersor_status_mask_all_get */ -/* Description : This is the function to get all thermal sensor alert */ -/* status mask 0x31 0xc1 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sersor_status_mask_all_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc1); //to get register 0x31 0xc1 - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_all_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SENSOR_STATUS_MASK) - { - for (i = 1; i <= 6; i++) - { - switch(i) - { - case ALERT_TH0_MASK: - if (status & res) - { - sprintf(buf, "%sALERT_TH1 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH1 Mask is disabled\n", buf); - } - break; - case ALERT_TH1_MASK: - if (status & res) - { - sprintf(buf, "%sALERT_TH2 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH2 Mask is disabled\n", buf); - } - break; - case ALERT_TH2_MASK: - if (status & res) - { - sprintf(buf, "%sALERT_TH3 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH3 Mask is disabled\n", buf); - } - break; - case ALERT_TH3_MASK: - if (status & res) - { - sprintf(buf, "%sALERT_TH4 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH4 Mask is disabled\n", buf); - } - break; - case ALERT_TH4_MASK: - if (status & res) - { - sprintf(buf, "%sALERT_TH5 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH5 Mask is disabled\n", buf); - } - break; - case ALERT_TH5_MASK: - if (status & res) - { - sprintf(buf, "%sALERT_TH6 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH6 Mask is disabled\n", buf); - } - break; - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sersor_status_mask_get */ -/* Description : This is the function to get thermal sensor alert */ -/* status mask 0x31 0xc1 */ -/* Input(s) : attr->index. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sersor_status_mask_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc1); //to get register 0x31 0xc1 - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_get status = %x\n",status)); - sprintf(buf, ""); - switch(attr->index) - { - case ALERT_TH0_MASK: - if (status & 0x1) - { - sprintf(buf, "%sALERT_TH1 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH1 Mask is disabled\n", buf); - } - break; - case ALERT_TH1_MASK: - if (status & 0x2) - { - sprintf(buf, "%sALERT_TH2 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH2 Mask is disabled\n", buf); - } - break; - case ALERT_TH2_MASK: - if (status & 0x4) - { - sprintf(buf, "%sALERT_TH3 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH3 Mask is disabled\n", buf); - } - break; - case ALERT_TH3_MASK: - if (status & 0x8) - { - sprintf(buf, "%sALERT_TH4 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH4 Mask is disabled\n", buf); - } - break; - case ALERT_TH4_MASK: - if (status & 0x10) - { - sprintf(buf, "%sALERT_TH5 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH5 Mask is disabled\n", buf); - } - break; - case ALERT_TH5_MASK: - if (status & 0x20) - { - sprintf(buf, "%sALERT_TH6 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH6 Mask is disabled\n", buf); - } - break; - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sersor_status_mask_set */ -/* Description : This is the function to set thermal sensor alert */ -/* status mask 0x31 0xc1 */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t sersor_status_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 result = 0; - int i = 0; - int j = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_3_data = i2c_get_clientdata(Cameo_CPLD_3_client); - - i = attr->index; - j = simple_strtol(buf, NULL, 10); //get input ON or OFF - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set i: %d\n", i)); - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set j: %d\n", j)); - mutex_lock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set lock\n")); - if (i >= 1 && i <= 6) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc1); //to get register 0x31 0xc1 - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set status = %x\n",status)); - if( j == TURN_ON) - { - status |= (1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xc1, status); //to set register 0x31 0xc1 - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sersor_status_mask_%d set ON FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "sersor_status_mask_set %02d ON\n", i)); - } - } - else if( j == TURN_OFF) - { - status &= ~(1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xc1, status); //to set register 0x31 0xc1 - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sersor_status_mask_%d set set OFF FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "sersor_status_mask_set %02d OFF\n", i)); - } - } - else - { - printk(KERN_ALERT "sersor_status_mask_%d set wrong value\n", i); - } - } - mutex_unlock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sersor_status_mask_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : switch_alarm_get */ -/* Description : This is the function to get thermal sensor alert */ -/* status switch board 0x31 0xc2 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_alarm_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - res = 0x1; - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc2); //to get register 0x31 0xc2 - debug_print((KERN_DEBUG "DEBUG : switch_alarm_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SWITCH_ALARM) - { - for (i = 1; i <= 4; i++) - { - if ( i == SW_ALERT_TH0) - { - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by SW_ALERT_TH0\n", buf); - } - } - else if( i == SW_ALERT_TH1) - { - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by SW_ALERT_TH1\n", buf); - } - } - else if( i == SW_ALERT_TH2) - { - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by SW_ALERT_TH2\n", buf); - } - } - else if( i == SW_ALERT_TH3) - { - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by SW_ALERT_TH3\n", buf); - } - } - res = res << 1; - } - if(status == 0xf) - { - sprintf(buf, "%sNo interrupt is triggered\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_alarm_mask_all_get */ -/* Description : This is the function to get all thermal sensor alert */ -/* status switch board mask 0x31 0xc3 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_alarm_mask_all_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc3); //to get register 0x31 0xc3 - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_all_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SWITCH_ALARM_MASK) - { - for (i = 1; i <= 4; i++) - { - if ( i == SW_ALERT_TH0) - { - if (status & res) - { - sprintf(buf, "%sSW_ALERT_TH1 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSW_ALERT_TH1 Mask is disabled\n", buf); - } - } - else if( i == SW_ALERT_TH1) - { - if (status & res) - { - sprintf(buf, "%sSW_ALERT_TH2 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSW_ALERT_TH2 Mask is disabled\n", buf); - } - } - else if( i == SW_ALERT_TH2) - { - if (status & res) - { - sprintf(buf, "%sSW_ALERT_TH3 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSW_ALERT_TH3 Mask is disabled\n", buf); - } - } - else if( i == SW_ALERT_TH3) - { - if (status & res) - { - sprintf(buf, "%sSW_ALERT_TH4 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSW_ALERT_TH4 Mask is disabled\n", buf); - } - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_alarm_mask_get */ -/* Description : This is the function to get thermal sensor alert */ -/* status switch board mask 0x31 0xc3 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_alarm_mask_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc3); //to get register 0x31 0xc3 - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SW_ALERT_TH0_MASK) - { - if (status & 0x1) - { - sprintf(buf, "%sALERT_TH1 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH1 Mask is disabled\n", buf); - } - } - else if(attr->index == SW_ALERT_TH1_MASK) - { - if (status & 0x2) - { - sprintf(buf, "%sALERT_TH2 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH2 Mask is disabled\n", buf); - } - } - else if(attr->index == SW_ALERT_TH2_MASK) - { - if (status & 0x4) - { - sprintf(buf, "%sALERT_TH3 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH3 Mask is disabled\n", buf); - } - } - else if(attr->index == SW_ALERT_TH3_MASK) - { - if (status & 0x8) - { - sprintf(buf, "%sALERT_TH4 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sALERT_TH4 Mask is disabled\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_alarm_mask_set */ -/* Description : This is the function to set thermal sensor alert */ -/* status switch board mask 0x31 0xc3 */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t switch_alarm_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 result = 0; - int i = 0; - int j = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_3_data = i2c_get_clientdata(Cameo_CPLD_3_client); - - i = attr->index; - j = simple_strtol(buf, NULL, 10); - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set i: %d\n", i)); - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set j: %d\n", j)); - mutex_lock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set lock\n")); - if (i >= 1 && i <= 4) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xc3); //to get register 0x31 0xc3 - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set status = %x\n",status)); - if( j == TURN_ON) - { - status |= (1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xc3, status); //to set register 0x31 0xc3 - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_alarm_mask_%d set ON FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "switch_alarm_mask_set %02d ON\n", i)); - } - } - else if( j == TURN_OFF) - { - status &= ~(1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xc3, status); //to set register 0x31 0xc3 - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_alarm_mask_%d set set OFF FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "switch_alarm_mask_set %02d OFF\n", i)); - } - } - else - { - printk(KERN_ALERT "switch_alarm_mask_%d set wrong value\n", i); - } - } - mutex_unlock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_alarm_mask_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : sensor_int_get */ -/* Description : This is the function to get thermal sensor interrupt */ -/* 0x31 0xd0 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sensor_int_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xd0); //to get register 0x31 0xd0 - debug_print((KERN_DEBUG "DEBUG : sensor_int_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SENSOR_INT) - { - for (i = 1; i <= 2; i++) - { - if ( i == SENSOR_INT_0) - { - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by Switch Board\n", buf); - } - } - else if( i == SENSOR_INT_1) - { - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by Carrier Board\n", buf); - } - } - res = res << 1; - } - if(status == 0x3) - { - sprintf(buf, "%sNo interrupt is triggered\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sersor_int_mask_all_get */ -/* Description : This is function to get all thermal sensor interrupt */ -/* mask 0x31 0xd1 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sersor_int_mask_all_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xd1); //to get register 0x31 0xd1 - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_all_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SENSOR_STATUS_MASK) - { - for (i = 1; i <= 2; i++) - { - if ( i == SENSOR_INT_0) - { - if (status & res) - { - sprintf(buf, "%sSENSOR_INT_1 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSENSOR_INT_1 Mask is disabled\n", buf); - } - } - else if( i == SENSOR_INT_1) - { - if (status & res) - { - sprintf(buf, "%sSENSOR_INT_2 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSENSOR_INT_2 Mask is disabled\n", buf); - } - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sersor_int_mask_get */ -/* Description : This is the function to get thermal sensor interrupt */ -/* mask 0x31 0xd1 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sersor_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xd1); //to get register 0x31 0xd1 - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SENSOR_INT_0_MASK) - { - if (status & 0x1) - { - sprintf(buf, "%sSENSOR_INT_1 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSENSOR_INT_1 Mask is disabled\n", buf); - } - } - else if(attr->index == SENSOR_INT_1_MASK) - { - if (status & 0x2) - { - sprintf(buf, "%sSENSOR_INT_2 Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSENSOR_INT_2 Mask is disabled\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sersor_int_mask_set */ -/* Description : This is the function to set thermal sensor interrupt */ -/* mask 0x31 0xd1 */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t sersor_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 result = 0; - int i = 0; - int j = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_3_data = i2c_get_clientdata(Cameo_CPLD_3_client); - - i = attr->index; - j = simple_strtol(buf, NULL, 10); - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set i: %d\n", i)); - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set j: %d\n", j)); - mutex_lock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set lock\n")); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xd1); //to get register 0x31 0xd1 - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set status = %x\n",status)); - if( j == TURN_ON) - { - status |= (1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xd1, status); //to set register 0x31 0xd1 - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sersor_int_mask_%d set ON FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "sersor_int_mask_set %02d ON\n", i)); - } - } - else if( j == TURN_OFF) - { - status &= ~(1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xd1, status); //to set register 0x31 0xd1 - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sersor_int_mask_%d set set OFF FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "sersor_int_mask_set %02d OFF\n", i)); - } - } - else - { - printk(KERN_ALERT "sersor_int_mask_%d set wrong value\n", i); - } - - mutex_unlock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sersor_int_mask_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : fan_status_get */ -/* Description : This is the function to get fan status 0x30 0x00 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -/*0x30 CPLD-1 640UHC*/ -static ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 bmc_present = -EPERM; - u8 mask = 0x1; - u8 res = 0x1; - u16 fan_speed; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *target_client = NULL; - - debug_print((KERN_DEBUG "DEBUG : fan_status_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == FAN_STATUS) - { - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0xe9); //to get register 0x14 0xe9 - } - else - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_4_client, 0xa1); //to get register 0x35 0xa1 - } - for (i = 1; i <= 8; i++) - { - if ( i >= 5 && i <= 8 ) - { - if (status & res) - { - sprintf(buf, "%sFan module %d status is Good\n", buf, i-4); - } - else - { - sprintf(buf, "%sFan module %d status is Fail\n", buf, i-4); - } - } - res = res << 1; - } - } - else if (attr->index == FAN_SPEED_RPM) - { - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - target_client = Cameo_BMC_client; - res = i2c_smbus_read_byte_data(Cameo_BMC_client, 0xe9); //to get register 0x14 0xe9 - } - else - { - target_client = Cameo_CPLD_4_client; - res = i2c_smbus_read_byte_data(Cameo_CPLD_4_client, 0xa1); //to get register 0x35 0xa1 - } - if(res < 0) { - sprintf(buf, "%sCheck fan present error\n", buf); - return sprintf(buf, "%s\n",buf); - } - for(i=0; i<4; i++) - { - // skip the fan which is not present - if(!(res & (0x01<index == FAN_INSERT) - { - for (i = 1; i <= 4; i++) - { - if (status & res) - { - sprintf(buf, "%sFan module %d is Insert\n", buf, i); - } - else - { - sprintf(buf, "%sFan module %d is Absent\n", buf, i); - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : fan_power_get */ -/* Description : This is the function to get fan power 0x30 0x02 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 bmc_present = -EPERM; - u8 mask = 0x1; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0xea); //to get register 0x14 0xe9 - } - else - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_4_client, 0xa2); //to get register 0x35 0xa1 - } - debug_print((KERN_DEBUG "DEBUG : fan_power_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == FAN_POWER) - { - for (i = 1; i <= 8; i++) - { - if ( i >= 5 && i <= 8 ) - { - if (status & res) - { - sprintf(buf, "%sFan module %d status is Power ON\n", buf, i-4); - } - else - { - sprintf(buf, "%sFan module %d status is Power OFF\n", buf, i-4); - } - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : fan_direct_get */ -/* Description : This is the function to get fan direct 0x30 0x03 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t fan_direct_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 bmc_present = -EPERM; - u8 mask = 0x1; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0xea); //to get register 0x14 0xe9 - } - else - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_4_client, 0xa2); //to get register 0x35 0xa1 - } - debug_print((KERN_DEBUG "DEBUG : fan_direct_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == FAN_DIRECT) - { - for (i = 1; i <= 4; i++) - { - if (status & res) - { - sprintf(buf, "%sFan module %d direction is OUT\n", buf, i); - } - else - { - sprintf(buf, "%sFan module %d direction is IN\n", buf, i); - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : usb_power_get */ -/* Description : This is the function to get usb power 0x30 0xa0 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t usb_power_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == USB_POWER) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa0); //to get register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : USB_POWER status = %x\n",status)); - sprintf(buf, ""); - if (status & res) - { - sprintf(buf, "%sUSB Power is ON\n", buf); - } - else - { - sprintf(buf, "%sUSB Power is OFF\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : usb_power_set */ -/* Description : This is the function to set usb power 0x30 0xa0 */ -/* */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t usb_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_2_data = i2c_get_clientdata(Cameo_CPLD_2_client); - - mutex_lock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : usb_power_set lock\n")); - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa0); //to get register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : usb_power_set status = %x\n",status)); - if (attr->index == USB_POWER) - { - i = simple_strtol(buf, NULL, 10); //get input ON or OFF - if (i == TURN_ON) - { - value = status | USB_ON; - debug_print((KERN_DEBUG "DEBUG : usb_power_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa0, value); //to set register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : usb_power_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: usb_ctrl_set ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "USB Power is ON\n")); - } - } - else if (i == TURN_OFF) - { - value = status & USB_OFF; - debug_print((KERN_DEBUG "DEBUG : usb_power_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa0, value); //to set register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : usb_power_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: usb_power_set OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "USB Power is OFF\n")); - } - } - else - { - printk(KERN_ALERT "USB_POWER set wrong Value\n"); - } - } - mutex_unlock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : usb_power_set unlock\n")); - return count; -} - -#ifdef WDT_CTRL_WANTED -/********************************************************************************/ -/* Function Name : wdt_status_get */ -/* Description : This is the function to get WDT timer */ -/* */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t wdt_status_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x10; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == WDT_CTRL) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa0); //to get register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : WDT status = %x\n",status)); - sprintf(buf, ""); - if (status & res) - { - sprintf(buf, "%sWDT is Enable\n", buf); - } - else - { - sprintf(buf, "%sWDT is Disable\n", buf); - } - } - return sprintf(buf, "%s", buf); -} -/********************************************************************************/ -/* Function Name : wdt_status_set */ -/* Description : This is the function to set WDT timer */ -/* */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t wdt_status_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_2_data = i2c_get_clientdata(Cameo_CPLD_2_client); - - mutex_lock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : wdt_status_set lock\n")); - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa0); //to get register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : wdt_status_set status = %x\n",status)); - if (attr->index == WDT_CTRL) - { - i = simple_strtol(buf, NULL, 10); //get input ON or OFF - if (i == TURN_ON) - { - value = status | 0x10; - debug_print((KERN_DEBUG "DEBUG : wdt_status_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa0, value); //to set register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : wdt_status_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: usb_ctrl_set ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "WDT is Enable\n")); - } - } - else if (i == TURN_OFF) - { - value = status & 0xef; - debug_print((KERN_DEBUG "DEBUG : wdt_status_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa0, value); //to set register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : wdt_status_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: wdt_status_set OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "WDT is Disable\n")); - } - } - else - { - printk(KERN_ALERT "WDT set wrong Value\n"); - } - } - mutex_unlock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : wdt_status_set unlock\n")); - return count; -} -#endif /*WDT_CTRL_WANTED*/ -/********************************************************************************/ -/* Function Name : shutdown_sys_get */ -/* Description : This is the function to get shutdown status */ -/* */ -/* Input(s) : 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -static ssize_t shutdown_sys_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x10; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == SYS_SHUTDOWN) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa1); //to get register 0x30 0xa1 - debug_print((KERN_DEBUG "DEBUG : Shutdown status = %x\n",status)); - sprintf(buf, ""); - if (status & res) - { - sprintf(buf, "%sShutdown is triggered\n", buf); - } - else - { - sprintf(buf, "%sShutdown is not triggered\n", buf); - } - } - return sprintf(buf, "%s", buf); -} -/********************************************************************************/ -/* Function Name : shutdown_sys_set */ -/* Description : This is the function to set shutdown status */ -/* */ -/* Input(s) : 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -static ssize_t shutdown_sys_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_2_data = i2c_get_clientdata(Cameo_CPLD_2_client); - - mutex_lock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : shutdown_sys_set lock\n")); - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa1); //to get register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : shutdown_sys_set status = %x\n",status)); - if (attr->index == WDT_CTRL) - { - i = simple_strtol(buf, NULL, 10); //get input ON or OFF - if (i == TURN_ON) - { - value = status | 0x10; - debug_print((KERN_DEBUG "DEBUG : shutdown_sys_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa1, value); //to set register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : shutdown_sys_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: usb_ctrl_set ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "Shutdown is Enable\n")); - } - } - else if (i == TURN_OFF) - { - value = status & 0xef; - debug_print((KERN_DEBUG "DEBUG : shutdown_sys_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa1, value); //to set register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : shutdown_sys_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: shutdown_sys_set OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "Shutdown is Disable\n")); - } - } - else - { - printk(KERN_ALERT "Shutdown set wrong Value\n"); - } - } - mutex_unlock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : shutdown_sys_set unlock\n")); - return count; -} -/********************************************************************************/ -/* Function Name : reset_sys_set */ -/* Description : This is the function to reset system 0x30 0xa1 */ -/* */ -/* Input(s) : 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t reset_sys_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = 0; - u8 value = 0; - u8 result = 0; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_2_data = i2c_get_clientdata(Cameo_CPLD_2_client); - - mutex_lock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : reset_sys_set lock\n")); - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa1); //to get register 0x30 0xa1 - debug_print((KERN_DEBUG "DEBUG : SYS_RESET status = %x\n",status)); - if (attr->index == SYS_RESET) - { - i = simple_strtol(buf, NULL, 10); //get input 0 to reset system - if (i == 0) - { - value = 0x0; //value 0 to reset system - debug_print((KERN_DEBUG "DEBUG : reset_sys_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa1, value); //to set register 0x30 0xa1 - debug_print((KERN_DEBUG "DEBUG : reset_sys_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: reset_sys_set set FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "Switch is reset\n")); - } - } - else - { - printk(KERN_ALERT "reset_sys_set set wrong Value\n"); - } - } - mutex_unlock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : reset_sys_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : module_reset_set */ -/* Description : This is the function to reset PHY module 0x30 0xa2 */ -/* */ -/* Input(s) : PHY module number. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t module_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 result = 0; - int card_num = 0; - int input = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_2_data = i2c_get_clientdata(Cameo_CPLD_2_client); - - if (attr->index == MODULE_RESET) - { - input = simple_strtol(buf, NULL, 10); //get input module number - if(input <= 0 || input > 8) - { - printk(KERN_ALERT "ERROR: module_reset_%d RESET FAILED!\n", input); - } - else - { - mutex_lock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : module_reset_set lock\n")); - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa2); //to get register 0x30 0xa2 - debug_print((KERN_DEBUG "DEBUG : module_reset_set status = %x\n",status)); - status &= ~(1 << (input-1)); - debug_print((KERN_DEBUG "DEBUG : module_reset_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa2, status); //to set register 0x30 0xa2 - debug_print((KERN_DEBUG "DEBUG : module_reset_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: module_reset_%d RESET FAILED!\n", card_num); - } - else - { - debug_print((KERN_DEBUG "module_reset_%02d SUCCESS\n", card_num)); - } - } - } - mutex_unlock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : module_reset_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : module_insert_get */ -/* Description : This is the function to get module insert 0x30 0xa3 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t module_insert_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa3); //get slot present status 0x30 0xa3 - debug_print((KERN_DEBUG "DEBUG : module_insert_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == MODULE_INSERT) - { - for (i = 1; i <= 8; i++) - { - if (status & res) - { - sprintf(buf, "%sModule %d is present\n", buf , i); - } - else - { - sprintf(buf, "%sModule %d is not present\n", buf, i); - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} -/********************************************************************************/ -/* Function Name : module_power_get */ -/* Description : This is the function to get module insert 0x30 0xa3 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t module_power_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa4); //get slot present status 0x30 0xa3 - debug_print((KERN_DEBUG "DEBUG : module_power_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == MODULE_POWER) - { - for (i = 1; i <= 8; i++) - { - if (status & res) - { - sprintf(buf, "%sModule %d is power good\n", buf , i); - } - else - { - sprintf(buf, "%sModule %d is not power good\n", buf, i); - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : module_12v_status_get */ -/* Description : This is the function to get module insert 0x30 0xa3 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t module_12v_status_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa5); //get slot present status 0x30 0xa3 - debug_print((KERN_DEBUG "DEBUG : module_12v_status_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == MODULE_12V_STAT) - { - for (i = 1; i <= 8; i++) - { - if (status & res) - { - sprintf(buf, "%sModule %d 12V is enable\n", buf , i); - } - else - { - sprintf(buf, "%sModule %d 12V is disable\n", buf, i); - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : module_enable_get */ -/* Description : This is the function to get module insert 0x30 0xa3 */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t module_enable_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xa5); //get slot present status 0x30 0xa3 - debug_print((KERN_DEBUG "DEBUG : module_enable_get status = %x\n",status)); - if (attr->index == MODULE_ENABLE) - { - sprintf(buf, "%s0x%x\n", buf, status); - } - return sprintf(buf, "%s", buf); -} -/********************************************************************************/ -/* Function Name : module_enable_set */ -/* Description : This is the function to reset PHY module 0x30 0xa2 */ -/* */ -/* Input(s) : PHY module number. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t module_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 result = 0; - int input = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_2_data = i2c_get_clientdata(Cameo_CPLD_2_client); - - if (attr->index == MODULE_ENABLE) - { - input = simple_strtol(buf, NULL, 16); //get input module number - debug_print((KERN_DEBUG "DEBUG : module_enable_set input = %x \n",input)); - - mutex_lock(&CPLD_2_data->update_lock); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xa5, input); //to set register 0x30 0xa2 - debug_print((KERN_DEBUG "DEBUG : module_enable_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: module RESET FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "module enable SUCCESS\n")); - } - mdelay(1000); - } - mutex_unlock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : module_enable_set unlock\n")); - return count; -} -/********************************************************************************/ -/* Function Name : switch_int_get */ -/* Description : This is the function to get switch interrupt status */ -/* 0x30 0xd0 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_int_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xd0); //to get register 0x30 0xd0 - debug_print((KERN_DEBUG "DEBUG : switch_int_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SWITCH_INT) - { - for (i = 1; i <= 6; i++) - { - switch(i) - { - case MODULE_INS_INT: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by Module insert\n", buf); - } - break; - case MODULE_INT: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by Module\n", buf); - } - break; - case MODULE_POWER_INT: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by Module Power\n", buf); - } - break; - case THER_SENSOR_INT: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by Thermal Sensor\n", buf); - } - break; - case IO_BOARD_INT: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by IO Board\n", buf); - } - break; - case FAN_ERROR_INT: - if (!(status & res)) - { - sprintf(buf, "%sInterrupt is triggered by FAN ERROR\n", buf); - } - break; - } - res = res << 1; - } - if(status == 0xf) - { - sprintf(buf, "%sNo interrupt is triggered\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_int_mask_all_get */ -/* Description : This is the function to get all switch interrupt */ -/* mask status 0x30 0xd1 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_int_mask_all_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xd1); //to get register 0x30 0xd1 - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_all_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SWITCH_INT_MASK) - { - for (i = 1; i <= 6; i++) - { - switch(i) - { - case MODULE_INS_INT_MASK: - if (status & res) - { - sprintf(buf, "%sModule insert interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sModule insert interrupt Mask is disabled\n", buf); - } - break; - case MODULE_INT_MASK: - if (status & res) - { - sprintf(buf, "%sModule interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sModule interrupt Mask is disabled\n", buf); - } - break; - case MODULE_POW_INT_MASK: - if (status & res) - { - sprintf(buf, "%sModule power interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sModule power interrupt Mask is disabled\n", buf); - } - break; - case THER_SEN_INT_MASK: - if (status & res) - { - sprintf(buf, "%sThermal Sensor interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sThermal Sensor interrupt Mask is disabled\n", buf); - } - break; - case IO_BOARD_INT_MASK: - if (status & res) - { - sprintf(buf, "%sIO Board interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sIO Board interrupt Mask is disabled\n", buf); - } - break; - case FAN_ERROR_INT_MASK: - if (status & res) - { - sprintf(buf, "%sFan error interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sFan error interrupt Mask is disabled\n", buf); - } - break; - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_int_mask_get */ -/* Description : This is the function to get switch interrupt */ -/* mask status 0x30 0xd1 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xd1); //to get register 0x30 0xd1 - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_get status = %x\n",status)); - sprintf(buf, ""); - switch(attr->index) - { - case MODULE_INS_INT_MASK: - if (status & 0x1) - { - sprintf(buf, "%sModule insert interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sModule insert interrupt Mask is disabled\n", buf); - } - break; - case MODULE_INT_MASK: - if (status & 0x2) - { - sprintf(buf, "%sModule interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sModule interrupt Mask is disabled\n", buf); - } - break; - case MODULE_POW_INT_MASK: - if (status & 0x4) - { - sprintf(buf, "%sModule power interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sModule power interrupt Mask is disabled\n", buf); - } - break; - case THER_SEN_INT_MASK: - if (status & 0x8) - { - sprintf(buf, "%sThermal Sensor interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sThermal Sensor interrupt Mask is disabled\n", buf); - } - break; - case IO_BOARD_INT_MASK: - if (status & 0x10) - { - sprintf(buf, "%sIO Board interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sIO Board interrupt Mask is disabled\n", buf); - } - break; - case FAN_ERROR_INT_MASK: - if (status & 0x20) - { - sprintf(buf, "%sFan error interrupt Mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sFan error interrupt Mask is disabled\n", buf); - } - break; - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_int_mask_set */ -/* Description : This is the function to set switch interrupt */ -/* mask status 0x30 0xd1 */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None . */ -/********************************************************************************/ -static ssize_t switch_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 result = 0; - int i = 0; - int j = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_2_data = i2c_get_clientdata(Cameo_CPLD_2_client); - - i = attr->index; - j = simple_strtol(buf, NULL, 10); - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set i: %d\n", i)); - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set j: %d\n", j)); - mutex_lock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set lock\n")); - if (i >= 1 && i <= 6) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0xd1); //to get register 0x30 0xd1 - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set status = %x\n",status)); - if( j == TURN_ON) - { - status |= (1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xd1, status); //to set register 0x30 0xd1 - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_int_mask_%d set ON FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "switch_int_mask_set %02d ON\n", i)); - } - } - else if( j == TURN_OFF) - { - status &= ~(1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_2_client, 0xd1, status); //to set register 0x30 0xd1 - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_int_mask_%d set set OFF FAILED!\n", i); - } - else - { - debug_print((KERN_DEBUG "switch_int_mask_set %02d OFF\n", i)); - } - } - else - { - printk(KERN_ALERT "switch_int_mask_%d set wrong value\n", i); - } - } - mutex_unlock(&CPLD_2_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_int_mask_set unlock\n")); - return count; -} - -/*0x33 I/O Board CPLD*/ -/********************************************************************************/ -/* Function Name : sfp_select_get */ -/* Description : This is the function to get sfp i2c interface */ -/* status 0x33 0x20 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sfp_select_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == SFP_SELECT) - { - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0x60); //to get register 0x33 0x60 - debug_print((KERN_DEBUG "DEBUG : SFP_SELECT status = %x\n",status)); - sprintf(buf, ""); - if (status & 0x1) - { - sprintf(buf, "%sI2C interface is set Port 1\n", buf); - } - else if (status & 0x2) - { - sprintf(buf, "%sI2C interface is set Port 2\n", buf); - } - else if (status & 0x3) - { - sprintf(buf, "%sI2C interface is set Port MGM\n", buf); - } - else - { - sprintf(buf, "%sI2C interface is NOT SET\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sfp_select_set */ -/* Description : This is the function to set sfp i2c interface */ -/* status 0x33 0x20 */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t sfp_select_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sfp_select_set lock\n")); - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0x60); //to get register 0x33 0x60 - debug_print((KERN_DEBUG "DEBUG : sfp_select_set status = %x\n",status)); - if (attr->index == SFP_SELECT) - { - i = simple_strtol(buf, NULL, 10); - if (i == 0) - { - value = 0x0; - debug_print((KERN_DEBUG "DEBUG : sfp_select_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x60, value); //to set register 0x33 0x60 - debug_print((KERN_DEBUG "DEBUG : sfp_select_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: I2C interface is set Port 1 FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "I2C interface is NOT set\n")); - } - } - else if (i == 1) - { - value = 0x1; - debug_print((KERN_DEBUG "DEBUG : sfp_select_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x60, value); //to set register 0x33 0x60 - debug_print((KERN_DEBUG "DEBUG : sfp_select_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: I2C interface is set Port 1 FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "I2C interface is set Port 1\n")); - } - } - else if (i == 2) - { - value = 0x2; - debug_print((KERN_DEBUG "DEBUG : sfp_select_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x60, value); //to set register 0x33 0x60 - debug_print((KERN_DEBUG "DEBUG : sfp_select_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: I2C interface is set Port 2 FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "I2C interface is set Port 2\n")); - } - } - else if (i == 3) - { - value = 0x3; - debug_print((KERN_DEBUG "DEBUG : sfp_select_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x60, value); //to set register 0x33 0x60 - debug_print((KERN_DEBUG "DEBUG : sfp_select_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: I2C interface is set Port MGM FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "I2C interface is set Port MGM\n")); - } - } - else - { - printk(KERN_ALERT "SFP_SELECT set wrong Value\n"); - } - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sfp_select_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : sfp_tx_get */ -/* Description : This is the function to get sfp tx status */ -/* 0x33 0x70 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sfp_tx_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0x70); //to get register 0x33 0x70 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SFP_TX_DISABLE) - { - for (i = 1; i <= 3; i++) - { - if ( i == SFP_PORT_1) - { - if (status & res) - { - sprintf(buf, "%sTX of SFP port 1 is disabled\n", buf); - } - else - { - sprintf(buf, "%sTX of SFP port 1 is enabled\n", buf); - } - } - else if( i == SFP_PORT_2) - { - if (status & res) - { - sprintf(buf, "%sTX of SFP port 2 is disabled\n", buf); - } - else - { - sprintf(buf, "%sTX of SFP port 2 is enabled\n", buf); - } - } - else if( i == SFP_PORT_MGM) - { - if (status & res) - { - sprintf(buf, "%sTX of SFP port MGM is disabled\n", buf); - } - else - { - sprintf(buf, "%sTX of SFP port MGM is enabled\n", buf); - } - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sfp_tx_set */ -/* Description : This is the function to set sfp tx status */ -/* 0x33 0x70 */ -/* Input(s) : 1 ~ 4. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t sfp_tx_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set lock\n")); - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0x70); //to get register 0x33 0xa0 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set status = %x\n",status)); - if (attr->index == SFP_TX_DISABLE) - { - i = simple_strtol(buf, NULL, 10); - if (i == SFP_PORT_1_OFF) //i = 1 - { - value = status | 0x1; - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x70, value); //to set register 0x33 0xa0 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sfp_tx_set PORT_1 OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SFP_PORT_1 is OFF\n")); - } - } - else if (i == SFP_PORT_1_ON) //i = 2 - { - value = status & 0xfe; - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x70, value); //to set register 0x33 0xa0 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sfp_tx_set PORT_1 ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SFP_PORT_1 is ON\n")); - } - } - else if (i == SFP_PORT_2_OFF) //i = 3 - { - value = status | 0x2; - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x70, value); //to set register 0x33 0xa0 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sfp_tx_set PORT_2 OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SFP_PORT_2 is OFF\n")); - } - } - else if (i == SFP_PORT_2_ON) //i = 4 - { - value = status & 0xfd; - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x70, value); //to set register 0x33 0xa0 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sfp_tx_set PORT_2 ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SFP_PORT_2 is ON\n")); - } - } - else if (i == SFP_PORT_MGM_OFF) //i = 5 - { - value = status | 0x4; - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x70, value); //to set register 0x33 0xa0 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sfp_tx_set MGM OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SFP_PORT_MGM is OFF\n")); - } - } - else if (i == SFP_PORT_MGM_ON) //i = 6 - { - value = status & 0xfb; - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0x70, value); //to set register 0x33 0xa0 - debug_print((KERN_DEBUG "DEBUG : sfp_tx_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sfp_tx_set MGM ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SFP_PORT_MGM is ON\n")); - } - } - else - { - printk(KERN_ALERT "SFP_TX set wrong Value\n"); - } - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : usb_power_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : sfp_insert_get */ -/* Description : This is the function to get sfp insert status */ -/* 0x33 0x80 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sfp_insert_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0x80); //to get register 0x33 0x80 - debug_print((KERN_DEBUG "DEBUG : sfp_insert_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SFP_INSERT) - { - for (i = 1; i <= 3; i++) - { - if ( i == SFP_PORT_1) - { - if (status & res) - { - sprintf(buf, "%sSFP port 1 is not present\n", buf); - } - else - { - sprintf(buf, "%sSFP port 1 is present\n", buf); - } - } - else if( i == SFP_PORT_2) - { - if (status & res) - { - sprintf(buf, "%sSFP port 2 is not present\n", buf); - } - else - { - sprintf(buf, "%sSFP port 2 is present\n", buf); - } - } - else if( i == SFP_PORT_MGM) - { - if (status & res) - { - sprintf(buf, "%sSFP port MGM is not present\n", buf); - } - else - { - sprintf(buf, "%sSFP port MGM is present\n", buf); - } - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sfp_rx_get */ -/* Description : This is the function to get sfp rx loss status */ -/* 0x33 0x90 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sfp_rx_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0x90); //to get register 0x33 0x90 - debug_print((KERN_DEBUG "DEBUG : sfp_rx_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SFP_RX_LOSS) - { - for (i = 1; i <= 3; i++) - { - if ( i == SFP_PORT_1) - { - if (status & res) - { - sprintf(buf, "%sSFP port 1 receiver loss of signal\n", buf); - } - else - { - sprintf(buf, "%sSFP port 1 receiver signal is detceted\n", buf); - } - } - else if( i == SFP_PORT_2) - { - if (status & res) - { - sprintf(buf, "%sSFP port 2 receiver loss of signal\n", buf); - } - else - { - sprintf(buf, "%sSFP port 2 receiver signal is detceted\n", buf); - } - } - else if( i == SFP_PORT_MGM) - { - if (status & res) - { - sprintf(buf, "%sSFP port MGM receiver loss of signal\n", buf); - } - else - { - sprintf(buf, "%sSFP port MGM receiver signal is detceted\n", buf); - } - } - res = res << 1; - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : psu_status_get */ -/* Description : This is the function to get psu status */ -/* 0x33 0xa0 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 bmc_present = -EPERM; - u8 res = 0x1; - u8 mask = 0x1; - int i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0xe8); //to get register 0x14 0xe8 - } - else - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_4_client, 0xa0); //to get register 0x35 0xa0 - } - debug_print((KERN_DEBUG "DEBUG : psu_status_get status = %x\n",status)); - sprintf(buf, ""); - switch (attr->index) - { - case PSU_PRESENT: - res = 0x1; - for (i = 1; i <= 4; i++) - { - if (status & res) - { - sprintf(buf, "%sPSU %d is present\n", buf, i); - } - else - { - sprintf(buf, "%sPSU %d is not present\n", buf, i); - } - res = res << 1; - } - break; - case PSU_STATUS: - res = 0x1; - for (i = 1; i <= 8; i++) - { - if (i >= 5 && i <=8) - { - if (status & res) - { - sprintf(buf, "%sPSU %d is not power good\n", buf, i - 4); - } - else - { - sprintf(buf, "%sPSU %d is power good\n", buf, i - 4); - } - } - res = res << 1; - } - break; - } - return sprintf(buf, "%s", buf); -} - -#ifdef LINEAR_CONVERT_FUNCTION -static long read_reg_linear(s32 data) -{ - s16 exponent; - s32 mantissa; - long val; - - exponent = ((s16)data) >> 11; - mantissa = ((s16)((data & 0x7ff) << 5)) >> 5; - - val = mantissa; - val = val * 1000L; - - if (exponent >= 0) - val <<= exponent; - else - val >>= -exponent; - - return val/1000; -} -#endif /*LINEAR_CONVERT_FUNCTION*/ -/********************************************************************************/ -/* Function Name : switch_button_get */ -/* Description : This is the function to get switch button status */ -/* 0x33 0xa1 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_button_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa1); //to get register 0x33 0xa1 - debug_print((KERN_DEBUG "DEBUG : switch_button_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SWITCH_BUTTON) - { - if (status & res) - { - sprintf(buf, "%sSwitch button is normal\n", buf); - } - else - { - sprintf(buf, "%sSwitch button is press and hold\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sys_led_get */ -/* Description : This is the function to get switch sys LED status */ -/* 0x33 0xa2 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sys_led_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - int led_a_status = 0; - int led_g_status = 0; - int led_b_status = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa2); //to get register 0x33 0xa2 - debug_print((KERN_DEBUG "DEBUG : sys_led_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == SYS_LED) - { - for (i = 1; i <= 3; i++) - { - if ( i == SYS_LED_A) - { - if (status & res) - { - led_a_status = TURN_ON; - } - else - { - led_a_status = TURN_OFF; - } - } - else if( i == SYS_LED_G) - { - if (status & res) - { - led_g_status = TURN_ON; - } - else - { - led_g_status = TURN_OFF; - } - } - else if( i == SYS_LED_BLINK) - { - if (status & res) - { - led_b_status = TURN_ON; - } - else - { - led_b_status = TURN_OFF; - } - } - res = res << 1; - } - - if(led_a_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSYS LED is set to amber and blink\n", buf); - } - else if(led_a_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSYS LED is set to amber\n", buf); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSYS LED is set to green and blink\n", buf); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSYS LED is set to green\n", buf); - } - else - { - sprintf(buf, "%sSYS LED is set OFF\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : sys_led_Set */ -/* Description : This is the function to set switch sys LED status */ -/* 0x33 0xa2 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sys_led_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sys_led_set lock\n")); - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa2); //to get register 0x33 0xa2 - debug_print((KERN_DEBUG "DEBUG : sys_led_set status = %x\n",status)); - if (attr->index == SYS_LED) - { - i = simple_strtol(buf, NULL, 10); - switch(i) - { - case SYS_LED_OFF: - value = 0x0; - debug_print((KERN_DEBUG "DEBUG : sys_led_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa2, value); //to set register 0x33 0xa2 - debug_print((KERN_DEBUG "DEBUG : sys_led_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sys_led_set SYS_LED_OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SYS LED is set OFF\n")); - } - break; - case SYS_LED_A_N: - value = 0x1; - debug_print((KERN_DEBUG "DEBUG : sys_led_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa2, value); //to set register 0x33 0xa2 - debug_print((KERN_DEBUG "DEBUG : sys_led_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sys_led_set SYS_LED_A_N FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SYS LED is set Amber\n")); - } - break; - case SYS_LED_A_B: - value = 0x5; - debug_print((KERN_DEBUG "DEBUG : sys_led_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa2, value); //to set register 0x33 0xa2 - debug_print((KERN_DEBUG "DEBUG : sys_led_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sys_led_set SYS_LED_A_B FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SYS LED is set Amber and Blink\n")); - } - break; - case SYS_LED_G_N: - value = 0x2; - debug_print((KERN_DEBUG "DEBUG : sys_led_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa2, value); //to set register 0x33 0xa2 - debug_print((KERN_DEBUG "DEBUG : sys_led_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sys_led_set SYS_LED_G_N FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SYS LED is set Green\n")); - } - break; - case SYS_LED_G_B: - value = 0x6; - debug_print((KERN_DEBUG "DEBUG : sys_led_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa2, value); //to set register 0x33 0xa2 - debug_print((KERN_DEBUG "DEBUG : sys_led_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: sys_led_set SYS_LED_G_B FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "SYS LED is set Green and Blink\n")); - } - break; - default: - printk(KERN_ALERT "SYS LED set wrong Value\n"); - } - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : sys_led_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : switch_led_all_get */ -/* Description : This is the function to get all switch LED status */ -/* 0x33 0xa3 ~ 0xa8 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_led_all_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 a_shift = 0x1; - u8 g_shift = 0x2; - u8 b_shift = 0x1; -#ifdef LED_L3_CTRL_WANTED - u8 led_3_status = 0; - u8 led_3_blink = 0; -#endif /*LED_L3_CTRL_WANTED*/ - u8 led_4_status = 0; - u8 led_4_blink = 0; - u8 led_5_status = 0; - u8 led_5_blink = 0; - u8 led_status_reg = 0xa3; - u8 led_blink_reg = 0xa4; - int i; - int j; - int led_status[5][4] = {{0},{0}}; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -#ifdef LED_L3_CTRL_WANTED - led_3_status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); //to get register 0x33 0xa3 - led_3_blink = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); -#endif /*LED_L3_CTRL_WANTED*/ - led_4_status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); - led_4_blink = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); - led_5_status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa5); - led_5_blink = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa6); -#ifdef LED_L3_CTRL_WANTED - debug_print((KERN_DEBUG "DEBUG : switch_led_all_get led_3_status = %x\n", led_3_status)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_get led_3_blink = %x\n", led_3_blink)); -#endif /*LED_L3_CTRL_WANTED*/ - debug_print((KERN_DEBUG "DEBUG : switch_led_all_get led_4_status = %x\n", led_4_status)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_get led_4_blink = %x\n", led_4_blink)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_get led_5_status = %x\n", led_5_status)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_get led_5_blink = %x\n", led_5_blink)); - sprintf(buf, ""); - if (attr->index == SWITCH_LED) - { -#ifdef LED_L3_CTRL_WANTED - for(i = 3; i<= 5; i++) -#else - for(i = 4; i<= 5; i++) -#endif /*LED_L3_CTRL_WANTED*/ - { - a_shift = 0x1; - g_shift = 0x2; - b_shift = 0x1; - for(j = 1; j<= 4; j++) - { - if (i2c_smbus_read_byte_data(ESC_600_128q_client, led_status_reg) & a_shift) - { - if(i2c_smbus_read_byte_data(ESC_600_128q_client, led_blink_reg) & b_shift) - { - led_status[i][j] = SWITCH_LED_A_B; - sprintf(buf, "%sSwitch LED %d-%d is set to amber and blink\n", buf, i, j); - } - else - { - led_status[i][j] = SWITCH_LED_A_N; - sprintf(buf, "%sSwitch LED %d-%d is set to amber\n", buf, i, j); - } - } - else if (i2c_smbus_read_byte_data(ESC_600_128q_client, led_status_reg) & g_shift) - { - if(i2c_smbus_read_byte_data(ESC_600_128q_client, led_blink_reg) & b_shift) - { - led_status[i][j] = SWITCH_LED_G_B; - sprintf(buf, "%sSwitch LED %d-%d is set to green and blink\n", buf, i, j); - } - else - { - led_status[i][j] = SWITCH_LED_G_N; - sprintf(buf, "%sSwitch LED %d-%d is set to green\n", buf, i, j); - } - } - else - { - led_status[i][j] = SWITCH_LED_OFF; - sprintf(buf, "%sSwitch LED %d-%d is set OFF\n", buf, i, j); - } - a_shift = a_shift<< 2; - g_shift = g_shift<< 2; - b_shift = b_shift<< 1; - } - led_status_reg = led_status_reg + 0x2; - led_blink_reg = led_blink_reg + 0x2; - } - - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_led_all_set */ -/* Description : This is the function to set all switch LED status */ -/* 0x33 0xa3 ~ 0xa8 */ -/* Input(s) : 0 ~ 4. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t switch_led_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 led_value = -EPERM; - u8 blink_value = -EPERM; -#ifdef LED_L3_CTRL_WANTED - u8 led_3_status = 0; - u8 led_3_blink = 0; -#endif /*LED_L3_CTRL_WANTED*/ - u8 led_4_status = 0; - u8 led_4_blink = 0; - u8 led_5_status = 0; - u8 led_5_blink = 0; - u8 result = 0; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set lock\n")); -#ifdef LED_L3_CTRL_WANTED - led_3_status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); //to get register 0x33 0xa3 - led_3_blink = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); -#endif /*LED_L3_CTRL_WANTED*/ - led_4_status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); - led_4_blink = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); - led_5_status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa5); - led_5_blink = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa6); -#ifdef LED_L3_CTRL_WANTED - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set led_3_status = %x\n", led_3_status)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set led_3_blink = %x\n", led_3_blink)); -#endif /*LED_L3_CTRL_WANTED*/ - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set led_4_status = %x\n", led_4_status)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set led_4_blink = %x\n", led_4_blink)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set led_5_status = %x\n", led_5_status)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set led_5_blink = %x\n", led_5_blink)); - if (attr->index == SWITCH_LED) - { - i = simple_strtol(buf, NULL, 10); - switch(i) - { - case SWITCH_LED_OFF: - led_value = 0x0; - blink_value = 0x0; - break; - case SWITCH_LED_A_N: - led_value = 0x55; - blink_value = 0x0; - break; - case SWITCH_LED_A_B: - led_value = 0x55; - blink_value = 0xf; - break; - case SWITCH_LED_G_N: - led_value = 0xaa; - blink_value = 0x0; - break; - case SWITCH_LED_G_B: - led_value = 0xaa; - blink_value = 0xf; - break; - default: - printk(KERN_ALERT "switch_led_all_set set wrong Value\n"); - } - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set led_value = %x\n",led_value)); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set blink_value = %x\n",blink_value)); -#ifdef LED_L3_CTRL_WANTED - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa3, led_value); -#endif /*LED_L3_CTRL_WANTED*/ - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa3, led_value); - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa5, led_value); -#ifdef LED_L3_CTRL_WANTED - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa4, blink_value); -#endif /*LED_L3_CTRL_WANTED*/ - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa4, blink_value); - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa6, blink_value); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_led_all_set OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "Switch LED ALL set %d \n", i)); - } - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_all_set unlock\n")); - return count; -} -#ifdef LED_L3_CTRL_WANTED -/********************************************************************************/ -/* Function Name : switch_led_3_get */ -/* Description : This is the function to get switch LED 3 status */ -/* 0x33 0xa3 0xa4 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_led_3_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - int led_a_status = 0; - int led_g_status = 0; - int led_b_status = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); //to get register 0x33 0xa3 - debug_print((KERN_DEBUG "DEBUG : switch_led_3_get status = %x\n",status)); - sprintf(buf, ""); - for (i = 1; i <= 8; i++) - { - if ( i == attr->index) - { - if (status & res) - { - led_a_status = TURN_ON; - } - else - { - led_a_status = TURN_OFF; - } - } - res = res << 1; - if( i == (attr->index + 1) ) - { - if (status & res) - { - led_g_status = TURN_ON; - } - else - { - led_g_status = TURN_OFF; - } - } - res = res << 1; - } - res = 0x1; - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); - debug_print((KERN_DEBUG "DEBUG : switch_led_3_get status = %x\n",status)); - for (i = 1; i <= 4; i++) - { - if ( i == attr->index) - { - if (status & res) - { - led_b_status = TURN_ON; - } - else - { - led_b_status = TURN_OFF; - } - } - res = res << 1; - } - - if(led_a_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSwitch LED 3-%d is set to amber and blink\n", buf, attr->index); - } - else if(led_a_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSwitch LED 3-%d is set to amber\n", buf, attr->index); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSwitch LED 3-%d is set to green and blink\n", buf, attr->index); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSwitch LED 3-%d is set to green\n", buf, attr->index); - } - else - { - sprintf(buf, "%sSwitch LED 3-%d is set OFF\n", buf, attr->index); - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_led_3_set */ -/* Description : This is the function to set switch LED 3 status */ -/* 0x33 0xa3 0xa4 */ -/* Input(s) : 0 ~ 4. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t switch_led_3_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 led_value = -EPERM; - u8 blk_value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set lock\n")); - led_value = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); //to get register 0x33 0xa3 - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set led_value = %x\n",led_value)); - blk_value = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set blk_value = %x\n",blk_value)); - if (attr->index != 0) - { - i = simple_strtol(buf, NULL, 10); - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set value = %d\n",i)); - switch(i) - { - case SWITCH_LED_OFF: - led_value &= ~(1 << ((attr->index)-1)); - led_value &= ~(1 << (attr->index)); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_A_N: - led_value |= (1 << ((attr->index)-1)); - led_value &= ~(1 << (attr->index)); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_A_B: - led_value |= (1 << ((attr->index)-1)); - led_value &= ~(1 << (attr->index)); - blk_value |= (1 << ((attr->index)-1)); - break; - case SWITCH_LED_G_N: - led_value |= (1 << (attr->index)); - led_value &= ~(1 << ((attr->index)-1)); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_G_B: - led_value |= (1 << (attr->index)); - led_value &= ~(1 << ((attr->index)-1)); - blk_value |= (1 << ((attr->index)-1)); - break; - default: - printk(KERN_ALERT "Switch LED set wrong Value\n"); - } - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set led_value = %x\n",led_value)); - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set blk_value = %x\n",blk_value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa3, led_value); - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa4, blk_value); - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_led_3_set SYS_LED_OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "Switch LED is set Success\n")); - } - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_3_set unlock\n")); - return count; -} -#endif /*LED_L3_CTRL_WANTED*/ - -/********************************************************************************/ -/* Function Name : switch_led_4_get */ -/* Description : This is the function to get switch LED 4 status */ -/* 0x33 0xa5 0xa6 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_led_4_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - int led_a_status = 0; - int led_g_status = 0; - int led_b_status = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); //to get register 0x33 0xa5 - debug_print((KERN_DEBUG "DEBUG : switch_led_4_get status = %x\n",status)); - sprintf(buf, ""); - for (i = 1; i <= 4; i++) - { - if ( i == attr->index) - { - if (status & res) - { - led_a_status = TURN_ON; - } - else - { - led_a_status = TURN_OFF; - } - } - res = res << 1; - if( i == (attr->index + 1) ) - { - if (status & res) - { - led_g_status = TURN_ON; - } - else - { - led_g_status = TURN_OFF; - } - } - res = res << 1; - } - res = 0x1; - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_get status = %x\n",status)); - for (i = 1; i <= 4; i++) - { - if ( i == attr->index) - { - if (status & res) - { - led_b_status = TURN_ON; - } - else - { - led_b_status = TURN_OFF; - } - } - res = res << 1; - } - - if(led_a_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSwitch LED 4-%d is set to amber and blink\n", buf, attr->index); - } - else if(led_a_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSwitch LED 4-%d is set to amber\n", buf, attr->index); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSwitch LED 4-%d is set to green and blink\n", buf, attr->index); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSwitch LED 4-%d is set to green\n", buf, attr->index); - } - else - { - sprintf(buf, "%sSwitch LED 4-%d is set OFF\n", buf, attr->index); - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_led_4_set */ -/* Description : This is the function to set switch LED 4 status */ -/* 0x33 0xa5 0xa6 */ -/* Input(s) : 0 ~ 4. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t switch_led_4_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 led_value = -EPERM; - u8 blk_value = -EPERM; - u8 result = -EPERM; - u8 offset = 0; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set lock\n")); - led_value = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa3); //to get register 0x33 0xa5 - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set led_value = %x\n",led_value)); - blk_value = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa4); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set blk_value = %x\n",blk_value)); - if (attr->index != 0) - { - i = simple_strtol(buf, NULL, 10); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set value = %d\n",i)); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set led 4-%d\n",attr->index)); - if(attr->index == 1) - { - offset = 0; - } - else - { - offset = 2*((attr->index)-1); - } - switch(i) - { - case SWITCH_LED_OFF: //i=0 - led_value &= ~(0x03 << offset); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_A_N: //i=1 - led_value &= ~(0x03 << offset); - led_value |= (0x01 << offset); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_A_B: //i=2 - led_value &= ~(0x03 << offset); - led_value |= (0x01 << offset); - blk_value |= (1 << ((attr->index)-1)); - break; - case SWITCH_LED_G_N: //i=3 - led_value &= ~(0x03 << offset); - led_value |= (0x02 << offset); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_G_B: //i=4 - led_value &= ~(0x03 << offset); - led_value |= (0x02 << offset); - blk_value |= (1 << ((attr->index)-1)); - break; - default: - printk(KERN_ALERT "Switch LED set wrong Value\n"); - } - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set led_value = %x\n",led_value)); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set blk_value = %x\n",blk_value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa3, led_value); - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa4, blk_value); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_led_4_set SYS_LED_OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "Switch LED is set Success\n")); - } - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_4_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : switch_led_5_get */ -/* Description : This is the function to get switch LED 5 status */ -/* 0x33 0xa7 0xa8 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t switch_led_5_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x1; - int i; - int led_a_status = 0; - int led_g_status = 0; - int led_b_status = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa5); //to get register 0x33 0xa5 - debug_print((KERN_DEBUG "DEBUG : switch_led_5_get status = %x\n",status)); - sprintf(buf, ""); - for (i = 1; i <= 8; i++) - { - if ( i == attr->index) - { - if (status & res) - { - led_a_status = TURN_ON; - } - else - { - led_a_status = TURN_OFF; - } - } - res = res << 1; - if( i == (attr->index + 1) ) - { - if (status & res) - { - led_g_status = TURN_ON; - } - else - { - led_g_status = TURN_OFF; - } - } - res = res << 1; - } - res = 0x1; - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa6); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_get status = %x\n",status)); - for (i = 1; i <= 4; i++) - { - if ( i == attr->index) - { - if (status & res) - { - led_b_status = TURN_ON; - } - else - { - led_b_status = TURN_OFF; - } - } - res = res << 1; - } - - if(led_a_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSwitch LED 5-%d is set to amber and blink\n", buf, attr->index); - } - else if(led_a_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSwitch LED 5-%d is set to amber\n", buf, attr->index); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_ON) - { - sprintf(buf, "%sSwitch LED 5-%d is set to green and blink\n", buf, attr->index); - } - else if(led_g_status == TURN_ON && led_b_status == TURN_OFF) - { - sprintf(buf, "%sSwitch LED 5-%d is set to green\n", buf, attr->index); - } - else - { - sprintf(buf, "%sSwitch LED 5-%d is set OFF\n", buf, attr->index); - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : switch_led_5_set */ -/* Description : This is the function to set switch LED 5 status */ -/* 0x33 0xa7 0xa8 */ -/* Input(s) : 0 ~ 4. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t switch_led_5_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 led_value = -EPERM; - u8 blk_value = -EPERM; - u8 result = -EPERM; - u8 offset = 0; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set lock\n")); - led_value = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa5); //to get register 0x33 0xa5 - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set led_value = %x\n",led_value)); - blk_value = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xa6); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set blk_value = %x\n",blk_value)); - if (attr->index != 0) - { - i = simple_strtol(buf, NULL, 10); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set value = %d\n",i)); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set led 5-%d\n",attr->index)); - if(attr->index == 1) - { - offset = 0; - } - else - { - offset = 2*((attr->index)-1); - } - switch(i) - { - case SWITCH_LED_OFF: //i=0 - led_value &= ~(0x03 << offset); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_A_N: //i=1 - led_value &= ~(0x03 << offset); - led_value |= (0x01 << offset); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_A_B: //i=2 - led_value &= ~(0x03 << offset); - led_value |= (0x01 << offset); - blk_value |= (1 << ((attr->index)-1)); - break; - case SWITCH_LED_G_N: //i=3 - led_value &= ~(0x03 << offset); - led_value |= (0x02 << offset); - blk_value &= ~(1 << ((attr->index)-1)); - break; - case SWITCH_LED_G_B: //i=4 - led_value &= ~(0x03 << offset); - led_value |= (0x02 << offset); - blk_value |= (1 << ((attr->index)-1)); - break; - default: - printk(KERN_ALERT "Switch LED set wrong Value\n"); - } - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set led_value = %x\n",led_value)); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set blk_value = %x\n",blk_value)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa5, led_value); - result |= i2c_smbus_write_byte_data(ESC_600_128q_client, 0xa6, blk_value); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: switch_led_5_set SYS_LED_OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "Switch LED is set Success\n")); - } - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : switch_led_5_set unlock\n")); - return count; -} - -/********************************************************************************/ -/* Function Name : sfp_int_get */ -/* Description : This is the function to get sfp interrupt status */ -/* 0x33 0xd0 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t sfp_int_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == SFP_INT) - { - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xd0); //to set register 0x33 0xd0 - debug_print((KERN_DEBUG "DEBUG : sfp_int_get status = %x\n",status)); - sprintf(buf, ""); - if (status & 0x2) - { - sprintf(buf, "%sInterrupt is triggered by SFP Loss\n", buf); - } - else if (status & 0x4) - { - sprintf(buf, "%sInterrupt is triggered by SFP ABS\n", buf); - } - else - { - sprintf(buf, "%sNo interrupt is triggered\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : psu_int_get */ -/* Description : This is the function to get psu interrupt status */ -/* 0x33 0xd0 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t psu_int_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == PSU_INT) - { - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xd0); //to set register 0x33 0xd0 - debug_print((KERN_DEBUG "DEBUG : psu_int_get status = %x\n",status)); - sprintf(buf, ""); - if (status & 0x1) - { - sprintf(buf, "%sInterrupt is triggered by PSU\n", buf); - } - else - { - sprintf(buf, "%sNo interrupt is triggered\n", buf); - } - } - return sprintf(buf, "%s", buf); -} -/********************************************************************************/ -/* Function Name : int_mask_get */ -/* Description : This is the function to get interrupt status */ -/* 0x33 0xd1 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t int_mask_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xd1); //to get register 0x33 0xd1 - debug_print((KERN_DEBUG "DEBUG : int_mask_get status = %x\n",status)); - sprintf(buf, ""); - if (attr->index == 1) - { - - if (status & 0x1) - { - sprintf(buf, "%sPSU interrupt mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sPSU interrupt mask is disabled\n", buf); - } - } - if (attr->index == 2) - { - - if (status & 0x2) - { - sprintf(buf, "%sSFP Loss interrupt mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSFP Loss interrupt mask is disabled\n", buf); - } - } - if (attr->index == 3) - { - - if (status & 0x4) - { - sprintf(buf, "%sSFP ABS interrupt mask is enabled\n", buf); - } - else - { - sprintf(buf, "%sSFP ABS interrupt mask is disabled\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : int_mask_set */ -/* Description : This is the function to set interrupt status */ -/* 0x33 0xa3 0xa4 */ -/* Input(s) : 1 or 0. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 result = 0; - int i = 0; - int j = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *data = i2c_get_clientdata(ESC_600_128q_client); - - i = attr->index; - j = simple_strtol(buf, NULL, 10); - debug_print((KERN_DEBUG "DEBUG : int_mask_set i: %d\n", i)); - debug_print((KERN_DEBUG "DEBUG : int_mask_set j: %d\n", j)); - mutex_lock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : int_mask_set lock\n")); - - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0xd1); //to get register 0x33 0xd1 - debug_print((KERN_DEBUG "DEBUG : int_mask_set status = %x\n",status)); - if( j == TURN_ON) - { - status |= (1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : int_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xd1, status); //to set register 0x33 0xd1 - debug_print((KERN_DEBUG "DEBUG : int_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: int_mask_set set ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "int_mask_set ON\n")); - } - } - else if( j == TURN_OFF) - { - status &= ~(1 << (i-1)); - debug_print((KERN_DEBUG "DEBUG : int_mask_set value = %x\n",status)); - result = i2c_smbus_write_byte_data(ESC_600_128q_client, 0xd1, status); //to set register 0x33 0xd1 - debug_print((KERN_DEBUG "DEBUG : int_mask_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: int_mask_set set OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "int_mask_set OFF\n")); - } - } - else - { - printk(KERN_ALERT " int_mask_set set wrong value\n"); - } - mutex_unlock(&data->update_lock); - debug_print((KERN_DEBUG "DEBUG : int_mask_set unlock\n")); - return count; -} -#ifdef ESC_600_BMC_WANTED -static ssize_t bmc_module_detect(struct device *dev, struct device_attribute *da, char *buf) -{ - u32 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - sprintf(buf, ""); - if(attr->index == BMC_DETECT) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); - debug_print((KERN_DEBUG "DEBUG : BMC byte status = 0x%x\n", status)); - } - if(status == 0x1) - { - sprintf(buf, "%sBMC module is present\n", buf); - } - else - { - sprintf(buf, "%sBMC module is not present\n", buf); - } - return sprintf(buf, "%s", buf); -} -static ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 bmc_present = -EPERM; - u8 status = -EPERM; - u8 mask = 0x1; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - sprintf(buf, ""); - if (attr->index == SENSOR_TEMP) - { - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - //to get 0x14 0x08 NCT7511 Temp - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x08); - if(status == 0xff) - { - sprintf(buf, "%sSensor (NCT7511) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (NCT7511) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x09 Left-Bottom:SB - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x09); - if(status == 0xff) - { - sprintf(buf, "%sSensor (Left-Bottom:SB) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (Left-Bottom:SB) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x10 Center-Top:SB - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x10); - if(status == 0xff) - { - sprintf(buf, "%sSensor (Center-Top:SB) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (Center-Top:SB) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x11 Center:SB - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x11); - if(status == 0xff) - { - sprintf(buf, "%sSensor (Center:SB) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (Center:SB) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x13 Left-Top:CB - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x13); - if(status == 0xff) - { - sprintf(buf, "%sSensor (Left-Top:CB) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (Left-Top:CB) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x14 Center:CB - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x14); - if(status == 0xff) - { - sprintf(buf, "%sSensor (Center:CB) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (Center:CB) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x15 Right-Bottom:CB - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x15); - if(status == 0xff) - { - sprintf(buf, "%sSensor (Right-Bottom:CB) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (Right-Bottom:CB) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x16 Left-Bottom:CB - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x16); - if(status == 0xff) - { - sprintf(buf, "%sSensor (Left-Bottom:CB) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (Left-Bottom:CB) is %d degrees (C)\n", buf, status); - } - //to get 0x14 0x17 I/O Board - status = i2c_smbus_read_byte_data(Cameo_BMC_client, 0x17); - if(status == 0xff) - { - sprintf(buf, "%sSensor (I/O Board) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (I/O Board) is %d degrees (C)\n", buf, status); - } - } - else - { - sprintf(buf, "%sBMC Module is not present\n", buf); - } - } - return sprintf(buf, "%s", buf); -} -static ssize_t module_temp_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 bmc_present = -EPERM; - u8 up_reg [9] = {0x00, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e}; - u8 down_reg [9] = {0x00, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2b, 0x2d, 0x2f}; - u8 status = -EPERM; - u8 mask = 0x1; - u8 i = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - sprintf(buf, ""); - - if(attr->index == MODULE_TEMP) - { - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - for(i = 1; i <= 8; i ++) - { - //to get Line Card up Temp - status = i2c_smbus_read_byte_data(Cameo_BMC_client, up_reg[i]); - if(status == 0xff) - { - sprintf(buf, "%sLine Card %d up READ FAILED\n", buf, i); - } - else - { - sprintf(buf, "%sLine Card %d up is %d degrees (C)\n", buf, i, status); - } - //to get Line Card down Temp - status = i2c_smbus_read_byte_data(Cameo_BMC_client, down_reg[i]); - if(status == 0xff) - { - sprintf(buf, "%sLine Card %d down READ FAILED\n", buf, i); - } - else - { - sprintf(buf, "%sLine Card %d down is %d degrees (C)\n", buf, i, status); - } - } - } - else - { - sprintf(buf, "%sBMC Module is not present\n", buf); - } - } - return sprintf(buf, "%s", buf); -} -static ssize_t mac_temp_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 bmc_present = -EPERM; - u16 status = -EPERM; - u8 mask = 0x1; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - sprintf(buf, ""); - if (attr->index == MAC_TEMP) - { - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - //to get MAC Temp 0x14 0x12 - status = i2c_smbus_read_word_data(Cameo_BMC_client, 0x12); - if(status == 0xffff) - { - sprintf(buf, "%sSensor (MAC MCP3425) READ FAILED\n", buf); - } - else - { - sprintf(buf, "%sSensor (MAC MCP3425) is 0x%x\n", buf, status); - } - } - else - { - sprintf(buf, "%sBMC Module is not present\n", buf); - } - } - return sprintf(buf, "%s", buf); -} - -static int two_complement_to_int(u16 data, u8 valid_bit, int mask) -{ - u16 valid_data = data & mask; - bool is_negative = valid_data >> (valid_bit - 1); - - return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; -} - -static ssize_t psu_module_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 bmc_present = -EPERM; - u8 module_num = 0; - u8 psu_table [5][11] = - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xd8}, - {0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xd9}, - {0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xda}, - {0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xdb}, - }; - u32 psu_status [11] = {0}; - u8 mask = 0x1; - u8 i = 0; - u16 u16_val = 0; - int exponent = 0, mantissa = 0; - int multiplier = 1000; // lm-sensor uint: mV, mA, mC - - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - sprintf(buf, ""); - - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - switch(attr->index) - { - case PSU_MODULE_1: - module_num = 1; - break; - case PSU_MODULE_2: - module_num = 2; - break; - case PSU_MODULE_3: - module_num = 3; - break; - case PSU_MODULE_4: - module_num = 4; - break; - } - - for(i = 0; i < 10; i ++) - { - u16_val = i2c_smbus_read_word_data(Cameo_BMC_client, psu_table[module_num][i]); - /* word data with linear format */ - if (i != 2 && i != 8) { - multiplier = 1000; - if (i == 6 || i == 7) /* pin, pout */ - multiplier = 1000000; // lm-sensor unit: uW - if ( i == 5 ) /* fan_speed */ - multiplier = 1; - - exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); - mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); - psu_status[i] = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ - (mantissa*multiplier / (1 << -exponent)); - } - } - /* vout mode */ - multiplier = 1000; - u16_val = i2c_smbus_read_byte_data(Cameo_BMC_client, psu_table[module_num][10]); - psu_status[10] = u16_val; - exponent = two_complement_to_int(u16_val & 0x1f, 5, 0x1f); - /* vout */ - u16_val = i2c_smbus_read_word_data(Cameo_BMC_client, psu_table[module_num][2]); - psu_status[2] = (exponent >= 0) ? ((u16_val << exponent)*multiplier) : \ - (u16_val*multiplier / (1 << -exponent)); - - sprintf(buf, "%sPSU %d VIN is %d\n", buf, module_num, psu_status[0]); - sprintf(buf, "%sPSU %d IIN is %d\n", buf, module_num, psu_status[1]); - sprintf(buf, "%sPSU %d VOUT is %d\n", buf, module_num, psu_status[2]); - sprintf(buf, "%sPSU %d IOUT is %d\n", buf, module_num, psu_status[3]); - sprintf(buf, "%sPSU %d TEMP_1 is %d\n", buf, module_num, psu_status[4]); - sprintf(buf, "%sPSU %d FAN_SPEED is %d\n", buf, module_num, psu_status[5]); - sprintf(buf, "%sPSU %d POUT is %d\n", buf, module_num, psu_status[6]); - sprintf(buf, "%sPSU %d PIN is %d\n", buf, module_num, psu_status[7]); - sprintf(buf, "%sPSU %d MFR_MODEL is %d\n", buf, module_num, psu_status[8]); - sprintf(buf, "%sPSU %d MFR_IOUT_MAX is %d\n", buf, module_num, psu_status[9]); - sprintf(buf, "%sPSU %d VMODE is %d\n", buf, module_num, psu_status[10]); - } - else - { - sprintf(buf, "%sBMC Module is not present\n", buf); - } - return sprintf(buf, "%s", buf); -} -static ssize_t dc_chip_switch_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 bmc_present = -EPERM; - u8 dc_table [8] = {0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; - u16 dc_status [8] = {0}; - u8 mask = 0x1; - u8 i = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - sprintf(buf, ""); - if (attr->index == DC_CHIP_SWITCH) - { - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - for(i = 0; i < 8; i ++) - { - dc_status[i] = i2c_smbus_read_word_data(Cameo_BMC_client, dc_table[i]); - } - sprintf(buf, "%sTPS40425 0x6e 0x88 is 0x%x\n", buf, dc_status[0]); - sprintf(buf, "%sTPS40425 0x6e 0x8c is 0x%x\n", buf, dc_status[1]); - sprintf(buf, "%sTPS40425 0x6e 0x96 is 0x%x\n", buf, dc_status[2]); - sprintf(buf, "%sTPS40425 0x70 0x88 is 0x%x\n", buf, dc_status[3]); - sprintf(buf, "%sTPS40425 0x70 0x8c is 0x%x\n", buf, dc_status[4]); - sprintf(buf, "%sTPS40425 0x70 0x96 is 0x%x\n", buf, dc_status[5]); - /*0x04 TBD*/ - sprintf(buf, "%sISP1014A 0x04 0x00 is 0x%x\n", buf, dc_status[6]); - sprintf(buf, "%sISP1014A 0x04 0x00 is 0x%x\n", buf, dc_status[7]); - } - else - { - sprintf(buf, "%sBMC Module is not present\n", buf); - } - } - return sprintf(buf, "%s", buf); -} -static ssize_t dc_chip_slot_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 bmc_present = -EPERM; - u8 module_num = 0; - u8 dc_table [9][10] = - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x30, 0x31, 0x33, 0x34, 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c}, - {0x40, 0x41, 0x43, 0x44, 0x46, 0x47, 0x48, 0x49, 0x4b, 0x4c}, - {0x50, 0x51, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5b, 0x5c}, - {0x60, 0x61, 0x63, 0x64, 0x66, 0x67, 0x68, 0x69, 0x6b, 0x6c}, - {0x70, 0x71, 0x73, 0x74, 0x76, 0x77, 0x78, 0x79, 0x7b, 0x7c}, - {0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x89, 0x8b, 0x8c}, - {0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c}, - {0xa0, 0xa1, 0xa3, 0xa4, 0xa6, 0xa7, 0xa8, 0xa9, 0xab, 0xac}, - }; - u16 dc_status [10] = {0}; - u8 mask = 0x1; - u8 i = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - sprintf(buf, ""); - bmc_present = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa3); //to get 0x31 0xa3 - if (bmc_present & mask) - { - switch(attr->index) - { - case DC_CHIP_SLOT_1: - module_num = 1; - break; - case DC_CHIP_SLOT_2: - module_num = 2; - break; - case DC_CHIP_SLOT_3: - module_num = 3; - break; - case DC_CHIP_SLOT_4: - module_num = 4; - break; - case DC_CHIP_SLOT_5: - module_num = 5; - break; - case DC_CHIP_SLOT_6: - module_num = 6; - break; - case DC_CHIP_SLOT_7: - module_num = 7; - break; - case DC_CHIP_SLOT_8: - module_num = 8; - break; - } - for(i = 0; i < 10; i ++) - { - dc_status[i] = i2c_smbus_read_word_data(Cameo_BMC_client, dc_table[module_num][i]); - } - sprintf(buf, "%sLine Card %d Chip 1 P0_VOUT is 0x%x\n", buf, module_num, dc_status[0]); - sprintf(buf, "%sLine Card %d Chip 1 P0_IOUT is 0x%x\n", buf, module_num, dc_status[1]); - sprintf(buf, "%sLine Card %d Chip 1 P1_VOUT is 0x%x\n", buf, module_num, dc_status[2]); - sprintf(buf, "%sLine Card %d Chip 1 P1_IOUT is 0x%x\n", buf, module_num, dc_status[3]); - sprintf(buf, "%sLine Card %d Chip 2 P0_VOUT is 0x%x\n", buf, module_num, dc_status[4]); - sprintf(buf, "%sLine Card %d Chip 2 P0_IOUT is 0x%x\n", buf, module_num, dc_status[5]); - sprintf(buf, "%sLine Card %d Chip 3 P0_VOUT is 0x%x\n", buf, module_num, dc_status[6]); - sprintf(buf, "%sLine Card %d Chip 3 P0_IOUT is 0x%x\n", buf, module_num, dc_status[7]); - sprintf(buf, "%sLine Card %d Chip 3 P1_VOUT is 0x%x\n", buf, module_num, dc_status[8]); - sprintf(buf, "%sLine Card %d Chip 3 P1_IOUT is 0x%x\n", buf, module_num, dc_status[9]); - } - else - { - sprintf(buf, "%sBMC Module is not present\n", buf); - } - return sprintf(buf, "%s", buf); -} -#endif /*ESC_600_BMC_WANTED*/ -/********************************************************************************/ -/* Function Name : jtag_select_get */ -/* Description : This is the function to get JTAG Reg 0x31 0xa1 0xa2 */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : String. */ -/********************************************************************************/ -static ssize_t jtag_select_get(struct device *dev, struct device_attribute *da, char *buf) -{ - sprintf(buf, ""); - /*TBD*/ - return sprintf(buf, "%s", buf); -} - -/********************************************************************************/ -/* Function Name : jtag_select_set */ -/* Description : This is the function to set JTAG Reg 0x31 0xa1 0xa2 */ -/* Input(s) : Jtag number. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static ssize_t jtag_select_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - /*TBD*/ - return count; -} - -static ssize_t cpld_version_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - sprintf(buf, ""); - if(attr->index == CPLD_VER) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_2_client, 0x20); - sprintf(buf, "%s0x30 CPLD version is 0x%x\n", buf, status); - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0x20); - sprintf(buf, "%s0x31 CPLD version is 0x%x\n", buf, status); - status = i2c_smbus_read_byte_data(ESC_600_128q_client, 0x20); - sprintf(buf, "%s0x33 CPLD version is 0x%x\n", buf, status); - } - return sprintf(buf, "%s", buf); -} - -#ifdef EEPROM_WP_WANTED -static ssize_t eeprom_wp_status_get(struct device *dev, struct device_attribute *da, char *buf) -{ - u8 status = -EPERM; - u8 res = 0x10; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (attr->index == EEPROM_WP_CTRL) - { - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa0); //to get register 0x30 0xa0 - debug_print((KERN_DEBUG "DEBUG : eeprom_wp status = %x\n",status)); - sprintf(buf, ""); - if (status & res) - { - sprintf(buf, "%sEEPROM is Protected\n", buf); - } - else - { - sprintf(buf, "%sEEPROM is Not Protected\n", buf); - } - } - return sprintf(buf, "%s", buf); -} -static ssize_t eeprom_wp_status_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) -{ - u8 status = -EPERM; - u8 value = -EPERM; - u8 result = -EPERM; - u16 i; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct Cameo_i2c_data *CPLD_3_data = i2c_get_clientdata(Cameo_CPLD_3_client); - - mutex_lock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : eeprom_wp_status_set lock\n")); - status = i2c_smbus_read_byte_data(Cameo_CPLD_3_client, 0xa0); //to get register 0x31 0xa0 - debug_print((KERN_DEBUG "DEBUG : eeprom_wp_status_set status = %x\n",status)); - if (attr->index == EEPROM_WP_CTRL) - { - i = simple_strtol(buf, NULL, 10); //get input ON or OFF - if (i == TURN_ON) - { - value = status | 0x10; - debug_print((KERN_DEBUG "DEBUG : eeprom_wp_status_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xa0, value); //to set register 0x31 0xa0 - debug_print((KERN_DEBUG "DEBUG : eeprom_wp_status_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: usb_ctrl_set ON FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "EEPROM is Protected\n")); - } - } - else if (i == TURN_OFF) - { - value = status & 0xef; - debug_print((KERN_DEBUG "DEBUG : eeprom_wp_status_set value = %x\n",value)); - result = i2c_smbus_write_byte_data(Cameo_CPLD_3_client, 0xa0, value); //to set register 0x31 0xa0 - debug_print((KERN_DEBUG "DEBUG : eeprom_wp_status_set result = %x\n",result)); - if (result < 0) - { - printk(KERN_ALERT "ERROR: eeprom_wp_status_set OFF FAILED!\n"); - } - else - { - debug_print((KERN_DEBUG "EEPROM is Not Protected\n")); - } - } - else - { - printk(KERN_ALERT "EEPROM set wrong Value\n"); - } - } - mutex_unlock(&CPLD_3_data->update_lock); - debug_print((KERN_DEBUG "DEBUG : usb_power_set unlock\n")); - return count; -} -#endif /*EEPROM_WP_WANTED*/ -/* end of function */ -/********************************************************************************/ -/* Function Name : Cameo_i2c_probe */ -/* Description : To probe i2c device */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static int Cameo_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) -{ - struct Cameo_i2c_data *data; - struct Cameo_i2c_data *CPLD_2_data; - struct Cameo_i2c_data *CPLD_3_data; - struct Cameo_i2c_data *CPLD_4_data; - struct Cameo_i2c_data *Cameo_Extpand_1_data; - struct Cameo_i2c_data *Cameo_Extpand_2_data; - struct Cameo_i2c_data *Cameo_BMC_data; - - int status; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - { - status = -EIO; - goto exit; - } - data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); - if (!data) - { - printk(KERN_ALERT "data kzalloc fail\n"); - status = -ENOMEM; - goto exit; - } - CPLD_2_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); - if (!CPLD_2_data) - { - printk(KERN_ALERT "CPLD_2_data kzalloc fail\n"); - status = -ENOMEM; - goto exit; - } - CPLD_3_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); - if (!CPLD_3_data) - { - printk(KERN_ALERT "CPLD_3_data kzalloc fail\n"); - status = -ENOMEM; - goto exit; - } - CPLD_4_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); - if (!CPLD_4_data) - { - printk(KERN_ALERT "CPLD_4_data kzalloc fail\n"); - status = -ENOMEM; - goto exit; - } - Cameo_Extpand_1_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); - if (!Cameo_Extpand_1_data) - { - printk(KERN_ALERT "Cameo_Extpand_1_data kzalloc fail\n"); - status = -ENOMEM; - goto exit; - } - Cameo_Extpand_2_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); - if (!Cameo_Extpand_2_data) - { - printk(KERN_ALERT "Cameo_Extpand_2_data kzalloc fail\n"); - status = -ENOMEM; - goto exit; - } - Cameo_BMC_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); - if (!Cameo_BMC_data) - { - printk(KERN_ALERT "Cameo_BMC_data kzalloc fail\n"); - status = -ENOMEM; - goto exit; - } - i2c_set_clientdata(client , data); - i2c_set_clientdata(Cameo_CPLD_2_client , CPLD_2_data); - i2c_set_clientdata(Cameo_CPLD_3_client , CPLD_3_data); - i2c_set_clientdata(Cameo_CPLD_4_client , CPLD_4_data); - i2c_set_clientdata(Cameo_Extpand_1_client , Cameo_Extpand_1_data); - i2c_set_clientdata(Cameo_Extpand_2_client , Cameo_Extpand_2_data); - i2c_set_clientdata(Cameo_BMC_client , Cameo_BMC_data); - mutex_init(&CPLD_2_data ->update_lock); - mutex_init(&CPLD_3_data ->update_lock); - mutex_init(&CPLD_4_data ->update_lock); - mutex_init(&Cameo_Extpand_1_data ->update_lock); - mutex_init(&Cameo_Extpand_2_data ->update_lock); - mutex_init(&Cameo_BMC_data ->update_lock); - data->valid = 0; - mutex_init(&data->update_lock); - dev_info(&client->dev, "chip found\n"); - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &ESC600_SYS_group); - if (status) - { - goto exit_free; - } - status = sysfs_create_group(&client->dev.kobj, &ESC600_PSU_group); - if (status) - { - goto exit_free; - } -#ifdef ESC_600_JTAG_WANTED - status = sysfs_create_group(&client->dev.kobj, &ESC600_JTAG_group); - if (status) - { - goto exit_free; - } -#endif - status = sysfs_create_group(&client->dev.kobj, &ESC600_SFP_group); - if (status) - { - goto exit_free; - } -#ifdef ESC_600_MASK_WANTED - status = sysfs_create_group(&client->dev.kobj, &ESC600_MASK_group); - if (status) - { - goto exit_free; - } -#endif - status = sysfs_create_group(&client->dev.kobj, &ESC600_FAN_group); - if (status) - { - goto exit_free; - } - status = sysfs_create_group(&client->dev.kobj, &ESC600_USB_group); - if (status) - { - goto exit_free; - } - status = sysfs_create_group(&client->dev.kobj, &ESC600_LED_group); - if (status) - { - goto exit_free; - } - status = sysfs_create_group(&client->dev.kobj, &ESC600_Reset_group); - if (status) - { - goto exit_free; - } - status = sysfs_create_group(&client->dev.kobj, &ESC600_Sensor_group); - if (status) - { - goto exit_free; - } -#ifdef ESC_600_INT_WANTED - status = sysfs_create_group(&client->dev.kobj, &ESC600_INT_group); - if (status) - { - goto exit_free; - } -#endif - status = sysfs_create_group(&client->dev.kobj, &ESC600_Module_group); - if (status) - { - goto exit_free; - } - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) - { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - dev_info(&client->dev, "%s: '%s'\n", dev_name(data->hwmon_dev), client->name); - return 0; -exit_remove: - sysfs_remove_group(&client->dev.kobj, &ESC600_SYS_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_PSU_group); -#ifdef ESC_600_JTAG_WANTED - sysfs_remove_group(&client->dev.kobj, &ESC600_JTAG_group); -#endif - sysfs_remove_group(&client->dev.kobj, &ESC600_SFP_group); -#ifdef ESC_600_MASK_WANTED - sysfs_remove_group(&client->dev.kobj, &ESC600_MASK_group); -#endif - sysfs_remove_group(&client->dev.kobj, &ESC600_FAN_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_USB_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_LED_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_Reset_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_Sensor_group); -#ifdef ESC_600_INT_WANTED - sysfs_remove_group(&client->dev.kobj, &ESC600_INT_group); -#endif - sysfs_remove_group(&client->dev.kobj, &ESC600_Module_group); -exit_free: - kfree(data); -exit: - return status; -} - -static int Cameo_i2c_remove(struct i2c_client *client) -{ - struct Cameo_i2c_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ESC600_SYS_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_PSU_group); -#ifdef ESC_600_JTAG_WANTED - sysfs_remove_group(&client->dev.kobj, &ESC600_JTAG_group); -#endif - sysfs_remove_group(&client->dev.kobj, &ESC600_SFP_group); -#ifdef ESC_600_MASK_WANTED - sysfs_remove_group(&client->dev.kobj, &ESC600_MASK_group); -#endif - sysfs_remove_group(&client->dev.kobj, &ESC600_FAN_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_USB_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_LED_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_Reset_group); - sysfs_remove_group(&client->dev.kobj, &ESC600_Sensor_group); -#ifdef ESC_600_INT_WANTED - sysfs_remove_group(&client->dev.kobj, &ESC600_INT_group); -#endif - sysfs_remove_group(&client->dev.kobj, &ESC600_Module_group); - kfree(data); - return 0; -} - -static const struct i2c_device_id Cameo_i2c_id[] = -{ - { "ESC_600_128q", 0 }, - {}, -}; -MODULE_DEVICE_TABLE(i2c, Cameo_i2c_id); - -static struct i2c_driver Cameo_i2c_driver = -{ - .class = I2C_CLASS_HWMON, - .driver = - { - .name = "ESC_600_128q", - }, - .probe = Cameo_i2c_probe, - .remove = Cameo_i2c_remove, - .id_table = Cameo_i2c_id, - .address_list = normal_i2c, -}; - -static struct i2c_board_info ESC_600_128q_info[] __initdata = -{ - { - I2C_BOARD_INFO("ESC_600_128q", 0x33), - .platform_data = NULL, - }, -}; - -static struct i2c_board_info Cameo_CPLD_2_info[] __initdata = -{ - { - I2C_BOARD_INFO("Cameo_CPLD_2", 0x30), - .platform_data = NULL, - }, -}; - -static struct i2c_board_info Cameo_CPLD_3_info[] __initdata = -{ - { - I2C_BOARD_INFO("Cameo_CPLD_3", 0x31), - .platform_data = NULL, - }, -}; - -static struct i2c_board_info Cameo_CPLD_4_info[] __initdata = -{ - { - I2C_BOARD_INFO("Cameo_CPLD_3", 0x35), - .platform_data = NULL, - }, -}; - -static struct i2c_board_info Cameo_Extpand_1_info[] __initdata = -{ - { - I2C_BOARD_INFO("Cameo_Extpand_1", 0x20), - .platform_data = NULL, - }, -}; - -static struct i2c_board_info Cameo_Extpand_2_info[] __initdata = -{ - { - I2C_BOARD_INFO("Cameo_Extpand_2", 0x21), - .platform_data = NULL, - }, -}; - -static struct i2c_board_info Cameo_BMC_info[] __initdata = -{ - { - I2C_BOARD_INFO("Cameo_BMC", 0x14), - .platform_data = NULL, - }, -}; - -/********************************************************************************/ -/* Function Name : Cameo_i2c_init */ -/* Description : To init i2c driver */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static int __init Cameo_i2c_init(void) -{ - int ret; - struct i2c_adapter *i2c_adap = i2c_get_adapter(0); - if (i2c_adap == NULL) - { - printk("ERROR: i2c_get_adapter FAILED!\n"); - return -1; - } - ESC_600_128q_client = i2c_new_device(i2c_adap, &ESC_600_128q_info[0]); - Cameo_CPLD_2_client = i2c_new_device(i2c_adap, &Cameo_CPLD_2_info[0]); - Cameo_CPLD_3_client = i2c_new_device(i2c_adap, &Cameo_CPLD_3_info[0]); - Cameo_CPLD_4_client = i2c_new_device(i2c_adap, &Cameo_CPLD_4_info[0]); - Cameo_Extpand_1_client = i2c_new_device(i2c_adap, &Cameo_Extpand_1_info[0]); - Cameo_Extpand_2_client = i2c_new_device(i2c_adap, &Cameo_Extpand_2_info[0]); - Cameo_BMC_client = i2c_new_device(i2c_adap, &Cameo_BMC_info[0]); - if (ESC_600_128q_info == NULL || Cameo_CPLD_2_info == NULL || - Cameo_CPLD_3_info == NULL || Cameo_Extpand_1_info == NULL || - Cameo_Extpand_2_info == NULL || Cameo_BMC_info == NULL || - Cameo_CPLD_4_info == NULL) - { - printk("ERROR: i2c_new_device FAILED!\n"); - return -1; - } - i2c_put_adapter(i2c_adap); - ret = i2c_add_driver(&Cameo_i2c_driver); - printk(KERN_ALERT "ESC600-128Q i2c Driver ret: %d\n", ret); - printk(KERN_ALERT "ESC600-128Q i2c Driver Version: %s\n", DRIVER_VERSION); - printk(KERN_ALERT "ESC600-128Q i2c Driver INSTALL SUCCESS\n"); - return ret; -} - -/********************************************************************************/ -/* Function Name : Cameo_i2c_exit */ -/* Description : To remove i2c driver */ -/* */ -/* Input(s) : None. */ -/* Output(s) : None. */ -/* Returns : None. */ -/********************************************************************************/ -static void __exit Cameo_i2c_exit(void) -{ - i2c_unregister_device(ESC_600_128q_client); - i2c_unregister_device(Cameo_CPLD_2_client); - i2c_unregister_device(Cameo_CPLD_3_client); - i2c_unregister_device(Cameo_CPLD_4_client); - i2c_unregister_device(Cameo_Extpand_1_client); - i2c_unregister_device(Cameo_Extpand_2_client); - i2c_unregister_device(Cameo_BMC_client); - i2c_del_driver(&Cameo_i2c_driver); - printk(KERN_ALERT "ESC600-128Q i2c driver uninstall success\n"); -} - -MODULE_AUTHOR("Cameo Inc."); -MODULE_DESCRIPTION("Cameo ESC600-128Q i2c driver"); -MODULE_LICENSE("GPL"); - -module_init(Cameo_i2c_init); -module_exit(Cameo_i2c_exit); \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.h b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.h index ec48200431..6c0fdc14ee 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.h +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/modules/x86-64-cameo-esc600-128q.h @@ -11,78 +11,8 @@ #include #include #include -#include -#define DRIVER_VERSION "2.5" - -#define TURN_OFF 0 -#define TURN_ON 1 -#define LED_ON 0x1 -#define LED_OFF 0xfe -#define ALERT_TH0 1 -#define ALERT_TH1 2 -#define ALERT_TH2 3 -#define ALERT_TH3 4 -#define ALERT_TH4 5 -#define ALERT_TH5 6 -#define ALERT_TH0_MASK 1 -#define ALERT_TH1_MASK 2 -#define ALERT_TH2_MASK 3 -#define ALERT_TH3_MASK 4 -#define ALERT_TH4_MASK 5 -#define ALERT_TH5_MASK 6 -#define SW_ALERT_TH0 1 -#define SW_ALERT_TH1 2 -#define SW_ALERT_TH2 3 -#define SW_ALERT_TH3 4 -#define SW_ALERT_TH0_MASK 1 -#define SW_ALERT_TH1_MASK 2 -#define SW_ALERT_TH2_MASK 3 -#define SW_ALERT_TH3_MASK 4 -#define SENSOR_INT_0 1 -#define SENSOR_INT_1 2 -#define SENSOR_INT_0_MASK 1 -#define SENSOR_INT_1_MASK 2 -#define FAN_CH1 1 -#define FAN_CH2 2 -#define FAN_CH3 3 -#define USB_ON 0x1 -#define USB_OFF 0xfe -#define MODULE_INS_INT 1 -#define MODULE_INT 2 -#define MODULE_POWER_INT 3 -#define THER_SENSOR_INT 4 -#define IO_BOARD_INT 5 -#define FAN_ERROR_INT 6 -#define MODULE_INS_INT_MASK 1 -#define MODULE_INT_MASK 2 -#define MODULE_POW_INT_MASK 3 -#define THER_SEN_INT_MASK 4 -#define IO_BOARD_INT_MASK 5 -#define FAN_ERROR_INT_MASK 6 -#define SFP_PORT_1 1 -#define SFP_PORT_2 2 -#define SFP_PORT_MGM 3 -#define SFP_PORT_1_ON 1 -#define SFP_PORT_1_OFF 2 -#define SFP_PORT_2_ON 3 -#define SFP_PORT_2_OFF 4 -#define SFP_PORT_MGM_ON 5 -#define SFP_PORT_MGM_OFF 6 -#define SYS_LED_A 1 -#define SYS_LED_G 2 -#define SYS_LED_BLINK 3 -#define SYS_LED_OFF 0 -#define SYS_LED_A_N 1 -#define SYS_LED_A_B 2 -#define SYS_LED_G_N 3 -#define SYS_LED_G_B 4 -#define SWITCH_LED_OFF 0 -#define SWITCH_LED_A_N 1 -#define SWITCH_LED_A_B 2 -#define SWITCH_LED_G_N 3 -#define SWITCH_LED_G_B 4 -#define SWITCH_LED_BLINK 1 +#define DRIVER_VERSION "1.0.5" struct i2c_adap { int nr; @@ -95,139 +25,99 @@ struct i2c_adap *gather_i2c_busses(void); void free_adapters(struct i2c_adap *adapters); /* compiler conditional */ -#define LED_CTRL_WANTED -#define USB_CTRL_WANTED -#define ESC_600_BMC_WANTED -#define ESC_600_INT_WANTED -#define ESC_600_ALARM_WANTED -#define ESC_600_STAT_WANTED -#define ESC_600_JTAG_WANTED -#define WDT_CTRL_WANTED -#define EEPROM_WP_WANTED -//#define EEPROM_WANTED -//#define LED_L3_CTRL_WANTED -//#define LINEAR_CONVERT_FUNCTION - -#define DEBUG_MSG -#ifdef DEBUG_MSG - #define debug_print(s) printk s -#else - #define debug_print(s) -#endif /* end of compiler conditional */ -/* i2c_client Declaration */ -static struct i2c_client *ESC_600_128q_client; //0x33 I/O Board CPLD ,XO2-640 -static struct i2c_client *Cameo_Extpand_1_client; //0x20 I/O Extpander ,PCA9534PW -static struct i2c_client *Cameo_Extpand_2_client; //0x21 I/O Extpander ,PCA9534PW -static struct i2c_client *Cameo_CPLD_2_client; //0x30 CPLD ,XO2-2000HC-4FTG256C -static struct i2c_client *Cameo_CPLD_3_client; //0x31 CPLD ,XO2-7000HC-4TG144C -static struct i2c_client *Cameo_CPLD_4_client; //0x35 CPLD ,XO2-2000HC-4FTG256C -#ifdef ESC_600_BMC_WANTED -static struct i2c_client *Cameo_BMC_client; //0x14 BMC ,Aspeed -#endif /*ESC_600_BMC_WANTED*/ -/* end of i2c_client Declaration */ - /* Function Declaration */ -/*0x33 I/O Board CPLD*/ -static ssize_t sfp_select_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_select_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t sfp_tx_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_tx_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t sfp_insert_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_rx_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_button_get(struct device *dev, struct device_attribute *da, char *buf); -#ifdef LED_CTRL_WANTED -static ssize_t sys_led_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sys_led_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t switch_led_all_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_led_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#ifdef LED_L3_CTRL_WANTED -static ssize_t switch_led_3_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_led_3_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*LED_L3_CTRL_WANTED*/ -static ssize_t switch_led_4_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_led_4_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t switch_led_5_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_led_5_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*LED_CTRL_WANTED*/ -#ifdef ESC_600_INT_WANTED -static ssize_t sfp_int_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t psu_int_get(struct device *dev, struct device_attribute *da, char *buf); -#endif /*ESC_600_INT_WANTED*/ -/*0x31 CPLD-1 700HC*/ -#ifdef LED_CTRL_WANTED -static ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*LED_CTRL_WANTED*/ -#ifdef ESC_600_JTAG_WANTED -static ssize_t jtag_select_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t jtag_select_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*ESC_600_JTAG_WANTED*/ -#ifdef ESC_600_STAT_WANTED -static ssize_t sensor_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sersor_status_mask_all_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sersor_status_mask_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sersor_status_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*ESC_600_STAT_WANTED*/ -#ifdef ESC_600_ALARM_WANTED -static ssize_t switch_alarm_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_alarm_mask_all_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_alarm_mask_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_alarm_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*ESC_600_ALARM_WANTED*/ -#ifdef ESC_600_INT_WANTED -static ssize_t sensor_int_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sersor_int_mask_all_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sersor_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sersor_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t int_mask_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*ESC_600_INT_WANTED*/ -/*0x30 CPLD-1 640UHC*/ -static ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t fan_insert_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t fan_direct_get(struct device *dev, struct device_attribute *da, char *buf); -#ifdef USB_CTRL_WANTED -static ssize_t usb_power_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t usb_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*USB_CTRL_WANTED*/ -static ssize_t shutdown_sys_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t shutdown_sys_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t reset_sys_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t module_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t module_power_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t module_12v_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t module_enable_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t module_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t module_insert_get(struct device *dev, struct device_attribute *da, char *buf); -#ifdef ESC_600_INT_WANTED -static ssize_t switch_int_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_int_mask_all_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t switch_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*ESC_600_INT_WANTED*/ -static ssize_t cpld_version_get(struct device *dev, struct device_attribute *da, char *buf); -#ifdef WDT_CTRL_WANTED -static ssize_t wdt_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t wdt_status_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*WDT_CTRL_WANTED*/ -#ifdef EEPROM_WP_WANTED -static ssize_t eeprom_wp_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t eeprom_wp_status_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif /*EEPROM_WP_WANTED*/ -/*0x14 BMC*/ -#ifdef ESC_600_BMC_WANTED -static ssize_t bmc_module_detect(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t module_temp_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t mac_temp_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t psu_module_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t dc_chip_switch_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t dc_chip_slot_get(struct device *dev, struct device_attribute *da, char *buf); -#endif /*ESC_600_BMC_WANTED*/ +/* x86-64-cameo-esc600-128q-sys.c */ +ssize_t cpld_hw_ver_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t wdt_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t wdt_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t eeprom_wp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t eeprom_wp_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t usb_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t usb_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t reset_mac_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t shutdown_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t bmc_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t switch_alarm_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t switch_alarm_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t switch_alarm_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sensor_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sersor_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sersor_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t module_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t module_insert_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t module_power_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t module_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t module_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t switch_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t switch_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t switch_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sfp_select_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_select_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sfp_tx_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_tx_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sfp_insert_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_rx_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sys_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sys_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sys_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t thermal_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t thermal_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t thermal_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +/* x86-64-cameo-esc600-128q-led.c */ +ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t switch_led_4_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t switch_led_4_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t switch_led_5_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t switch_led_5_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t led_fiber_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_fiber_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +/* x86-64-cameo-esc600-128q-thermal.c */ +ssize_t line_card_temp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_max_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_min_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_crit_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_lcrit_get(struct device *dev, struct device_attribute *da, char *buf); +/* x86-64-cameo-esc600-128q-fan.c */ +ssize_t fan_ctrl_mode_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_ctrl_rpm_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_direct_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_rpm_get(struct device *dev, struct device_attribute *da, char *buf); +/* x86-64-cameo-esc600-128q-power.c */ +ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_temp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_fan_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_pout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_pin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iout_max_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vmode_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_pout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_11_p0_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_11_p1_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_12_p0_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_12_p1_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_13_p0_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_13_p1_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_11_p0_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_11_p1_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_12_p0_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_12_p1_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_13_p0_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_13_p1_iout_get(struct device *dev, struct device_attribute *da, char *buf); /* end of Function Declaration */ /* struct i2c_data */ @@ -235,405 +125,962 @@ struct Cameo_i2c_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status; /* Status register read from CPLD */ + char valid; + unsigned long last_updated; + u8 status; }; -/*end of struct i2c_data */ /* struct i2c_sysfs_attributes */ enum Cameo_i2c_sysfs_attributes { - /*0x31 CPLD-1 700HC*/ -#ifdef LED_CTRL_WANTED - LED_CTRL, -#endif /*LED_CTRL_WANTED*/ -#ifdef ESC_600_JTAG_WANTED - JTAG_SELECT, -#endif /*ESC_600_JTAG_WANTED*/ -#ifdef ESC_600_STAT_WANTED - SENSOR_STATUS, - SENSOR_STATUS_MASK, -#endif /*ESC_600_STAT_WANTED*/ -#ifdef ESC_600_ALARM_WANTED - SWITCH_ALARM, - SWITCH_ALARM_MASK, -#endif /*ESC_600_ALARM_WANTED*/ -#ifdef ESC_600_INT_WANTED - SENSOR_INT, - SENSOR_INT_MASK, -#endif /*ESC_600_INT_WANTED*/ - /*0x30 CPLD-1 640UHC*/ - FAN_STATUS, - FAN_INSERT, - FAN_POWER, - FAN_DIRECT, - FAN_SPEED_RPM, -#ifdef USB_CTRL_WANTED - USB_POWER, -#endif /*USB_CTRL_WANTED*/ - SYS_SHUTDOWN, - SYS_RESET, + /* x86-64-cameo-esc600-128q-sys.c */ + CPLD_30_VER, + CPLD_31_VER, + CPLD_33_VER, + WDT_EN, + EEPROM_WP, + USB_EN, + SHUTDOWN_SET, + RESET, + BMC_PRESENT, + SW_ALERT_TH0, + SW_ALERT_TH1, + SW_ALERT_TH2, + SW_ALERT_TH3, + SW_ALERT_TH0_MASK, + SW_ALERT_TH1_MASK, + SW_ALERT_TH2_MASK, + SW_ALERT_TH3_MASK, + CB_INT, + SB_INT, + CB_INT_MASK, + SB_INT_MASK, MODULE_RESET, - MODULE_INSERT, - MODULE_POWER, - MODULE_ENABLE, - MODULE_12V_STAT, - CPLD_VER, -#ifdef ESC_600_INT_WANTED - SWITCH_INT, - SWITCH_INT_MASK, -#endif /*ESC_600_INT_WANTED*/ -#ifdef WDT_CTRL_WANTED - WDT_CTRL, -#endif -#ifdef EEPROM_WP_WANTED - EEPROM_WP_CTRL, -#endif - /*0x33 I/O Board CPLD*/ + MODULE_1_PRESENT, + MODULE_2_PRESENT, + MODULE_3_PRESENT, + MODULE_4_PRESENT, + MODULE_5_PRESENT, + MODULE_6_PRESENT, + MODULE_7_PRESENT, + MODULE_8_PRESENT, + MODULE_1_POWER, + MODULE_2_POWER, + MODULE_3_POWER, + MODULE_4_POWER, + MODULE_5_POWER, + MODULE_6_POWER, + MODULE_7_POWER, + MODULE_8_POWER, + MODULE_1_ENABLE, + MODULE_2_ENABLE, + MODULE_3_ENABLE, + MODULE_4_ENABLE, + MODULE_5_ENABLE, + MODULE_6_ENABLE, + MODULE_7_ENABLE, + MODULE_8_ENABLE, + MODULE_INS_INT, + MODULE_INT, + MODULE_POWER_INT, + THER_SENSOR_INT, + IO_BOARD_INT, + FAN_ERROR_INT, + PHY_POWER_INT, + SW_POWER_INT, + MODULE_INS_INT_MASK, + MODULE_INT_MASK, + MODULE_POW_INT_MASK, + THER_SEN_INT_MASK, + IO_BOARD_INT_MASK, + FAN_ERROR_INT_MASK, + PHY_POWER_INT_MASK, + SW_POWER_INT_MASK, SFP_SELECT, - SFP_INSERT, - SFP_TX_DISABLE, - SFP_RX_LOSS, - PSU_PRESENT, - PSU_STATUS, - SWITCH_BUTTON, -#ifdef ESC_600_BMC_WANTED - SENSOR_TEMP, - MODULE_TEMP, - MAC_TEMP, - DC_CHIP_SWITCH, - DC_CHIP_SLOT_1, - DC_CHIP_SLOT_2, - DC_CHIP_SLOT_3, - DC_CHIP_SLOT_4, - DC_CHIP_SLOT_5, - DC_CHIP_SLOT_6, - DC_CHIP_SLOT_7, - DC_CHIP_SLOT_8, - PSU_MODULE_1, - PSU_MODULE_2, - PSU_MODULE_3, - PSU_MODULE_4, - BMC_DETECT, -#endif /*ESC_600_BMC_WANTED*/ -#ifdef LED_CTRL_WANTED - SYS_LED, - SWITCH_LED, -#endif /*LED_CTRL_WANTED*/ -#ifdef ESC_600_INT_WANTED - SFP_INT, - SFP_INT_MASK, - PSU_INT, -#endif /*ESC_600_INT_WANTED*/ + SFP_PORT_TX_1, + SFP_PORT_TX_2, + SFP_PORT_TX_MGM, + SFP_PORT_1, + SFP_PORT_2, + SFP_PORT_MGM, + SFP_PORT_RX_1, + SFP_PORT_RX_2, + SFP_PORT_RX_MGM, + SFP_LOSS_INT, + SFP_ABS_INT, + SFP_LOSS_MASK, + SFP_ABS_MASK, + ALERT_TH0_INT, + ALERT_TH1_INT, + ALERT_TH2_INT, + ALERT_TH3_INT, + ALERT_TH4_INT, + ALERT_TH5_INT, + ALERT_TH0_INT_MASK, + ALERT_TH1_INT_MASK, + ALERT_TH2_INT_MASK, + ALERT_TH3_INT_MASK, + ALERT_TH4_INT_MASK, + ALERT_TH5_INT_MASK, + /* x86-64-cameo-esc600-128q-led.c */ + LED_SYS, + LED_LOC, + LED_FLOW, + LED_4_1, + LED_4_2, + LED_4_3, + LED_4_4, + LED_5_1, + LED_5_2, + LED_5_3, + LED_5_4, + LED_FIBER, + /* x86-64-cameo-esc600-128q-thermal.c */ + LINE_CARD_1_UP_TEMP, + LINE_CARD_2_UP_TEMP, + LINE_CARD_3_UP_TEMP, + LINE_CARD_4_UP_TEMP, + LINE_CARD_5_UP_TEMP, + LINE_CARD_6_UP_TEMP, + LINE_CARD_7_UP_TEMP, + LINE_CARD_8_UP_TEMP, + LINE_CARD_1_DN_TEMP, + LINE_CARD_2_DN_TEMP, + LINE_CARD_3_DN_TEMP, + LINE_CARD_4_DN_TEMP, + LINE_CARD_5_DN_TEMP, + LINE_CARD_6_DN_TEMP, + LINE_CARD_7_DN_TEMP, + LINE_CARD_8_DN_TEMP, + NCT7511_TEMP, + LEFT_BOT_SB_TEMP, + CTR_TOP_SB_TEMP, + CTR_SB_TEMP, + LEFT_TOP_CB_TEMP, + CTR_CB_TEMP, + RIGHT_BOT_CB_TEMP, + LEFT_BOT_CB_TEMP, + IO_BOARD_TEMP, + /* x86-64-cameo-esc600-128q-fan.c */ + FANCTRL_MODE, + FANCTRL_RPM, + FAN_1_STAT, + FAN_2_STAT, + FAN_3_STAT, + FAN_4_STAT, + FAN_1_PRESENT, + FAN_2_PRESENT, + FAN_3_PRESENT, + FAN_4_PRESENT, + FAN_1_POWER, + FAN_2_POWER, + FAN_3_POWER, + FAN_4_POWER, + FAN_1_DIRECT, + FAN_2_DIRECT, + FAN_3_DIRECT, + FAN_4_DIRECT, + FAN_1_RPM, + FAN_2_RPM, + FAN_3_RPM, + FAN_4_RPM, + /* x86-64-cameo-esc600-128q-power.c */ + PSU_1_STST, + PSU_2_STST, + PSU_3_STST, + PSU_4_STST, + PSU_1_PRESENT, + PSU_2_PRESENT, + PSU_3_PRESENT, + PSU_4_PRESENT, + PSU1_VIN, + PSU2_VIN, + PSU3_VIN, + PSU4_VIN, + PSU1_IIN, + PSU2_IIN, + PSU3_IIN, + PSU4_IIN, + PSU1_VOUT, + PSU2_VOUT, + PSU3_VOUT, + PSU4_VOUT, + PSU1_IOUT, + PSU2_IOUT, + PSU3_IOUT, + PSU4_IOUT, + PSU1_TEMP, + PSU2_TEMP, + PSU3_TEMP, + PSU4_TEMP, + PSU1_FAN_SPEED, + PSU2_FAN_SPEED, + PSU3_FAN_SPEED, + PSU4_FAN_SPEED, + PSU1_POUT, + PSU2_POUT, + PSU3_POUT, + PSU4_POUT, + PSU1_PIN, + PSU2_PIN, + PSU3_PIN, + PSU4_PIN, + PSU1_MFR_MODEL, + PSU2_MFR_MODEL, + PSU3_MFR_MODEL, + PSU4_MFR_MODEL, + PSU1_MFR_IOUT_MAX, + PSU2_MFR_IOUT_MAX, + PSU3_MFR_IOUT_MAX, + PSU4_MFR_IOUT_MAX, + PSU1_VMODE, + PSU2_VMODE, + PSU3_VMODE, + PSU4_VMODE, + DC_6E_P0_VOUT, + DC_70_P0_VOUT, + DC_70_P1_VOUT, + DC_6E_P0_IOUT, + DC_70_P0_IOUT, + DC_70_P1_IOUT, + DC_6E_P0_POUT, + DC_70_P0_POUT, + DC_70_P1_POUT, + CARD_1_DC_11_P0_VOUT, + CARD_2_DC_11_P0_VOUT, + CARD_3_DC_11_P0_VOUT, + CARD_4_DC_11_P0_VOUT, + CARD_5_DC_11_P0_VOUT, + CARD_6_DC_11_P0_VOUT, + CARD_7_DC_11_P0_VOUT, + CARD_8_DC_11_P0_VOUT, + CARD_1_DC_11_P1_VOUT, + CARD_2_DC_11_P1_VOUT, + CARD_3_DC_11_P1_VOUT, + CARD_4_DC_11_P1_VOUT, + CARD_5_DC_11_P1_VOUT, + CARD_6_DC_11_P1_VOUT, + CARD_7_DC_11_P1_VOUT, + CARD_8_DC_11_P1_VOUT, + CARD_1_DC_12_P0_VOUT, + CARD_2_DC_12_P0_VOUT, + CARD_3_DC_12_P0_VOUT, + CARD_4_DC_12_P0_VOUT, + CARD_5_DC_12_P0_VOUT, + CARD_6_DC_12_P0_VOUT, + CARD_7_DC_12_P0_VOUT, + CARD_8_DC_12_P0_VOUT, + CARD_1_DC_12_P1_VOUT, + CARD_2_DC_12_P1_VOUT, + CARD_3_DC_12_P1_VOUT, + CARD_4_DC_12_P1_VOUT, + CARD_5_DC_12_P1_VOUT, + CARD_6_DC_12_P1_VOUT, + CARD_7_DC_12_P1_VOUT, + CARD_8_DC_12_P1_VOUT, + CARD_1_DC_13_P0_VOUT, + CARD_2_DC_13_P0_VOUT, + CARD_3_DC_13_P0_VOUT, + CARD_4_DC_13_P0_VOUT, + CARD_5_DC_13_P0_VOUT, + CARD_6_DC_13_P0_VOUT, + CARD_7_DC_13_P0_VOUT, + CARD_8_DC_13_P0_VOUT, + CARD_1_DC_13_P1_VOUT, + CARD_2_DC_13_P1_VOUT, + CARD_3_DC_13_P1_VOUT, + CARD_4_DC_13_P1_VOUT, + CARD_5_DC_13_P1_VOUT, + CARD_6_DC_13_P1_VOUT, + CARD_7_DC_13_P1_VOUT, + CARD_8_DC_13_P1_VOUT, + CARD_1_DC_11_P0_IOUT, + CARD_2_DC_11_P0_IOUT, + CARD_3_DC_11_P0_IOUT, + CARD_4_DC_11_P0_IOUT, + CARD_5_DC_11_P0_IOUT, + CARD_6_DC_11_P0_IOUT, + CARD_7_DC_11_P0_IOUT, + CARD_8_DC_11_P0_IOUT, + CARD_1_DC_11_P1_IOUT, + CARD_2_DC_11_P1_IOUT, + CARD_3_DC_11_P1_IOUT, + CARD_4_DC_11_P1_IOUT, + CARD_5_DC_11_P1_IOUT, + CARD_6_DC_11_P1_IOUT, + CARD_7_DC_11_P1_IOUT, + CARD_8_DC_11_P1_IOUT, + CARD_1_DC_12_P0_IOUT, + CARD_2_DC_12_P0_IOUT, + CARD_3_DC_12_P0_IOUT, + CARD_4_DC_12_P0_IOUT, + CARD_5_DC_12_P0_IOUT, + CARD_6_DC_12_P0_IOUT, + CARD_7_DC_12_P0_IOUT, + CARD_8_DC_12_P0_IOUT, + CARD_1_DC_12_P1_IOUT, + CARD_2_DC_12_P1_IOUT, + CARD_3_DC_12_P1_IOUT, + CARD_4_DC_12_P1_IOUT, + CARD_5_DC_12_P1_IOUT, + CARD_6_DC_12_P1_IOUT, + CARD_7_DC_12_P1_IOUT, + CARD_8_DC_12_P1_IOUT, + CARD_1_DC_13_P0_IOUT, + CARD_2_DC_13_P0_IOUT, + CARD_3_DC_13_P0_IOUT, + CARD_4_DC_13_P0_IOUT, + CARD_5_DC_13_P0_IOUT, + CARD_6_DC_13_P0_IOUT, + CARD_7_DC_13_P0_IOUT, + CARD_8_DC_13_P0_IOUT, + CARD_1_DC_13_P1_IOUT, + CARD_2_DC_13_P1_IOUT, + CARD_3_DC_13_P1_IOUT, + CARD_4_DC_13_P1_IOUT, + CARD_5_DC_13_P1_IOUT, + CARD_6_DC_13_P1_IOUT, + CARD_7_DC_13_P1_IOUT, + CARD_8_DC_13_P1_IOUT, }; /* end of struct i2c_sysfs_attributes */ /* sysfs attributes for SENSOR_DEVICE_ATTR */ -/*ESC600_SYS_attributes*/ -static SENSOR_DEVICE_ATTR(cpld_version , S_IRUGO , cpld_version_get , NULL , CPLD_VER); -#ifdef WDT_CTRL_WANTED -static SENSOR_DEVICE_ATTR(wdt_ctrl , S_IRUGO | S_IWUSR , wdt_status_get , wdt_status_set , WDT_CTRL); -#endif /*WDT_CTRL_WANTED*/ -#ifdef EEPROM_WP_WANTED -static SENSOR_DEVICE_ATTR(eeprom_wp_ctrl , S_IRUGO | S_IWUSR , eeprom_wp_status_get , eeprom_wp_status_set , EEPROM_WP_CTRL); -#endif /*EEPROM_WP_WANTED*/ -/*ESC600_PSU_attributes*/ -static SENSOR_DEVICE_ATTR(psu_present , S_IRUGO , psu_status_get , NULL , PSU_PRESENT); -static SENSOR_DEVICE_ATTR(psu_status , S_IRUGO , psu_status_get , NULL , PSU_STATUS); -#ifdef ESC_600_BMC_WANTED -static SENSOR_DEVICE_ATTR(psu_module_1 , S_IRUGO , psu_module_get , NULL , PSU_MODULE_1); -static SENSOR_DEVICE_ATTR(psu_module_2 , S_IRUGO , psu_module_get , NULL , PSU_MODULE_2); -static SENSOR_DEVICE_ATTR(psu_module_3 , S_IRUGO , psu_module_get , NULL , PSU_MODULE_3); -static SENSOR_DEVICE_ATTR(psu_module_4 , S_IRUGO , psu_module_get , NULL , PSU_MODULE_4); -static SENSOR_DEVICE_ATTR(dc_chip_switch , S_IRUGO , dc_chip_switch_get , NULL , DC_CHIP_SWITCH); -static SENSOR_DEVICE_ATTR(dc_chip_slot_1 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_1); -static SENSOR_DEVICE_ATTR(dc_chip_slot_2 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_2); -static SENSOR_DEVICE_ATTR(dc_chip_slot_3 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_3); -static SENSOR_DEVICE_ATTR(dc_chip_slot_4 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_4); -static SENSOR_DEVICE_ATTR(dc_chip_slot_5 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_5); -static SENSOR_DEVICE_ATTR(dc_chip_slot_6 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_6); -static SENSOR_DEVICE_ATTR(dc_chip_slot_7 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_7); -static SENSOR_DEVICE_ATTR(dc_chip_slot_8 , S_IRUGO , dc_chip_slot_get , NULL , DC_CHIP_SLOT_8); -#endif /*ESC_600_BMC_WANTED*/ -/*ESC600_JTAG_attributes*/ -#ifdef ESC_600_JTAG_WANTED -static SENSOR_DEVICE_ATTR(jtag_select , S_IRUGO | S_IWUSR , jtag_select_get , jtag_select_set , JTAG_SELECT); -#endif /*ESC_600_JTAG_WANTED*/ -/*ESC600_SFP_attributes*/ -static SENSOR_DEVICE_ATTR(sfp_select , S_IRUGO | S_IWUSR , sfp_select_get , sfp_select_set , SFP_SELECT); -static SENSOR_DEVICE_ATTR(sfp_insert , S_IRUGO , sfp_insert_get , NULL , SFP_INSERT); -static SENSOR_DEVICE_ATTR(sfp_tx_disable , S_IRUGO | S_IWUSR , sfp_tx_get , sfp_tx_set , SFP_TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_rx_loss , S_IRUGO , sfp_rx_get , NULL , SFP_RX_LOSS); -/*ESC600_Mask_attributes*/ -#ifdef ESC_600_STAT_WANTED -static SENSOR_DEVICE_ATTR(sersor_status_mask_all , S_IRUGO , sersor_status_mask_all_get , NULL , SENSOR_STATUS_MASK); -static SENSOR_DEVICE_ATTR(sersor_status_mask_1 , S_IRUGO | S_IWUSR , sersor_status_mask_get , sersor_status_mask_set , 1); -static SENSOR_DEVICE_ATTR(sersor_status_mask_2 , S_IRUGO | S_IWUSR , sersor_status_mask_get , sersor_status_mask_set , 2); -static SENSOR_DEVICE_ATTR(sersor_status_mask_3 , S_IRUGO | S_IWUSR , sersor_status_mask_get , sersor_status_mask_set , 3); -static SENSOR_DEVICE_ATTR(sersor_status_mask_4 , S_IRUGO | S_IWUSR , sersor_status_mask_get , sersor_status_mask_set , 4); -static SENSOR_DEVICE_ATTR(sersor_status_mask_5 , S_IRUGO | S_IWUSR , sersor_status_mask_get , sersor_status_mask_set , 5); -static SENSOR_DEVICE_ATTR(sersor_status_mask_6 , S_IRUGO | S_IWUSR , sersor_status_mask_get , sersor_status_mask_set , 6); -#endif /*ESC_600_STAT_WANTED*/ -#ifdef ESC_600_ALARM_WANTED -static SENSOR_DEVICE_ATTR(switch_alarm_mask_all , S_IRUGO , switch_alarm_mask_all_get , NULL , SWITCH_ALARM_MASK); -static SENSOR_DEVICE_ATTR(switch_alarm_mask_1 , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , 1); -static SENSOR_DEVICE_ATTR(switch_alarm_mask_2 , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , 2); -static SENSOR_DEVICE_ATTR(switch_alarm_mask_3 , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , 3); -static SENSOR_DEVICE_ATTR(switch_alarm_mask_4 , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , 4); -#endif /*ESC_600_ALARM_WANTED*/ -#ifdef ESC_600_INT_WANTED -static SENSOR_DEVICE_ATTR(sersor_int_mask_all , S_IRUGO , sersor_int_mask_all_get , NULL , SENSOR_INT_MASK); -static SENSOR_DEVICE_ATTR(sersor_int_mask_1 , S_IRUGO | S_IWUSR , sersor_int_mask_get , sersor_int_mask_set , 1); -static SENSOR_DEVICE_ATTR(sersor_int_mask_2 , S_IRUGO | S_IWUSR , sersor_int_mask_get , sersor_int_mask_set , 2); -static SENSOR_DEVICE_ATTR(switch_int_mask_all , S_IRUGO , switch_int_mask_all_get , NULL , SWITCH_INT_MASK); -static SENSOR_DEVICE_ATTR(phy_module_ins_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , 1); -static SENSOR_DEVICE_ATTR(phy_module_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , 2); -static SENSOR_DEVICE_ATTR(phy_module_power_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , 3); -static SENSOR_DEVICE_ATTR(cpld2_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , 4); -static SENSOR_DEVICE_ATTR(io_board_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , 5); -static SENSOR_DEVICE_ATTR(fan_error_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , 6); -static SENSOR_DEVICE_ATTR(psu_int_mask , S_IRUGO | S_IWUSR , int_mask_get , int_mask_set , 1); -static SENSOR_DEVICE_ATTR(sfp_loss_int_mask , S_IRUGO | S_IWUSR , int_mask_get , int_mask_set , 2); -static SENSOR_DEVICE_ATTR(sfp_abs_int_mask , S_IRUGO | S_IWUSR , int_mask_get , int_mask_set , 3); -#endif /*ESC_600_INT_WANTED*/ -/*ESC600_Fan_attributes*/ -static SENSOR_DEVICE_ATTR(fan_status , S_IRUGO , fan_status_get , NULL , FAN_STATUS); -static SENSOR_DEVICE_ATTR(fan_insert , S_IRUGO , fan_insert_get , NULL , FAN_INSERT); -static SENSOR_DEVICE_ATTR(fan_power , S_IRUGO , fan_power_get , NULL , FAN_POWER); -static SENSOR_DEVICE_ATTR(fan_direct , S_IRUGO , fan_direct_get , NULL , FAN_DIRECT); -static SENSOR_DEVICE_ATTR(fan_speed_rpm , S_IRUGO , fan_status_get , NULL , FAN_SPEED_RPM); -/*ESC600_USB_attributes*/ -#ifdef USB_CTRL_WANTED -static SENSOR_DEVICE_ATTR(usb_power , S_IRUGO | S_IWUSR , usb_power_get , usb_power_set , USB_POWER); -#endif /*USB_CTRL_WANTED*/ -/*ESC600_LED_attributes*/ -#ifdef LED_CTRL_WANTED -static SENSOR_DEVICE_ATTR(led_ctrl , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , LED_CTRL); -static SENSOR_DEVICE_ATTR(sys_led , S_IRUGO | S_IWUSR , sys_led_get , sys_led_set , SYS_LED); -static SENSOR_DEVICE_ATTR(switch_led_all , S_IRUGO | S_IWUSR , switch_led_all_get , switch_led_all_set , SWITCH_LED); -#ifdef LED_L3_CTRL_WANTED -static SENSOR_DEVICE_ATTR(switch_led_3_1 , S_IRUGO | S_IWUSR , switch_led_3_get , switch_led_3_set , 1); -static SENSOR_DEVICE_ATTR(switch_led_3_2 , S_IRUGO | S_IWUSR , switch_led_3_get , switch_led_3_set , 2); -static SENSOR_DEVICE_ATTR(switch_led_3_3 , S_IRUGO | S_IWUSR , switch_led_3_get , switch_led_3_set , 3); -static SENSOR_DEVICE_ATTR(switch_led_3_4 , S_IRUGO | S_IWUSR , switch_led_3_get , switch_led_3_set , 4); -#endif /*LED_L3_CTRL_WANTED*/ -static SENSOR_DEVICE_ATTR(switch_led_4_1 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 1); -static SENSOR_DEVICE_ATTR(switch_led_4_2 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 2); -static SENSOR_DEVICE_ATTR(switch_led_4_3 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 3); -static SENSOR_DEVICE_ATTR(switch_led_4_4 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 4); -static SENSOR_DEVICE_ATTR(switch_led_5_1 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 1); -static SENSOR_DEVICE_ATTR(switch_led_5_2 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 2); -static SENSOR_DEVICE_ATTR(switch_led_5_3 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 3); -static SENSOR_DEVICE_ATTR(switch_led_5_4 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 4); -#endif /*LED_CTRL_WANTED*/ -/*ESC600_Reset_attributes*/ -static SENSOR_DEVICE_ATTR(shutdown_sys , S_IRUGO | S_IWUSR , shutdown_sys_get , shutdown_sys_set , SYS_SHUTDOWN); -static SENSOR_DEVICE_ATTR(reset_sys , S_IRUGO | S_IWUSR , NULL , reset_sys_set , SYS_RESET); -/*ESC600_Sensor_attributes*/ -#ifdef ESC_600_STAT_WANTED -static SENSOR_DEVICE_ATTR(sensor_status , S_IRUGO , sensor_status_get , NULL , SENSOR_STATUS); -#endif /*ESC_600_STAT_WANTED*/ -#ifdef ESC_600_ALARM_WANTED -static SENSOR_DEVICE_ATTR(switch_alarm , S_IRUGO , switch_alarm_get , NULL , SWITCH_ALARM); -#endif /*ESC_600_ALARM_WANTED*/ -static SENSOR_DEVICE_ATTR(switch_button , S_IRUGO , switch_button_get , NULL , SWITCH_BUTTON); -#ifdef ESC_600_BMC_WANTED -static SENSOR_DEVICE_ATTR(sensor_temp , S_IRUGO , themal_temp_get , NULL , SENSOR_TEMP); -static SENSOR_DEVICE_ATTR(module_temp , S_IRUGO , module_temp_get , NULL , MODULE_TEMP); -static SENSOR_DEVICE_ATTR(mac_temp , S_IRUGO , mac_temp_get , NULL , MAC_TEMP); -static SENSOR_DEVICE_ATTR(bmc_present , S_IRUGO , bmc_module_detect , NULL , BMC_DETECT); -#endif /*ESC_600_BMC_WANTED*/ -/*ESC600_INT_attributes*/ -#ifdef ESC_600_INT_WANTED -static SENSOR_DEVICE_ATTR(sensor_int , S_IRUGO , sensor_int_get , NULL , SENSOR_INT); -static SENSOR_DEVICE_ATTR(switch_int , S_IRUGO , switch_int_get , NULL , SWITCH_INT); -static SENSOR_DEVICE_ATTR(sfp_int , S_IRUGO , sfp_int_get , NULL , SFP_INT); -static SENSOR_DEVICE_ATTR(psu_int , S_IRUGO , psu_int_get , NULL , PSU_INT); -#endif /*ESC_600_INT_WANTED*/ -/*ESC600_Module_attributes*/ -static SENSOR_DEVICE_ATTR(module_reset , S_IRUGO | S_IWUSR , NULL , module_reset_set , MODULE_RESET); -static SENSOR_DEVICE_ATTR(module_insert , S_IRUGO , module_insert_get , NULL , MODULE_INSERT); -static SENSOR_DEVICE_ATTR(module_power , S_IRUGO , module_power_get , NULL , MODULE_POWER); -static SENSOR_DEVICE_ATTR(module_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_ENABLE); -static SENSOR_DEVICE_ATTR(module_12v_status , S_IRUGO , module_12v_status_get , NULL , MODULE_12V_STAT); + /* x86-64-cameo-esc600-128q-sys.c */ + static SENSOR_DEVICE_ATTR(cpld_30_ver , S_IRUGO , cpld_hw_ver_get , NULL , 30); + static SENSOR_DEVICE_ATTR(cpld_31_ver , S_IRUGO , cpld_hw_ver_get , NULL , 31); + static SENSOR_DEVICE_ATTR(cpld_33_ver , S_IRUGO , cpld_hw_ver_get , NULL , 33); + static SENSOR_DEVICE_ATTR(wdt_en , S_IRUGO | S_IWUSR , wdt_enable_get , wdt_enable_set , WDT_EN); + static SENSOR_DEVICE_ATTR(eeprom_wp , S_IRUGO | S_IWUSR , eeprom_wp_get , eeprom_wp_set , EEPROM_WP); + static SENSOR_DEVICE_ATTR(usb_en , S_IRUGO | S_IWUSR , usb_enable_get , usb_enable_set , USB_EN); + static SENSOR_DEVICE_ATTR(shutdown_set , S_IRUGO | S_IWUSR , NULL , shutdown_set , SHUTDOWN_SET); + static SENSOR_DEVICE_ATTR(reset , S_IRUGO | S_IWUSR , NULL , reset_mac_set , RESET); + static SENSOR_DEVICE_ATTR(bmc_present , S_IRUGO , bmc_enable_get , NULL , BMC_PRESENT); + static SENSOR_DEVICE_ATTR(sw_alert_th0 , S_IRUGO , switch_alarm_get , NULL , SW_ALERT_TH0); + static SENSOR_DEVICE_ATTR(sw_alert_th1 , S_IRUGO , switch_alarm_get , NULL , SW_ALERT_TH1); + static SENSOR_DEVICE_ATTR(sw_alert_th2 , S_IRUGO , switch_alarm_get , NULL , SW_ALERT_TH2); + static SENSOR_DEVICE_ATTR(sw_alert_th3 , S_IRUGO , switch_alarm_get , NULL , SW_ALERT_TH3); + static SENSOR_DEVICE_ATTR(sw_alert_th0_mask , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , SW_ALERT_TH0_MASK); + static SENSOR_DEVICE_ATTR(sw_alert_th1_mask , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , SW_ALERT_TH1_MASK); + static SENSOR_DEVICE_ATTR(sw_alert_th2_mask , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , SW_ALERT_TH2_MASK); + static SENSOR_DEVICE_ATTR(sw_alert_th3_mask , S_IRUGO | S_IWUSR , switch_alarm_mask_get , switch_alarm_mask_set , SW_ALERT_TH3_MASK); + static SENSOR_DEVICE_ATTR(cb_int , S_IRUGO , sensor_int_get , NULL , CB_INT); + static SENSOR_DEVICE_ATTR(sb_int , S_IRUGO , sensor_int_get , NULL , SB_INT); + static SENSOR_DEVICE_ATTR(cb_int_mask , S_IRUGO | S_IWUSR , sersor_int_mask_get , sersor_int_mask_set , CB_INT_MASK); + static SENSOR_DEVICE_ATTR(sb_int_mask , S_IRUGO | S_IWUSR , sersor_int_mask_get , sersor_int_mask_set , SB_INT_MASK); + static SENSOR_DEVICE_ATTR(module_reset , S_IRUGO | S_IWUSR , NULL , module_reset_set , MODULE_RESET); + static SENSOR_DEVICE_ATTR(module_1_present , S_IRUGO , module_insert_get , NULL , MODULE_1_PRESENT); + static SENSOR_DEVICE_ATTR(module_2_present , S_IRUGO , module_insert_get , NULL , MODULE_2_PRESENT); + static SENSOR_DEVICE_ATTR(module_3_present , S_IRUGO , module_insert_get , NULL , MODULE_3_PRESENT); + static SENSOR_DEVICE_ATTR(module_4_present , S_IRUGO , module_insert_get , NULL , MODULE_4_PRESENT); + static SENSOR_DEVICE_ATTR(module_5_present , S_IRUGO , module_insert_get , NULL , MODULE_5_PRESENT); + static SENSOR_DEVICE_ATTR(module_6_present , S_IRUGO , module_insert_get , NULL , MODULE_6_PRESENT); + static SENSOR_DEVICE_ATTR(module_7_present , S_IRUGO , module_insert_get , NULL , MODULE_7_PRESENT); + static SENSOR_DEVICE_ATTR(module_8_present , S_IRUGO , module_insert_get , NULL , MODULE_8_PRESENT); + static SENSOR_DEVICE_ATTR(module_1_power , S_IRUGO , module_power_get , NULL , MODULE_1_POWER); + static SENSOR_DEVICE_ATTR(module_2_power , S_IRUGO , module_power_get , NULL , MODULE_2_POWER); + static SENSOR_DEVICE_ATTR(module_3_power , S_IRUGO , module_power_get , NULL , MODULE_3_POWER); + static SENSOR_DEVICE_ATTR(module_4_power , S_IRUGO , module_power_get , NULL , MODULE_4_POWER); + static SENSOR_DEVICE_ATTR(module_5_power , S_IRUGO , module_power_get , NULL , MODULE_5_POWER); + static SENSOR_DEVICE_ATTR(module_6_power , S_IRUGO , module_power_get , NULL , MODULE_6_POWER); + static SENSOR_DEVICE_ATTR(module_7_power , S_IRUGO , module_power_get , NULL , MODULE_7_POWER); + static SENSOR_DEVICE_ATTR(module_8_power , S_IRUGO , module_power_get , NULL , MODULE_8_POWER); + static SENSOR_DEVICE_ATTR(module_1_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_1_ENABLE); + static SENSOR_DEVICE_ATTR(module_2_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_2_ENABLE); + static SENSOR_DEVICE_ATTR(module_3_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_3_ENABLE); + static SENSOR_DEVICE_ATTR(module_4_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_4_ENABLE); + static SENSOR_DEVICE_ATTR(module_5_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_5_ENABLE); + static SENSOR_DEVICE_ATTR(module_6_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_6_ENABLE); + static SENSOR_DEVICE_ATTR(module_7_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_7_ENABLE); + static SENSOR_DEVICE_ATTR(module_8_enable , S_IRUGO | S_IWUSR , module_enable_get , module_enable_set , MODULE_8_ENABLE); + static SENSOR_DEVICE_ATTR(module_ins_int , S_IRUGO , switch_int_get , NULL , MODULE_INS_INT); + static SENSOR_DEVICE_ATTR(module_int , S_IRUGO , switch_int_get , NULL , MODULE_INT); + static SENSOR_DEVICE_ATTR(module_power_int , S_IRUGO , switch_int_get , NULL , MODULE_POWER_INT); + static SENSOR_DEVICE_ATTR(ther_sensor_int , S_IRUGO , switch_int_get , NULL , THER_SENSOR_INT); + static SENSOR_DEVICE_ATTR(io_board_int , S_IRUGO , switch_int_get , NULL , IO_BOARD_INT); + static SENSOR_DEVICE_ATTR(fan_error_int , S_IRUGO , switch_int_get , NULL , FAN_ERROR_INT); + static SENSOR_DEVICE_ATTR(phy_power_int , S_IRUGO , switch_int_get , NULL , PHY_POWER_INT); + static SENSOR_DEVICE_ATTR(sw_power_int , S_IRUGO , switch_int_get , NULL , SW_POWER_INT); + static SENSOR_DEVICE_ATTR(module_ins_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , MODULE_INS_INT_MASK); + static SENSOR_DEVICE_ATTR(module_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , MODULE_INT_MASK); + static SENSOR_DEVICE_ATTR(module_pow_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , MODULE_POW_INT_MASK); + static SENSOR_DEVICE_ATTR(ther_sen_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , THER_SEN_INT_MASK); + static SENSOR_DEVICE_ATTR(io_board_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , IO_BOARD_INT_MASK); + static SENSOR_DEVICE_ATTR(fan_error_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , FAN_ERROR_INT_MASK); + static SENSOR_DEVICE_ATTR(phy_power_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , PHY_POWER_INT_MASK); + static SENSOR_DEVICE_ATTR(sw_power_int_mask , S_IRUGO | S_IWUSR , switch_int_mask_get , switch_int_mask_set , SW_POWER_INT_MASK); + static SENSOR_DEVICE_ATTR(sfp_select , S_IRUGO | S_IWUSR , sfp_select_get , sfp_select_set , SFP_SELECT); + static SENSOR_DEVICE_ATTR(sfp_port_tx_1 , S_IRUGO | S_IWUSR , sfp_tx_get , sfp_tx_set , 1); + static SENSOR_DEVICE_ATTR(sfp_port_tx_2 , S_IRUGO | S_IWUSR , sfp_tx_get , sfp_tx_set , 2); + static SENSOR_DEVICE_ATTR(sfp_port_tx_mgm , S_IRUGO | S_IWUSR , sfp_tx_get , sfp_tx_set , 3); + static SENSOR_DEVICE_ATTR(sfp_port_1 , S_IRUGO , sfp_insert_get , NULL , SFP_PORT_1); + static SENSOR_DEVICE_ATTR(sfp_port_2 , S_IRUGO , sfp_insert_get , NULL , SFP_PORT_2); + static SENSOR_DEVICE_ATTR(sfp_port_mgm , S_IRUGO , sfp_insert_get , NULL , SFP_PORT_MGM); + static SENSOR_DEVICE_ATTR(sfp_port_rx_1 , S_IRUGO , sfp_rx_get , NULL , SFP_PORT_RX_1); + static SENSOR_DEVICE_ATTR(sfp_port_rx_2 , S_IRUGO , sfp_rx_get , NULL , SFP_PORT_RX_2); + static SENSOR_DEVICE_ATTR(sfp_port_rx_mgm , S_IRUGO , sfp_rx_get , NULL , SFP_PORT_RX_MGM); + static SENSOR_DEVICE_ATTR(sfp_loss_int , S_IRUGO , sys_int_get , NULL , SFP_LOSS_INT); + static SENSOR_DEVICE_ATTR(sfp_abs_int , S_IRUGO , sys_int_get , NULL , SFP_ABS_INT); + static SENSOR_DEVICE_ATTR(sfp_loss_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , SFP_LOSS_MASK); + static SENSOR_DEVICE_ATTR(sfp_abs_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , SFP_ABS_MASK); + static SENSOR_DEVICE_ATTR(alert_th0_int , S_IRUGO , thermal_int_get , NULL , ALERT_TH0_INT); + static SENSOR_DEVICE_ATTR(alert_th1_int , S_IRUGO , thermal_int_get , NULL , ALERT_TH1_INT); + static SENSOR_DEVICE_ATTR(alert_th2_int , S_IRUGO , thermal_int_get , NULL , ALERT_TH2_INT); + static SENSOR_DEVICE_ATTR(alert_th3_int , S_IRUGO , thermal_int_get , NULL , ALERT_TH3_INT); + static SENSOR_DEVICE_ATTR(alert_th4_int , S_IRUGO , thermal_int_get , NULL , ALERT_TH4_INT); + static SENSOR_DEVICE_ATTR(alert_th5_int , S_IRUGO , thermal_int_get , NULL , ALERT_TH5_INT); + static SENSOR_DEVICE_ATTR(alert_th0_int_mask , S_IRUGO | S_IWUSR , thermal_int_mask_get , thermal_int_mask_set , ALERT_TH0_INT_MASK); + static SENSOR_DEVICE_ATTR(alert_th1_int_mask , S_IRUGO | S_IWUSR , thermal_int_mask_get , thermal_int_mask_set , ALERT_TH1_INT_MASK); + static SENSOR_DEVICE_ATTR(alert_th2_int_mask , S_IRUGO | S_IWUSR , thermal_int_mask_get , thermal_int_mask_set , ALERT_TH2_INT_MASK); + static SENSOR_DEVICE_ATTR(alert_th3_int_mask , S_IRUGO | S_IWUSR , thermal_int_mask_get , thermal_int_mask_set , ALERT_TH3_INT_MASK); + static SENSOR_DEVICE_ATTR(alert_th4_int_mask , S_IRUGO | S_IWUSR , thermal_int_mask_get , thermal_int_mask_set , ALERT_TH4_INT_MASK); + static SENSOR_DEVICE_ATTR(alert_th5_int_mask , S_IRUGO | S_IWUSR , thermal_int_mask_get , thermal_int_mask_set , ALERT_TH5_INT_MASK); + /* x86-64-cameo-esc600-128q-led.c */ + static SENSOR_DEVICE_ATTR(led_sys , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 1 ); + static SENSOR_DEVICE_ATTR(led_loc , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 2 ); + static SENSOR_DEVICE_ATTR(led_flow , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 3 ); + static SENSOR_DEVICE_ATTR(led_4_1 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 1 ); + static SENSOR_DEVICE_ATTR(led_4_2 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 2 ); + static SENSOR_DEVICE_ATTR(led_4_3 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 3 ); + static SENSOR_DEVICE_ATTR(led_4_4 , S_IRUGO | S_IWUSR , switch_led_4_get , switch_led_4_set , 4 ); + static SENSOR_DEVICE_ATTR(led_5_1 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 1 ); + static SENSOR_DEVICE_ATTR(led_5_2 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 2 ); + static SENSOR_DEVICE_ATTR(led_5_3 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 3 ); + static SENSOR_DEVICE_ATTR(led_5_4 , S_IRUGO | S_IWUSR , switch_led_5_get , switch_led_5_set , 4 ); + static SENSOR_DEVICE_ATTR(led_fiber , S_IRUGO | S_IWUSR , led_fiber_get , led_fiber_set , LED_FIBER); + /* x86-64-cameo-esc600-128q-thermal.c */ + static SENSOR_DEVICE_ATTR(line_card_1_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_1_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_2_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_2_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_3_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_3_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_4_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_4_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_5_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_5_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_6_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_6_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_7_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_7_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_8_up_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_8_UP_TEMP); + static SENSOR_DEVICE_ATTR(line_card_1_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_1_DN_TEMP); + static SENSOR_DEVICE_ATTR(line_card_2_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_2_DN_TEMP); + static SENSOR_DEVICE_ATTR(line_card_3_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_3_DN_TEMP); + static SENSOR_DEVICE_ATTR(line_card_4_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_4_DN_TEMP); + static SENSOR_DEVICE_ATTR(line_card_5_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_5_DN_TEMP); + static SENSOR_DEVICE_ATTR(line_card_6_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_6_DN_TEMP); + static SENSOR_DEVICE_ATTR(line_card_7_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_7_DN_TEMP); + static SENSOR_DEVICE_ATTR(line_card_8_dn_temp , S_IRUGO , line_card_temp_get , NULL , LINE_CARD_8_DN_TEMP); + static SENSOR_DEVICE_ATTR(nct7511_temp , S_IRUGO , themal_temp_get , NULL , NCT7511_TEMP); + static SENSOR_DEVICE_ATTR(left_bot_sb_temp , S_IRUGO , themal_temp_get , NULL , LEFT_BOT_SB_TEMP); + static SENSOR_DEVICE_ATTR(ctr_top_sb_temp , S_IRUGO , themal_temp_get , NULL , CTR_TOP_SB_TEMP); + static SENSOR_DEVICE_ATTR(ctr_sb_temp , S_IRUGO , themal_temp_get , NULL , CTR_SB_TEMP); + static SENSOR_DEVICE_ATTR(left_top_cb_temp , S_IRUGO , themal_temp_get , NULL , LEFT_TOP_CB_TEMP); + static SENSOR_DEVICE_ATTR(ctr_cb_temp , S_IRUGO , themal_temp_get , NULL , CTR_CB_TEMP); + static SENSOR_DEVICE_ATTR(right_bot_cb_temp , S_IRUGO , themal_temp_get , NULL , RIGHT_BOT_CB_TEMP); + static SENSOR_DEVICE_ATTR(left_bot_cb_temp , S_IRUGO , themal_temp_get , NULL , LEFT_BOT_CB_TEMP); + static SENSOR_DEVICE_ATTR(io_board_temp , S_IRUGO , themal_temp_get , NULL , IO_BOARD_TEMP); + /* x86-64-cameo-esc600-128q-fan.c */ + static SENSOR_DEVICE_ATTR(fanctrl_mode , S_IRUGO , fan_ctrl_mode_get , NULL , FANCTRL_MODE); + static SENSOR_DEVICE_ATTR(fanctrl_rpm , S_IRUGO , fan_ctrl_rpm_get , NULL , FANCTRL_RPM); + static SENSOR_DEVICE_ATTR(fan1_stat , S_IRUGO , fan_status_get , NULL , 1); + static SENSOR_DEVICE_ATTR(fan2_stat , S_IRUGO , fan_status_get , NULL , 2); + static SENSOR_DEVICE_ATTR(fan3_stat , S_IRUGO , fan_status_get , NULL , 3); + static SENSOR_DEVICE_ATTR(fan4_stat , S_IRUGO , fan_status_get , NULL , 4); + static SENSOR_DEVICE_ATTR(fan1_present , S_IRUGO , fan_present_get , NULL , 1); + static SENSOR_DEVICE_ATTR(fan2_present , S_IRUGO , fan_present_get , NULL , 2); + static SENSOR_DEVICE_ATTR(fan3_present , S_IRUGO , fan_present_get , NULL , 3); + static SENSOR_DEVICE_ATTR(fan4_present , S_IRUGO , fan_present_get , NULL , 4); + static SENSOR_DEVICE_ATTR(fan1_power , S_IRUGO , fan_power_get , NULL , 1); + static SENSOR_DEVICE_ATTR(fan2_power , S_IRUGO , fan_power_get , NULL , 2); + static SENSOR_DEVICE_ATTR(fan3_power , S_IRUGO , fan_power_get , NULL , 3); + static SENSOR_DEVICE_ATTR(fan4_power , S_IRUGO , fan_power_get , NULL , 4); + static SENSOR_DEVICE_ATTR(fan1_direct , S_IRUGO , fan_direct_get , NULL , 1); + static SENSOR_DEVICE_ATTR(fan2_direct , S_IRUGO , fan_direct_get , NULL , 2); + static SENSOR_DEVICE_ATTR(fan3_direct , S_IRUGO , fan_direct_get , NULL , 3); + static SENSOR_DEVICE_ATTR(fan4_direct , S_IRUGO , fan_direct_get , NULL , 4); + static SENSOR_DEVICE_ATTR(fan1_rpm , S_IRUGO , fan_rpm_get , NULL , FAN_1_RPM); + static SENSOR_DEVICE_ATTR(fan2_rpm , S_IRUGO , fan_rpm_get , NULL , FAN_2_RPM); + static SENSOR_DEVICE_ATTR(fan3_rpm , S_IRUGO , fan_rpm_get , NULL , FAN_3_RPM); + static SENSOR_DEVICE_ATTR(fan4_rpm , S_IRUGO , fan_rpm_get , NULL , FAN_4_RPM); + /* x86-64-cameo-esc600-128q-power.c */ + static SENSOR_DEVICE_ATTR(psu1_good , S_IRUGO , psu_status_get , NULL , 1); + static SENSOR_DEVICE_ATTR(psu2_good , S_IRUGO , psu_status_get , NULL , 2); + static SENSOR_DEVICE_ATTR(psu3_good , S_IRUGO , psu_status_get , NULL , 3); + static SENSOR_DEVICE_ATTR(psu4_good , S_IRUGO , psu_status_get , NULL , 4); + static SENSOR_DEVICE_ATTR(psu1_prnt , S_IRUGO , psu_present_get , NULL , 1); + static SENSOR_DEVICE_ATTR(psu2_prnt , S_IRUGO , psu_present_get , NULL , 2); + static SENSOR_DEVICE_ATTR(psu3_prnt , S_IRUGO , psu_present_get , NULL , 3); + static SENSOR_DEVICE_ATTR(psu4_prnt , S_IRUGO , psu_present_get , NULL , 4); + static SENSOR_DEVICE_ATTR(psu1_vin , S_IRUGO , psu_vin_get , NULL , PSU1_VIN); + static SENSOR_DEVICE_ATTR(psu2_vin , S_IRUGO , psu_vin_get , NULL , PSU2_VIN); + static SENSOR_DEVICE_ATTR(psu3_vin , S_IRUGO , psu_vin_get , NULL , PSU3_VIN); + static SENSOR_DEVICE_ATTR(psu4_vin , S_IRUGO , psu_vin_get , NULL , PSU4_VIN); + static SENSOR_DEVICE_ATTR(psu1_iin , S_IRUGO , psu_iin_get , NULL , PSU1_IIN); + static SENSOR_DEVICE_ATTR(psu2_iin , S_IRUGO , psu_iin_get , NULL , PSU2_IIN); + static SENSOR_DEVICE_ATTR(psu3_iin , S_IRUGO , psu_iin_get , NULL , PSU3_IIN); + static SENSOR_DEVICE_ATTR(psu4_iin , S_IRUGO , psu_iin_get , NULL , PSU4_IIN); + static SENSOR_DEVICE_ATTR(psu1_vout , S_IRUGO , psu_vout_get , NULL , PSU1_VOUT); + static SENSOR_DEVICE_ATTR(psu2_vout , S_IRUGO , psu_vout_get , NULL , PSU2_VOUT); + static SENSOR_DEVICE_ATTR(psu3_vout , S_IRUGO , psu_vout_get , NULL , PSU3_VOUT); + static SENSOR_DEVICE_ATTR(psu4_vout , S_IRUGO , psu_vout_get , NULL , PSU4_VOUT); + static SENSOR_DEVICE_ATTR(psu1_iout , S_IRUGO , psu_iout_get , NULL , PSU1_IOUT); + static SENSOR_DEVICE_ATTR(psu2_iout , S_IRUGO , psu_iout_get , NULL , PSU2_IOUT); + static SENSOR_DEVICE_ATTR(psu3_iout , S_IRUGO , psu_iout_get , NULL , PSU3_IOUT); + static SENSOR_DEVICE_ATTR(psu4_iout , S_IRUGO , psu_iout_get , NULL , PSU4_IOUT); + static SENSOR_DEVICE_ATTR(psu1_temp , S_IRUGO , psu_temp_get , NULL , PSU1_TEMP); + static SENSOR_DEVICE_ATTR(psu2_temp , S_IRUGO , psu_temp_get , NULL , PSU2_TEMP); + static SENSOR_DEVICE_ATTR(psu3_temp , S_IRUGO , psu_temp_get , NULL , PSU3_TEMP); + static SENSOR_DEVICE_ATTR(psu4_temp , S_IRUGO , psu_temp_get , NULL , PSU4_TEMP); + static SENSOR_DEVICE_ATTR(psu1_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU1_FAN_SPEED); + static SENSOR_DEVICE_ATTR(psu2_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU2_FAN_SPEED); + static SENSOR_DEVICE_ATTR(psu3_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU3_FAN_SPEED); + static SENSOR_DEVICE_ATTR(psu4_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU4_FAN_SPEED); + static SENSOR_DEVICE_ATTR(psu1_pout , S_IRUGO , psu_pout_get , NULL , PSU1_POUT); + static SENSOR_DEVICE_ATTR(psu2_pout , S_IRUGO , psu_pout_get , NULL , PSU2_POUT); + static SENSOR_DEVICE_ATTR(psu3_pout , S_IRUGO , psu_pout_get , NULL , PSU3_POUT); + static SENSOR_DEVICE_ATTR(psu4_pout , S_IRUGO , psu_pout_get , NULL , PSU4_POUT); + static SENSOR_DEVICE_ATTR(psu1_pin , S_IRUGO , psu_pin_get , NULL , PSU1_PIN); + static SENSOR_DEVICE_ATTR(psu2_pin , S_IRUGO , psu_pin_get , NULL , PSU2_PIN); + static SENSOR_DEVICE_ATTR(psu3_pin , S_IRUGO , psu_pin_get , NULL , PSU3_PIN); + static SENSOR_DEVICE_ATTR(psu4_pin , S_IRUGO , psu_pin_get , NULL , PSU4_PIN); + static SENSOR_DEVICE_ATTR(psu1_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU1_MFR_MODEL); + static SENSOR_DEVICE_ATTR(psu2_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU2_MFR_MODEL); + static SENSOR_DEVICE_ATTR(psu3_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU3_MFR_MODEL); + static SENSOR_DEVICE_ATTR(psu4_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU4_MFR_MODEL); + static SENSOR_DEVICE_ATTR(psu1_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU1_MFR_IOUT_MAX); + static SENSOR_DEVICE_ATTR(psu2_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU2_MFR_IOUT_MAX); + static SENSOR_DEVICE_ATTR(psu3_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU3_MFR_IOUT_MAX); + static SENSOR_DEVICE_ATTR(psu4_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU4_MFR_IOUT_MAX); + static SENSOR_DEVICE_ATTR(psu1_vmode , S_IRUGO , psu_vmode_get , NULL , PSU1_VMODE); + static SENSOR_DEVICE_ATTR(psu2_vmode , S_IRUGO , psu_vmode_get , NULL , PSU2_VMODE); + static SENSOR_DEVICE_ATTR(psu3_vmode , S_IRUGO , psu_vmode_get , NULL , PSU3_VMODE); + static SENSOR_DEVICE_ATTR(psu4_vmode , S_IRUGO , psu_vmode_get , NULL , PSU4_VMODE); + static SENSOR_DEVICE_ATTR(dc_6e_p0_vout , S_IRUGO , dc_vout_get , NULL , DC_6E_P0_VOUT); + static SENSOR_DEVICE_ATTR(dc_70_p0_vout , S_IRUGO , dc_vout_get , NULL , DC_70_P0_VOUT); + static SENSOR_DEVICE_ATTR(dc_70_p1_vout , S_IRUGO , dc_vout_get , NULL , DC_70_P1_VOUT); + static SENSOR_DEVICE_ATTR(dc_6e_p0_iout , S_IRUGO , dc_iout_get , NULL , DC_6E_P0_IOUT); + static SENSOR_DEVICE_ATTR(dc_70_p0_iout , S_IRUGO , dc_iout_get , NULL , DC_70_P0_IOUT); + static SENSOR_DEVICE_ATTR(dc_70_p1_iout , S_IRUGO , dc_iout_get , NULL , DC_70_P1_IOUT); + static SENSOR_DEVICE_ATTR(dc_6e_p0_pout , S_IRUGO , dc_pout_get , NULL , DC_6E_P0_POUT); + static SENSOR_DEVICE_ATTR(dc_70_p0_pout , S_IRUGO , dc_pout_get , NULL , DC_70_P0_POUT); + static SENSOR_DEVICE_ATTR(dc_70_p1_pout , S_IRUGO , dc_pout_get , NULL , DC_70_P1_POUT); + static SENSOR_DEVICE_ATTR(card_1_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_1_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_2_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_3_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_4_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_5_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_6_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_7_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_11_p0_vout , S_IRUGO , dc_11_p0_vout_get , NULL , CARD_8_DC_11_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_1_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_2_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_3_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_4_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_5_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_6_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_7_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_11_p1_vout , S_IRUGO , dc_11_p1_vout_get , NULL , CARD_8_DC_11_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_1_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_2_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_3_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_4_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_5_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_6_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_7_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_12_p0_vout , S_IRUGO , dc_12_p0_vout_get , NULL , CARD_8_DC_12_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_1_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_2_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_3_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_4_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_5_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_6_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_7_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_12_p1_vout , S_IRUGO , dc_12_p1_vout_get , NULL , CARD_8_DC_12_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_1_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_2_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_3_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_4_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_5_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_6_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_7_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_13_p0_vout , S_IRUGO , dc_13_p0_vout_get , NULL , CARD_8_DC_13_P0_VOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_1_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_2_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_3_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_4_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_5_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_6_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_7_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_13_p1_vout , S_IRUGO , dc_13_p1_vout_get , NULL , CARD_8_DC_13_P1_VOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_1_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_2_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_3_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_4_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_5_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_6_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_7_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_11_p0_iout , S_IRUGO , dc_11_p0_iout_get , NULL , CARD_8_DC_11_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_1_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_2_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_3_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_4_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_5_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_6_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_7_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_11_p1_iout , S_IRUGO , dc_11_p1_iout_get , NULL , CARD_8_DC_11_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_1_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_2_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_3_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_4_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_5_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_6_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_7_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_12_p0_iout , S_IRUGO , dc_12_p0_iout_get , NULL , CARD_8_DC_12_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_1_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_2_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_3_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_4_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_5_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_6_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_7_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_12_p1_iout , S_IRUGO , dc_12_p1_iout_get , NULL , CARD_8_DC_12_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_1_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_2_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_3_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_4_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_5_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_6_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_7_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_13_p0_iout , S_IRUGO , dc_13_p0_iout_get , NULL , CARD_8_DC_13_P0_IOUT); + static SENSOR_DEVICE_ATTR(card_1_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_1_DC_13_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_2_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_2_DC_13_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_3_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_3_DC_13_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_4_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_4_DC_13_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_5_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_5_DC_13_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_6_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_6_DC_13_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_7_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_7_DC_13_P1_IOUT); + static SENSOR_DEVICE_ATTR(card_8_dc_13_p1_iout , S_IRUGO , dc_13_p1_iout_get , NULL , CARD_8_DC_13_P1_IOUT); /* end of sysfs attributes for SENSOR_DEVICE_ATTR */ /* sysfs attributes for hwmon */ +/* i2c-0 */ static struct attribute *ESC600_SYS_attributes[] = { -#ifdef ESC_600_BMC_WANTED + &sensor_dev_attr_cpld_30_ver.dev_attr.attr, + &sensor_dev_attr_cpld_31_ver.dev_attr.attr, + &sensor_dev_attr_cpld_33_ver.dev_attr.attr, + &sensor_dev_attr_wdt_en.dev_attr.attr, + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_usb_en.dev_attr.attr, + &sensor_dev_attr_shutdown_set.dev_attr.attr, + &sensor_dev_attr_reset.dev_attr.attr, &sensor_dev_attr_bmc_present.dev_attr.attr, -#endif /*ESC_600_BMC_WANTED*/ - &sensor_dev_attr_cpld_version.dev_attr.attr, -#ifdef WDT_CTRL_WANTED - &sensor_dev_attr_wdt_ctrl.dev_attr.attr, -#endif -#ifdef EEPROM_WP_WANTED - &sensor_dev_attr_eeprom_wp_ctrl.dev_attr.attr, -#endif - NULL -}; -static struct attribute *ESC600_PSU_attributes[] = -{ - &sensor_dev_attr_psu_present.dev_attr.attr, - &sensor_dev_attr_psu_status.dev_attr.attr, -#ifdef ESC_600_BMC_WANTED - &sensor_dev_attr_psu_module_1.dev_attr.attr, - &sensor_dev_attr_psu_module_2.dev_attr.attr, - &sensor_dev_attr_psu_module_3.dev_attr.attr, - &sensor_dev_attr_psu_module_4.dev_attr.attr, - &sensor_dev_attr_dc_chip_switch.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_1.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_2.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_3.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_4.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_5.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_6.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_7.dev_attr.attr, - &sensor_dev_attr_dc_chip_slot_8.dev_attr.attr, -#endif /*ESC_600_BMC_WANTED*/ - NULL -}; - -#ifdef ESC_600_JTAG_WANTED -static struct attribute *ESC600_JTAG_attributes[] = -{ - &sensor_dev_attr_jtag_select.dev_attr.attr, - NULL -}; -#endif - -static struct attribute *ESC600_SFP_attributes[] = -{ - &sensor_dev_attr_sfp_select.dev_attr.attr, - &sensor_dev_attr_sfp_insert.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, - NULL -}; - -static struct attribute *ESC600_Mask_attributes[] = -{ -#ifdef ESC_600_STAT_WANTED - &sensor_dev_attr_sersor_status_mask_all.dev_attr.attr, - &sensor_dev_attr_sersor_status_mask_1.dev_attr.attr, - &sensor_dev_attr_sersor_status_mask_2.dev_attr.attr, - &sensor_dev_attr_sersor_status_mask_3.dev_attr.attr, - &sensor_dev_attr_sersor_status_mask_4.dev_attr.attr, - &sensor_dev_attr_sersor_status_mask_5.dev_attr.attr, - &sensor_dev_attr_sersor_status_mask_6.dev_attr.attr, -#endif /*ESC_600_STAT_WANTED*/ -#ifdef ESC_600_ALARM_WANTED - &sensor_dev_attr_switch_alarm_mask_all.dev_attr.attr, - &sensor_dev_attr_switch_alarm_mask_1.dev_attr.attr, - &sensor_dev_attr_switch_alarm_mask_2.dev_attr.attr, - &sensor_dev_attr_switch_alarm_mask_3.dev_attr.attr, - &sensor_dev_attr_switch_alarm_mask_4.dev_attr.attr, -#endif /*ESC_600_ALARM_WANTED*/ -#ifdef ESC_600_INT_WANTED - &sensor_dev_attr_sersor_int_mask_all.dev_attr.attr, - &sensor_dev_attr_sersor_int_mask_1.dev_attr.attr, - &sensor_dev_attr_sersor_int_mask_2.dev_attr.attr, - &sensor_dev_attr_switch_int_mask_all.dev_attr.attr, - &sensor_dev_attr_phy_module_ins_mask.dev_attr.attr, - &sensor_dev_attr_phy_module_int_mask.dev_attr.attr, - &sensor_dev_attr_phy_module_power_mask.dev_attr.attr, - &sensor_dev_attr_cpld2_int_mask.dev_attr.attr, + &sensor_dev_attr_sw_alert_th0.dev_attr.attr, + &sensor_dev_attr_sw_alert_th1.dev_attr.attr, + &sensor_dev_attr_sw_alert_th2.dev_attr.attr, + &sensor_dev_attr_sw_alert_th3.dev_attr.attr, + &sensor_dev_attr_sw_alert_th0_mask.dev_attr.attr, + &sensor_dev_attr_sw_alert_th1_mask.dev_attr.attr, + &sensor_dev_attr_sw_alert_th2_mask.dev_attr.attr, + &sensor_dev_attr_sw_alert_th3_mask.dev_attr.attr, + &sensor_dev_attr_cb_int.dev_attr.attr, + &sensor_dev_attr_sb_int.dev_attr.attr, + &sensor_dev_attr_cb_int_mask.dev_attr.attr, + &sensor_dev_attr_sb_int_mask.dev_attr.attr, + &sensor_dev_attr_module_reset.dev_attr.attr, + &sensor_dev_attr_module_1_present.dev_attr.attr, + &sensor_dev_attr_module_2_present.dev_attr.attr, + &sensor_dev_attr_module_3_present.dev_attr.attr, + &sensor_dev_attr_module_4_present.dev_attr.attr, + &sensor_dev_attr_module_5_present.dev_attr.attr, + &sensor_dev_attr_module_6_present.dev_attr.attr, + &sensor_dev_attr_module_7_present.dev_attr.attr, + &sensor_dev_attr_module_8_present.dev_attr.attr, + &sensor_dev_attr_module_1_power.dev_attr.attr, + &sensor_dev_attr_module_2_power.dev_attr.attr, + &sensor_dev_attr_module_3_power.dev_attr.attr, + &sensor_dev_attr_module_4_power.dev_attr.attr, + &sensor_dev_attr_module_5_power.dev_attr.attr, + &sensor_dev_attr_module_6_power.dev_attr.attr, + &sensor_dev_attr_module_7_power.dev_attr.attr, + &sensor_dev_attr_module_8_power.dev_attr.attr, + &sensor_dev_attr_module_1_enable.dev_attr.attr, + &sensor_dev_attr_module_2_enable.dev_attr.attr, + &sensor_dev_attr_module_3_enable.dev_attr.attr, + &sensor_dev_attr_module_4_enable.dev_attr.attr, + &sensor_dev_attr_module_5_enable.dev_attr.attr, + &sensor_dev_attr_module_6_enable.dev_attr.attr, + &sensor_dev_attr_module_7_enable.dev_attr.attr, + &sensor_dev_attr_module_8_enable.dev_attr.attr, + &sensor_dev_attr_module_ins_int.dev_attr.attr, + &sensor_dev_attr_module_int.dev_attr.attr, + &sensor_dev_attr_module_power_int.dev_attr.attr, + &sensor_dev_attr_ther_sensor_int.dev_attr.attr, + &sensor_dev_attr_io_board_int.dev_attr.attr, + &sensor_dev_attr_fan_error_int.dev_attr.attr, + &sensor_dev_attr_phy_power_int.dev_attr.attr, + &sensor_dev_attr_sw_power_int.dev_attr.attr, + &sensor_dev_attr_module_ins_int_mask.dev_attr.attr, + &sensor_dev_attr_module_int_mask.dev_attr.attr, + &sensor_dev_attr_module_pow_int_mask.dev_attr.attr, + &sensor_dev_attr_ther_sen_int_mask.dev_attr.attr, &sensor_dev_attr_io_board_int_mask.dev_attr.attr, - &sensor_dev_attr_fan_error_mask.dev_attr.attr, - &sensor_dev_attr_psu_int_mask.dev_attr.attr, - &sensor_dev_attr_sfp_loss_int_mask.dev_attr.attr, - &sensor_dev_attr_sfp_abs_int_mask.dev_attr.attr, -#endif /*ESC_600_INT_WANTED*/ + &sensor_dev_attr_fan_error_int_mask.dev_attr.attr, + &sensor_dev_attr_phy_power_int_mask.dev_attr.attr, + &sensor_dev_attr_sw_power_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_select.dev_attr.attr, + &sensor_dev_attr_sfp_port_tx_1.dev_attr.attr, + &sensor_dev_attr_sfp_port_tx_2.dev_attr.attr, + &sensor_dev_attr_sfp_port_tx_mgm.dev_attr.attr, + &sensor_dev_attr_sfp_port_1.dev_attr.attr, + &sensor_dev_attr_sfp_port_2.dev_attr.attr, + &sensor_dev_attr_sfp_port_mgm.dev_attr.attr, + &sensor_dev_attr_sfp_port_rx_1.dev_attr.attr, + &sensor_dev_attr_sfp_port_rx_2.dev_attr.attr, + &sensor_dev_attr_sfp_port_rx_mgm.dev_attr.attr, + &sensor_dev_attr_sfp_loss_int.dev_attr.attr, + &sensor_dev_attr_sfp_abs_int.dev_attr.attr, + &sensor_dev_attr_sfp_loss_mask.dev_attr.attr, + &sensor_dev_attr_sfp_abs_mask.dev_attr.attr, + &sensor_dev_attr_alert_th0_int.dev_attr.attr, + &sensor_dev_attr_alert_th1_int.dev_attr.attr, + &sensor_dev_attr_alert_th2_int.dev_attr.attr, + &sensor_dev_attr_alert_th3_int.dev_attr.attr, + &sensor_dev_attr_alert_th4_int.dev_attr.attr, + &sensor_dev_attr_alert_th5_int.dev_attr.attr, + &sensor_dev_attr_alert_th0_int_mask.dev_attr.attr, + &sensor_dev_attr_alert_th1_int_mask.dev_attr.attr, + &sensor_dev_attr_alert_th2_int_mask.dev_attr.attr, + &sensor_dev_attr_alert_th3_int_mask.dev_attr.attr, + &sensor_dev_attr_alert_th4_int_mask.dev_attr.attr, + &sensor_dev_attr_alert_th5_int_mask.dev_attr.attr, NULL }; - -static struct attribute *ESC600_Fan_attributes[] = -{ - &sensor_dev_attr_fan_status.dev_attr.attr, - &sensor_dev_attr_fan_insert.dev_attr.attr, - &sensor_dev_attr_fan_power.dev_attr.attr, - &sensor_dev_attr_fan_direct.dev_attr.attr, - &sensor_dev_attr_fan_speed_rpm.dev_attr.attr, - NULL -}; - -#ifdef USB_CTRL_WANTED -static struct attribute *ESC600_USB_attributes[] = -{ - &sensor_dev_attr_usb_power.dev_attr.attr, - NULL -}; -#endif /*USB_CTRL_WANTED*/ - -#ifdef LED_CTRL_WANTED static struct attribute *ESC600_LED_attributes[] = { - - &sensor_dev_attr_led_ctrl.dev_attr.attr, - &sensor_dev_attr_sys_led.dev_attr.attr, - &sensor_dev_attr_switch_led_all.dev_attr.attr, -#ifdef LED_L3_CTRL_WANTED - &sensor_dev_attr_switch_led_3_1.dev_attr.attr, - &sensor_dev_attr_switch_led_3_2.dev_attr.attr, - &sensor_dev_attr_switch_led_3_3.dev_attr.attr, - &sensor_dev_attr_switch_led_3_4.dev_attr.attr, -#endif /*LED_L3_CTRL_WANTED*/ - &sensor_dev_attr_switch_led_4_1.dev_attr.attr, - &sensor_dev_attr_switch_led_4_2.dev_attr.attr, - &sensor_dev_attr_switch_led_4_3.dev_attr.attr, - &sensor_dev_attr_switch_led_4_4.dev_attr.attr, - &sensor_dev_attr_switch_led_5_1.dev_attr.attr, - &sensor_dev_attr_switch_led_5_2.dev_attr.attr, - &sensor_dev_attr_switch_led_5_3.dev_attr.attr, - &sensor_dev_attr_switch_led_5_4.dev_attr.attr, + &sensor_dev_attr_led_sys.dev_attr.attr, + &sensor_dev_attr_led_loc.dev_attr.attr, + &sensor_dev_attr_led_flow.dev_attr.attr, + &sensor_dev_attr_led_4_1.dev_attr.attr, + &sensor_dev_attr_led_4_2.dev_attr.attr, + &sensor_dev_attr_led_4_3.dev_attr.attr, + &sensor_dev_attr_led_4_4.dev_attr.attr, + &sensor_dev_attr_led_5_1.dev_attr.attr, + &sensor_dev_attr_led_5_2.dev_attr.attr, + &sensor_dev_attr_led_5_3.dev_attr.attr, + &sensor_dev_attr_led_5_4.dev_attr.attr, + &sensor_dev_attr_led_fiber.dev_attr.attr, NULL }; -#endif - -static struct attribute *ESC600_Reset_attributes[] = +static struct attribute *ESC600_THERMAL_attributes[] = { - &sensor_dev_attr_shutdown_sys.dev_attr.attr, - &sensor_dev_attr_reset_sys.dev_attr.attr, + &sensor_dev_attr_line_card_1_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_2_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_3_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_4_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_5_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_6_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_7_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_8_up_temp.dev_attr.attr, + &sensor_dev_attr_line_card_1_dn_temp.dev_attr.attr, + &sensor_dev_attr_line_card_2_dn_temp.dev_attr.attr, + &sensor_dev_attr_line_card_3_dn_temp.dev_attr.attr, + &sensor_dev_attr_line_card_4_dn_temp.dev_attr.attr, + &sensor_dev_attr_line_card_5_dn_temp.dev_attr.attr, + &sensor_dev_attr_line_card_6_dn_temp.dev_attr.attr, + &sensor_dev_attr_line_card_7_dn_temp.dev_attr.attr, + &sensor_dev_attr_line_card_8_dn_temp.dev_attr.attr, + &sensor_dev_attr_nct7511_temp.dev_attr.attr, + &sensor_dev_attr_left_bot_sb_temp.dev_attr.attr, + &sensor_dev_attr_ctr_top_sb_temp.dev_attr.attr, + &sensor_dev_attr_ctr_sb_temp.dev_attr.attr, + &sensor_dev_attr_left_top_cb_temp.dev_attr.attr, + &sensor_dev_attr_ctr_cb_temp.dev_attr.attr, + &sensor_dev_attr_right_bot_cb_temp.dev_attr.attr, + &sensor_dev_attr_left_bot_cb_temp.dev_attr.attr, + &sensor_dev_attr_io_board_temp.dev_attr.attr, NULL }; - -static struct attribute *ESC600_Sensor_attributes[] = +static struct attribute *ESC600_FAN_attributes[] = { -#ifdef ESC_600_STAT_WANTED - &sensor_dev_attr_sensor_status.dev_attr.attr, -#endif /*ESC_600_STAT_WANTED*/ -#ifdef ESC_600_ALARM_WANTED - &sensor_dev_attr_switch_alarm.dev_attr.attr, -#endif /*ESC_600_ALARM_WANTED*/ - &sensor_dev_attr_switch_button.dev_attr.attr, -#ifdef ESC_600_BMC_WANTED - &sensor_dev_attr_sensor_temp.dev_attr.attr, - &sensor_dev_attr_module_temp.dev_attr.attr, - &sensor_dev_attr_mac_temp.dev_attr.attr, -#endif /*ESC_600_BMC_WANTED*/ - NULL -}; - -#ifdef ESC_600_INT_WANTED -static struct attribute *ESC600_INT_attributes[] = -{ - &sensor_dev_attr_sensor_int.dev_attr.attr, - &sensor_dev_attr_switch_int.dev_attr.attr, - &sensor_dev_attr_sfp_int.dev_attr.attr, - &sensor_dev_attr_psu_int.dev_attr.attr, + &sensor_dev_attr_fanctrl_mode.dev_attr.attr, + &sensor_dev_attr_fanctrl_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_stat.dev_attr.attr, + &sensor_dev_attr_fan2_stat.dev_attr.attr, + &sensor_dev_attr_fan3_stat.dev_attr.attr, + &sensor_dev_attr_fan4_stat.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan1_power.dev_attr.attr, + &sensor_dev_attr_fan2_power.dev_attr.attr, + &sensor_dev_attr_fan3_power.dev_attr.attr, + &sensor_dev_attr_fan4_power.dev_attr.attr, + &sensor_dev_attr_fan1_direct.dev_attr.attr, + &sensor_dev_attr_fan2_direct.dev_attr.attr, + &sensor_dev_attr_fan3_direct.dev_attr.attr, + &sensor_dev_attr_fan4_direct.dev_attr.attr, + &sensor_dev_attr_fan1_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rpm.dev_attr.attr, NULL }; -#endif - -static struct attribute *ESC600_Module_attributes[] = +static struct attribute *ESC600_POWER_attributes[] = { - &sensor_dev_attr_module_reset.dev_attr.attr, - &sensor_dev_attr_module_insert.dev_attr.attr, - &sensor_dev_attr_module_power.dev_attr.attr, - &sensor_dev_attr_module_enable.dev_attr.attr, - &sensor_dev_attr_module_12v_status.dev_attr.attr, + &sensor_dev_attr_psu1_good.dev_attr.attr, + &sensor_dev_attr_psu2_good.dev_attr.attr, + &sensor_dev_attr_psu3_good.dev_attr.attr, + &sensor_dev_attr_psu4_good.dev_attr.attr, + &sensor_dev_attr_psu1_prnt.dev_attr.attr, + &sensor_dev_attr_psu2_prnt.dev_attr.attr, + &sensor_dev_attr_psu3_prnt.dev_attr.attr, + &sensor_dev_attr_psu4_prnt.dev_attr.attr, + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu3_vin.dev_attr.attr, + &sensor_dev_attr_psu4_vin.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu3_iin.dev_attr.attr, + &sensor_dev_attr_psu4_iin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu3_vout.dev_attr.attr, + &sensor_dev_attr_psu4_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu3_iout.dev_attr.attr, + &sensor_dev_attr_psu4_iout.dev_attr.attr, + &sensor_dev_attr_psu1_temp.dev_attr.attr, + &sensor_dev_attr_psu2_temp.dev_attr.attr, + &sensor_dev_attr_psu3_temp.dev_attr.attr, + &sensor_dev_attr_psu4_temp.dev_attr.attr, + &sensor_dev_attr_psu1_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu2_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu3_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu4_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + &sensor_dev_attr_psu3_pout.dev_attr.attr, + &sensor_dev_attr_psu4_pout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu3_pin.dev_attr.attr, + &sensor_dev_attr_psu4_pin.dev_attr.attr, + &sensor_dev_attr_psu1_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu2_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu3_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu4_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu1_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu2_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu3_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu4_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu1_vmode.dev_attr.attr, + &sensor_dev_attr_psu2_vmode.dev_attr.attr, + &sensor_dev_attr_psu3_vmode.dev_attr.attr, + &sensor_dev_attr_psu4_vmode.dev_attr.attr, + &sensor_dev_attr_dc_6e_p0_vout.dev_attr.attr, + &sensor_dev_attr_dc_70_p0_vout.dev_attr.attr, + &sensor_dev_attr_dc_70_p1_vout.dev_attr.attr, + &sensor_dev_attr_dc_6e_p0_iout.dev_attr.attr, + &sensor_dev_attr_dc_70_p0_iout.dev_attr.attr, + &sensor_dev_attr_dc_70_p1_iout.dev_attr.attr, + &sensor_dev_attr_dc_6e_p0_pout.dev_attr.attr, + &sensor_dev_attr_dc_70_p0_pout.dev_attr.attr, + &sensor_dev_attr_dc_70_p1_pout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_11_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_11_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_12_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_12_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_13_p0_vout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_13_p1_vout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_11_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_11_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_12_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_12_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_13_p0_iout.dev_attr.attr, + &sensor_dev_attr_card_1_dc_13_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_2_dc_13_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_3_dc_13_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_4_dc_13_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_5_dc_13_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_6_dc_13_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_7_dc_13_p1_iout.dev_attr.attr, + &sensor_dev_attr_card_8_dc_13_p1_iout.dev_attr.attr, NULL }; /* end of sysfs attributes for hwmon */ @@ -645,77 +1092,27 @@ static const struct attribute_group ESC600_SYS_group = .attrs = ESC600_SYS_attributes, }; -static const struct attribute_group ESC600_PSU_group = -{ - .name = "ESC600_PSU", - .attrs = ESC600_PSU_attributes, -}; - -#ifdef ESC_600_JTAG_WANTED -static const struct attribute_group ESC600_JTAG_group = -{ - .name = "ESC600_JTAG", - .attrs = ESC600_JTAG_attributes, -}; -#endif - -static const struct attribute_group ESC600_SFP_group = -{ - .name = "ESC600_SFP", - .attrs = ESC600_SFP_attributes, -}; - -static const struct attribute_group ESC600_MASK_group = -{ - .name = "ESC600_MASK", - .attrs = ESC600_Mask_attributes, -}; - -static const struct attribute_group ESC600_FAN_group = -{ - .name = "ESC600_FAN", - .attrs = ESC600_Fan_attributes, -}; - -#ifdef USB_CTRL_WANTED -static const struct attribute_group ESC600_USB_group = -{ - .name = "ESC600_USB", - .attrs = ESC600_USB_attributes, -}; -#endif /*USB_CTRL_WANTED*/ - -#ifdef LED_CTRL_WANTED static const struct attribute_group ESC600_LED_group = { .name = "ESC600_LED", .attrs = ESC600_LED_attributes, }; -#endif /*LED_CTRL_WANTED*/ -static const struct attribute_group ESC600_Reset_group = +static const struct attribute_group ESC600_THERMAL_group = { - .name = "ESC600_Reset", - .attrs = ESC600_Reset_attributes, + .name = "ESC600_THERMAL", + .attrs = ESC600_THERMAL_attributes, }; -static const struct attribute_group ESC600_Sensor_group = +static const struct attribute_group ESC600_FAN_group = { - .name = "ESC600_Sensor", - .attrs = ESC600_Sensor_attributes, + .name = "ESC600_FAN", + .attrs = ESC600_FAN_attributes, }; -#ifdef ESC_600_INT_WANTED -static const struct attribute_group ESC600_INT_group = +static const struct attribute_group ESC600_POWER_group = { - .name = "ESC600_INT", - .attrs = ESC600_INT_attributes, + .name = "ESC600_POWER", + .attrs = ESC600_POWER_attributes, }; -#endif - -static const struct attribute_group ESC600_Module_group = -{ - .name = "ESC600_Module", - .attrs = ESC600_Module_attributes, -}; -/* end of struct attribute_group */ \ No newline at end of file +/* end of struct attribute_group */ diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/platform_setup.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/platform_setup.py new file mode 100755 index 0000000000..f40e09c27b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/platform_setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='ESC600-128Q sonic platform API', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'esc600-128q/sonic_platform'}, +) \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/setup.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/setup.py index 8f07f05e69..e9e05003a2 100755 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/setup.py +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/setup.py @@ -11,5 +11,5 @@ setup( packages=['esc600-128q'], package_dir={'esc600-128q': 'esc600-128q/credo_baldeagle/python_wheel'}, - package_data={'esc600-128q': 'esc600-128q/credo_baldeagle/python_wheel/*.pyc'} + package_data={'esc600-128q': 'esc600-128q/credo_baldeagle/python_wheel/*.py'} ) diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/__init__.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/__init__.py new file mode 100755 index 0000000000..0b887c8c6b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/__init__.py @@ -0,0 +1 @@ +__all__ = ["platform", "chassis", "fan", "psu"] diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/chassis.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/chassis.py new file mode 100755 index 0000000000..f963df684d --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/chassis.py @@ -0,0 +1,335 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + import os + import time + import subprocess + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.platDev import PlatDev + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" + + +# XCVR type definition +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" +QSFP_DD_TYPE = "QSFP_DD" + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + _global_port_pres_dict = {} + + def __init__(self): + super(Chassis, self).__init__() + + # Initialize SKU name and Platform name + self.sku_name = self._get_sku_name() + self.platform_name = self._get_platform_name() + self.name = self.sku_name + + # get the device infomation of platform + self.platdev = PlatDev() + + #self._component_list = [] + #self._module_list = [] + #self._fan_drawer_list = [] + + self._eeprom = Eeprom() + # init component + for i in range(self.platdev.get_component_count()): + component = Component(i, self.platdev.get_component_name(i), self.platdev.get_component_descript(i)) + self._component_list.append(component) + # init fan list + if self.platdev.get_fan_support(): + fanlist = self.platdev.get_fan_list() + for index in range(0,len(fanlist)): + fan_name = fanlist[index] + for pos in range(0, self.platdev.get_fan_num_by_name(fan_name)): + fan = Fan( index, pos, [self.platdev.get_fan_sysfile_path_by_name(fan_name),'']) + self._fan_list.append(fan) + + # init psu list + psulist = self.platdev.get_psu_list() + for index in range(0, len(psulist)): + psu_name = psulist[index] + psu = Psu(index, [ self.platdev.get_psu_attr_path_by_name(psu_name), \ + self.platdev.get_psu_status_path_by_name(psu_name) ], \ + self.platdev.bmc_is_exist()) + self._psu_list.append(psu) + + # init thermal list + thermal_info_list = self.platdev.get_thermal_dev_info_all() + for index in range(0, len(thermal_info_list)): + if len(self.platdev.get_thermal_dev_tempidx_by_idx(index)) > 1: + for idx in self.platdev.get_thermal_dev_tempidx_by_idx(index): + thermal = Thermal(idx, self.platdev.get_thermal_dev_name_by_idx(index)+"-{}".format(idx), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(),\ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + else: + thermal = Thermal(1, self.platdev.get_thermal_dev_name_by_idx(index), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(), \ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + + # init sfp list + port_num = 1 + for sfpg_name in self.platdev.get_sfp_group_list(): + temp_type = self.platdev.get_sfp_group_type_by_name(sfpg_name) + if temp_type == 'QSFP28': + sfp_type = QSFP_TYPE + elif temp_type == 'QSFP-DD': + sfp_type = QSFP_DD_TYPE + else: + sfp_type = SFP_TYPE + + for x in range(0,self.platdev.get_sfp_group_number_by_name(sfpg_name)): + eeprom_path_list = ['n/a','n/a'] + if self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] != 'n/a': + eeprom_path_list[0] = self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] + '/eeprom' + if os.path.exists(eeprom_path_list[0].replace("0050", "0051")): + eeprom_path_list[1] = eeprom_path_list[0].replace("0050", "0051") + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + sfp = Sfp(port_num, eeprom_path_list, sfp_type, self.platdev.get_sfp_ext_sysfile_list()) + port_num += 1 + self._sfp_list.append(sfp) + + self.init_global_port_presence() + + def _get_sku_name(self): + p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + + def _get_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.name + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr('') + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + # not support any hardware reboot, just return REBOOT_CAUSE_NON_HARDWARE + # to keep reboot cause as software reboot + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + ############################################## + # System LED methods + ############################################## + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + return False + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + raise NotImplementedError + + ############################################## + # Other methods + ############################################## + + def init_global_port_presence(self): + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + port_dict = {} + while True: + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, {'sfp':port_dict} + + time.sleep(1) + + + def sfp_debugger(self): + """ + Try to show all parameters read from eeprom with sfp methods + """ + print("SFP EEPROM data:") + for n in range(0, len(self._sfp_list)): + print("======SFP{}==TYPE {}====".format(n, self._sfp_list[n].sfp_type)) + print("get_transceiver_info:") + print(self._sfp_list[n].get_transceiver_info()) + print(" ") + + print("get_transceiver_threshold_info:") + print(self._sfp_list[n].get_transceiver_threshold_info()) + print(" ") + + print("get_transceiver_bulk_status:") + print(self._sfp_list[n].get_transceiver_bulk_status()) + print(" ") + + print("get_lpmode:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_lpmode())) + # set_lpmode + + print("get_power_override:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_power_override())) + + print("get_temperature:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_temperature())) + + print("get_voltage") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_voltage())) + + print("get_tx_bias") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_bias())) + + print("get_rx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_rx_power())) + + print("get_tx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_power())) + + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/component.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/component.py new file mode 100755 index 0000000000..5fd9dd9092 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/component.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +######################################################################## +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + def __init__(self, idx,name,descript): + ComponentBase.__init__(self) + self.index = idx + self.name = name + self.description = descript + + def _get_cpld_register(self, syspath): + rv = 'ERR' + if (not os.path.isfile(syspath)): + return rv + # noinspection PyBroadException + try: + with open(syspath, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def _get_cpld_version(self, cpld_number): + cpld_version_reg = { + 1: "/sys/class/hwmon/hwmon2/device/ESC600_SYS/cpld_30_ver", + 2: "master_cpld_ver", + 3: "slave_cpld_ver" + } + + cpld_version = self._get_cpld_register(cpld_version_reg[cpld_number]) + + if cpld_version != 'ERR': + return cpld_version[-4:] + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + bios_ver = self._get_bios_version() + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index <= 3: + return self._get_cpld_version(self.index) + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/eeprom.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/eeprom.py new file mode 100755 index 0000000000..8740c4c11a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/eeprom.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +try: + import os + import sys + import re + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + # noinspection PyBroadException + try: + match = re.search( + '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) + if match is not None: + idx = match.group(1) + value = match.group(3).rstrip('\0') + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + err = self.read_eeprom_db() + if err: + # Failed to read EEPROM information from database. Read from cache file + pass + else: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + return self.__parse_output(decode_output) + + status = self.check_status() + if status < 'ok': + return {} + + if not os.path.exists(CACHE_ROOT): + # noinspection PyBroadException + try: + os.makedirs(CACHE_ROOT) + except Exception: + pass + + # + # only the eeprom classes that inherit from eeprom_base + # support caching. Others will work normally + # + # noinspection PyBroadException + try: + self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE)) + except Exception: + pass + + data = self.read_eeprom() + if data is None: + return 0 + # noinspection PyBroadException + try: + self.update_cache(data) + except Exception: + pass + + self.decode_eeprom(data) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(data) + if not is_valid: + return {} + + return self.__parse_output(decode_output) + + def get_eeprom(self): + return self._eeprom + + + def serial_number_str(self): + """ + Returns the serial number + """ + return self._eeprom.get('0x23', "Undefined.") + + def base_mac_addr(self, e): + """ + Returns the base mac address found in the system EEPROM + """ + return self._eeprom.get('0x24', "Undefined.") + + def modelstr(self): + """ + Returns the Model name + """ + return self._eeprom.get('0x28', "Undefined.") + + def part_number_str(self): + """ + Returns the part number + """ + return self._eeprom.get('0x22', "Undefined.") + + def revision_str(self): + """ + Returns the device revision + """ + return self._eeprom.get('0x26', "Undefined.") + + def serial_str(self): + return self._eeprom.get('0x2F', "Undefined.") + + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self._eeprom \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/fan.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/fan.py new file mode 100755 index 0000000000..b63b216dc1 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/fan.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +FAN_POSITION_NAME = ["Front","Rear"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_index, position_index, attr_path, psu_fan = False): + # fan_index: the index of a fan module belongs to + # position_index : position of the fan in a fan module, 0 -> front, 1 -> rear, + # position_index : index of PSU belongs to if psu_fan is True, start from 0 + super(Fan, self).__init__() + self.index = fan_index + 1 + self.position = position_index + self.is_psu_fan = psu_fan + self.attr_path = attr_path[0] + + if psu_fan is True: + self.fan_name = "PSU{}_FAN{}".format(self.index, self.position+1) + self.speed_file = attr_path[1] + else: + self.fan_name = "FAN{}".format(self.index) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_presence(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_prnt'.format(self.index)) + if data == '1': + return True + else: + return False + ret = self.__read_attr_file(self.attr_path + 'fan{}_present'.format(self.index)) + if ret == '1': + return True + elif ret == '0': + return False + else: + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.fan_name + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + return self.FAN_DIRECTION_NOT_APPLICABLE + + def get_status(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_good'.format(self.index)) + if data == '1': + return True + else: + return False + data = self.__read_attr_file(self.attr_path + 'fan{}_stat'.format(self.index)) + if data == '1': + return True + elif data == '0': + return False + else: + return False + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan is True and self.get_presence(): + speed = self.__read_attr_file( self.speed_file, 0) + if speed is not None: + return (int(speed)*100)//16000 + else: + return 0 + + if self.get_presence(): + if self.position ==0: + speed_file =self.attr_path + 'fan{}_rpm'.format(self.index) + else: + speed_file =self.attr_path + 'fan{}_rpm'.format(self.index) + data = self.__read_attr_file(speed_file) + if data is not None: + for sdata in data.split(' '): + if sdata.isdigit(): + return (int(sdata)*100)//18000 + return 0 + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + return self.get_speed() + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + """ + raise NotImplementedError + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platDev.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platDev.py new file mode 100755 index 0000000000..8829febe90 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platDev.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python + +try: + import os + import copy + import json + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("paltDev") +PLATFORM_INSTALL_INFO_FILE = "/etc/sonic/platform_install.json" +PLATFORM_NAME = "esc600_128q" + +# THERMAL_SENSOR_LIST +# index is used to indicate the default temp{}_* under sysfile_path +# support_mask: 1:support 0:not support +# bit 0 : temperature (always 1) +# bit 1 : high threshold +# bit 2 : low threshold +# bit 3 : high critical threshold +# bit 4 : low critical threshold +# bit 7 : cpu internal sensor +# ext_sysfile_list: each specified path of each supported function, +# which not follows the (default) genernal naming rule +# [0] ext_temp_file : temperature +# [1] ext_high_thr : high threshold +# [2] ext_low_thr : low threshold +# [3] ext_high_cri_thr : high critical threshold +# [4] ext_low_cri_thr : low critical threshold + +# ['Sensor 1 Top', 'temp_th0_t', 'temp_th0_t_max', 'temp_th0_t_min', 'temp_th0_t_crit', 'temp_th0_t_lcrit'], +# ['Sensor 1 Bottom', 'temp_th0_b', 'temp_th0_b_max', 'temp_th0_b_min', 'temp_th0_b_crit', 'temp_th0_b_lcrit'], +# ['Sensor 1 Remote', 'temp_th0_r', 'temp_th0_r_max', 'temp_th0_r_min', 'temp_th0_r_crit', 'temp_th0_r_lcrit'], +# ['Sensor 2 Top', 'temp_th1_t', 'temp_th1_t_max', 'temp_th1_t_min', 'temp_th1_t_crit', 'temp_th1_t_lcrit'], +# ['Sensor 2 Bottom', 'temp_th1_b', 'temp_th1_b_max', 'temp_th1_b_min', 'temp_th1_b_crit', 'temp_th1_b_lcrit'], +# ['Sensor 3 Top', 'temp_th2_t', 'temp_th2_t_max', 'temp_th2_t_min', 'temp_th2_t_crit', 'temp_th2_t_lcrit'], +# ['Sensor 3 Bottom', 'temp_th2_b', 'temp_th2_b_max', 'temp_th2_b_min', 'temp_th2_b_crit', 'temp_th2_b_lcrit'], +# ['Sensor 4 Top', 'temp_th3_t', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit'], +# ['Sensor 4 Bottom', 'temp_th3_b', 'temp_th3_b_max', 'temp_th3_b_min', 'temp_th3_b_crit', 'temp_th3_b_lcrit'], + +THERMAL_SENSOR_LIST = [ + { + 'name': "pch_haswell",'temp_index': [1],'sysfile_path': "/sys/class/hwmon/hwmon0/",'support_mask': 0x81, + 'ext_sysfile_list': None + }, + { + 'name': "CPU core temp", 'temp_index': [1, 2],'sysfile_path': "/sys/class/hwmon/hwmon1/",'support_mask': 0x8B, + 'ext_sysfile_list': None + }, + { + 'name': "NCT7511Y(U2)", 'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon6/",'support_mask': 0x01, + 'ext_sysfile_list': {1:['nct7511_temp', 'temp_th0_t_max', 'temp_th0_t_min', 'temp_th0_t_crit', 'temp_th0_t_lcrit']} + }, + { + 'name': "G781(U49)", 'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon3/", 'support_mask': 0x01, + 'ext_sysfile_list': {1:['left_bot_sb_temp', 'temp_th1_t_max', 'temp_th1_t_min', 'temp_th1_t_crit', 'temp_th1_t_lcrit']} + }, + { + 'name': "G781(U1)",'temp_index': [1],'sysfile_path': "/sys/class/hwmon/hwmon4/",'support_mask': 0x01, + 'ext_sysfile_list': {1:['ctr_top_sb_temp', 'temp_th2_t_max', 'temp_th2_t_min', 'temp_th2_t_crit', 'temp_th2_t_lcrit']} + }, + { + 'name': "G781(U21)",'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon5/",'support_mask': 0x01, + 'ext_sysfile_list': {1:['ctr_sb_temp', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit']} + }, + { + 'name': "G781(U1x)", 'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon5/", 'support_mask': 0x01, + 'ext_sysfile_list': {1:['left_top_cb_temp', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit']} + }, + { + 'name': "G781(U11)", 'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon5/", 'support_mask': 0x01, + 'ext_sysfile_list': {1:['ctr_cb_temp', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit']} + }, + { + 'name': "G781(U16)", 'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon5/", 'support_mask': 0x01, + 'ext_sysfile_list': {1:['right_bot_cb_temp', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit']} + }, + { + 'name': "G781(U17)", 'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon5/", 'support_mask': 0x01, + 'ext_sysfile_list': {1:['left_bot_cb_temp', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit']} + }, + { + 'name': "G781(U6)", 'temp_index': [1], 'sysfile_path': "/sys/class/hwmon/hwmon5/", 'support_mask': 0x01, + 'ext_sysfile_list': {1:['io_board_temp', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit']} + } +] + +# PSU LIST +# ext_sysfile_list +# [0] : sysfile path for present +# [1] : sysfile path for status +# +PSU_LIST = ['PSU1', 'PSU2', 'PSU3', 'PSU4'] + +PSU_INFO = { + 'PSU1': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC600_POWER/" + }, + 'PSU2': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC600_POWER/" + }, + 'PSU3': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC600_POWER/" + }, + 'PSU4': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC600_POWER/" + } +} + +# SFP LIST +# +# +FAN_LIST = ['FAN1', 'FAN2', 'FAN3', 'FAN4'] + +FAN_INFO = { + 'FAN1': { + 'isdraw': True, + 'fan_num': 1, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC600_FAN/' + }, + 'FAN2': { + 'isdraw': True, + 'fan_num': 1, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC600_FAN/' + }, + 'FAN3': { + 'isdraw': True, + 'fan_num': 1, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC600_FAN/' + }, + 'FAN4': { + 'isdraw': True, + 'fan_num': 1, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC600_FAN/' + }, +} + + +# SFP LIST +# +# +SFP_EXT_SYSFILE_LIST = [] + +PLATFORM_CARD_LIST = ['PHY_CPLD_1', 'PHY_CPLD_2', 'PHY_CPLD_3', 'PHY_CPLD_4', 'PHY_CPLD_5', 'PHY_CPLD_6', 'PHY_CPLD_7', + 'PHY_CPLD_8'] +SFP_GROUP_LIST = ['SFP-G11', 'SFP-G12', 'SFP-G21', 'SFP-G22', 'SFP-G31', 'SFP-G32', 'SFP-G41', 'SFP-G42', + 'SFP-G51', 'SFP-G52', 'SFP-G61', 'SFP-G62', 'SFP-G71', 'SFP-G72', 'SFP-G81', 'SFP-G82'] +PORT_NUM = 0 + +# SFP-eeprom paths /sys/bus/i2c/devices/XX-0050 +SFP_GROUP_INFO = { + "SFP-G11": {"type": "QSFP28", "paths": [], "number": 8}, "SFP-G12": {"type": "QSFP28","paths": [], "number": 8}, + "SFP-G21": {"type": "QSFP28", "paths": [], "number": 8}, "SFP-G22": {"type": "QSFP28","paths": [], "number": 8}, + "SFP-G31": {"type": "QSFP28", "paths": [], "number": 8}, "SFP-G32": {"type": "QSFP28","paths": [], "number": 8}, + "SFP-G41": {"type": "QSFP28", "paths": [], "number": 8},"SFP-G42": {"type": "QSFP28","paths": [], "number": 8}, + "SFP-G51": {"type": "QSFP28", "paths": [], "number": 8}, "SFP-G52": {"type": "QSFP28", "paths": [], "number": 8}, + "SFP-G61": {"type": "QSFP28", "paths": [], "number": 8}, "SFP-G62": {"type": "QSFP28", "paths": [], "number": 8}, + "SFP-G71": {"type": "QSFP28", "paths": [], "number": 8}, "SFP-G72": {"type": "QSFP28", "paths": [], "number": 8}, + "SFP-G81": {"type": "QSFP28", "paths": [], "number": 8}, "SFP-G82": {"type": "QSFP28", "paths": [], "number": 8}, +} + +# +#Component +# ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " +# "modules (1-16)")], +# ["Slave-CPLD", "Used for managing QSFP modules (17-32)"] + +CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["System-CPLD", "Used for managing CPU board devices and power"] +] + +class PlatDev(): + def __init__(self): + self.plat_name = PLATFORM_NAME + self.psu_info = copy.deepcopy(PSU_INFO) + self.thermal_info = [] + self.fan_info = copy.deepcopy(FAN_INFO) + self.sfp_info = copy.deepcopy(SFP_GROUP_INFO) + self.device_install_info = dict() + self.sfp_install_info = dict() + + # get install info + self.get_dev_install_info() + # update path info with install info + # Item 1/2 not changed, append directly + self.thermal_info.append(THERMAL_SENSOR_LIST[0]) + self.thermal_info.append(THERMAL_SENSOR_LIST[1]) + + for i in range(2, len(THERMAL_SENSOR_LIST)): + install_info = self.device_install_info.get(THERMAL_SENSOR_LIST[i]['name']) + if install_info : + if self.bmc_is_exist(): + THERMAL_SENSOR_LIST[i]['sysfile_path'] = '/sys/class/hwmon/hwmon2/device/ESC600_THERMAL/' + else: + if install_info.get('hwmon_path') is None: + continue + THERMAL_SENSOR_LIST[i]['sysfile_path'] = install_info.get('hwmon_path') + self.thermal_info.append(THERMAL_SENSOR_LIST[i]) + + for psu_name in PSU_LIST: + install_info = self.device_install_info.get(psu_name) + if install_info: + if self.bmc_is_exist(): + self.psu_info[psu_name]['attr_path']= '/sys/class/hwmon/hwmon2/device/ESC600_POWER/' + else: + self.psu_info[psu_name]['attr_path'] = install_info.get('hwmon_path')+ '/device/' + + for sfp_group_name in SFP_GROUP_LIST: + install_info = self.sfp_install_info.get(sfp_group_name) + if install_info: + self.sfp_info[sfp_group_name]['paths'] = install_info.get('paths') + self.sfp_info[sfp_group_name]['number'] = install_info.get('number') + # 400G line card + if self.sfp_info[sfp_group_name]['number'] == 4: + self.sfp_info[sfp_group_name]['type'] = 'QSFP-DD' + + def get_dev_install_info(self): + global SFP_EXT_SYSFILE_LIST + global PORT_NUM + PORT_NUM =0 + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + self.sfp_install_info = install_info[2] + self.device_install_info = install_info[1] + for card_name in PLATFORM_CARD_LIST: + card = install_info[1][card_name] + if card['portnum'] == 0: + continue + for i in range(1,card['portnum']+1): + PORT_NUM = PORT_NUM+1 + present_file = card['hwmon_path']+'/device/'+'QSFP_present_{}'.format(i) + lp_file = card['hwmon_path']+'/device/'+'QSFP_low_power_{}'.format(i) + reset_file = card['hwmon_path']+'/device/'+'QSFP_reset_{}'.format(i) + SFP_EXT_SYSFILE_LIST.append([present_file,lp_file,reset_file]) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def bmc_is_exist(self): + bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESC600_SYS/bmc_present' + if os.path.exists(bmc_filePath): + value = self.__read_attr_file(bmc_filePath) + if int(value) == 1: + return True + else: + return False + else: + return False + ######Componet method ##### + def get_component_count(self): + return len(CHASSIS_COMPONENTS) + + def get_component_name(self,idx): + return CHASSIS_COMPONENTS[idx][0] + + def get_component_descript(self,idx): + return CHASSIS_COMPONENTS[idx][1] + + ###### PSU method ###### + def get_psu_list(self): + return PSU_LIST + + def get_psu_info_all(self): + return self.psu_info + + def get_psu_info_by_name(self, name): + return self.psu_info.get(name) + + def get_psu_attr_path_by_name(self, name): + return self.psu_info[name].get('attr_path') + + def get_psu_status_path_by_name(self, name): + return self.psu_info[name].get('status_path') + + ###### Thermal method ###### + def get_thermal_dev_info_all(self): + return self.thermal_info + + def get_thermal_dev_name_by_idx(self, index): + return self.thermal_info[index].get('name') + + def get_thermal_dev_tempidx_by_idx(self, index): + return self.thermal_info[index].get('temp_index') + + def get_thermal_dev_sysfile_path_by_idx(self, index): + return self.thermal_info[index].get('sysfile_path') + + def get_thermal_dev_support_mask_by_idx(self, index): + return self.thermal_info[index].get('support_mask') + + def get_thermal_dev_ext_sysfile_list_by_idx(self, index): + return self.thermal_info[index].get('ext_sysfile_list') + + ###### Fan method ###### + def get_fan_support(self): + return True + + def get_fan_list(self): + return FAN_LIST + + def get_fan_info_all(self): + return self.fan_info + + def get_fan_info_by_name(self, name): + return self.fan_info.get(name) + + def get_fan_sysfile_path_by_name(self, name): + return self.fan_info[name].get('attr_path') + + def get_fan_is_draw_by_name(self, name): + return self.fan_info[name].get('isdraw') + + def get_fan_num_by_name(self, name): + return self.fan_info[name].get('fan_num') + + ###### SFP method ###### + def get_sfp_num(self): + return PORT_NUM + + def get_sfp_group_list(self): + return SFP_GROUP_LIST + + def get_sfp_group_info(self): + return self.sfp_info + + def get_sfp_group_info_by_name(self, name): + return self.sfp_info.get(name) + + def get_sfp_group_type_by_name(self, name): + return self.sfp_info[name].get('type') + + def get_sfp_group_path_by_name(self, name): + return self.sfp_info[name].get('paths') + + def get_sfp_group_number_by_name(self, name): + return self.sfp_info[name].get('number') + + def get_sfp_ext_sysfile_list(self): + return SFP_EXT_SYSFILE_LIST + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platform.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platform.py new file mode 100755 index 0000000000..2456a6f2e7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/platform.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/psu.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/psu.py new file mode 100755 index 0000000000..20e365e73d --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/psu.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common.logger import Logger + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +# To do: should be defined in platDev +PSU_MAX_VOUT = 12.0 # voltage +PSU_MIN_VOUT = 3.3 # voltage +PSU_MAX_TEMP = 50.0 # C + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, index, info_list,is_bmc): + PsuBase.__init__(self) + self.index = index + self.is_bmc = is_bmc + self.attr_path = info_list[0] + self.status_path = info_list[1] + if is_bmc: + speed_file = self.attr_path + 'psu{}_fan_speed'.format(index+1) + else: + speed_file = self.attr_path + 'psu_fan_speed_1' + + fan = Fan( index, 0, [self.status_path, speed_file ],True) + self._fan_list.append(fan) + self.psu_name = "PSU{}".format(self.index+1) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.psu_name + + def get_presence(self): + """ + Retrieves the presence status of power supply unit (PSU) defined + Returns: + bool: True if PSU is present, False if not + """ + data = self.__read_attr_file(self.status_path + 'psu{}_prnt'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + data = self.__read_attr_file(self.status_path + 'psu{}_good'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_vout'.format(self.index+1) + else: + path = self.attr_path + "/psu_vout" + vout = self.__read_attr_file( path, 0) + if vout is not None: + return float(vout) / 1000 + + return False + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_iout'.format(self.index+1) + else: + path = self.attr_path + "/psu_iout" + iout = self.__read_attr_file( path, 0) + if iout is not None: + return float(iout) / 1000 + return False + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_pout'.format(self.index+1) + else: + path = self.attr_path + "/psu_pout" + pout = self.__read_attr_file( path, 0) + if pout is not None: + return float(pout) / 1000000 + return False + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + raise NotImplementedError + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.is_bmc: + path = self.attr_path+'psu{}_temp'.format(self.index+1) + else: + path = self.attr_path + "/psu_temp_1" + temperature = self.__read_attr_file( path, 0) + if temperature is not None: + return float(temperature) / 1000 + + return False + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return PSU_MAX_TEMP + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MAX_VOUT + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MIN_VOUT diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/sfp.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/sfp.py new file mode 100755 index 0000000000..a2121080e2 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/sfp.py @@ -0,0 +1,1636 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + import time + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common.logger import Logger + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_InterfaceId + from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("sfp") + +############################################################################# +# +# SFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# ------------------------------------------------ 0 +# | Serial ID Defined by SFP MSA (96 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 95 +# | Vendor Specific (32 bytes) | +# |----------------------------------------------| 127 +# | Reserved, SFF-8079 (128 byte) | +# ------------------------------------------------ 255 +# +# 2 wire address 1010001x (A2h) (i2c 0x51) +# ------------------------------------------------ 0 +# | Alarm and Warning Threshold (56 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 55 +# | Cal Constants (40 bytes) | +# |----------------------------------------------| 95 +# | Real Time Diagnostic Interface(24 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 119 +# | Vendor Specific (7 bytes) | +# |----------------------------------------------| 126 +# | Page Select Byte (Optional) | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# Page 00h/01h +# |----------------------------------------------| 128 +# | User Writeable EEPROM (120 bytes) | +# |----------------------------------------------| 247 +# | Vendor Specific (8 bytes) | +# ------------------------------------------------ 255 +# Page 02h +# |----------------------------------------------| 128 +# | Control Function (128 bytes) | +# ------------------------------------------------ 255 +# Page 03h-7Fh +# |----------------------------------------------| 128 +# | Reserved (128 bytes) | +# ------------------------------------------------ 255 +# Page 80h-FFh +# |----------------------------------------------| 128 +# | Vendor Specific (128 bytes) | +# ------------------------------------------------ 255 +# +# ========================================================== +# QSFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# +# ------------------------------------------------ 0 +# | ID and status (3 bytes) | +# |----------------------------------------------| 2 +# | Interrupt Flags (19 bytes) | +# |----------------------------------------------| 21 +# | Module Monitors (12 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 33 +# | Channel Monitors (12 bytes) | +# |----------------------------------------------| 81 +# | Reserved (4 bytes) | +# |----------------------------------------------| 85 +# | Control (12 bytes) | <- get_power_override +# |----------------------------------------------| 97 +# | ~~~ | +# |----------------------------------------------| 126 +# | Page Select Byte | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# +# Page 00h +# |----------------------------------------------| 128 +# | Base ID Filed (64 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 191 +# | Extended ID (32 bytes) | +# |----------------------------------------------| 223 +# | Vendor Specific ID (8 bytes) | +# ------------------------------------------------ 255 +# Page 01h (optional) +# |----------------------------------------------| 128 +# | ~~~~ (128 bytes) | +# ------------------------------------------------ 255 +# Page 02h (optional) +# |----------------------------------------------| 128 +# | User EEPROM Data (128 bytes) | +# ------------------------------------------------ 255 + +# Page 03h (optional on QSFP28) +# |----------------------------------------------| 128 +# | Module Threshold (48 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 175 +# | Channel Threshold (48 bytes) | +# |----------------------------------------------| 223 +# | Reserved (2 bytes) | +# |----------------------------------------------| 225 +# | Vendor Specific Channel Controls (16 bytes) | +# |----------------------------------------------| 241 +# | Channel Monitor Masks (12 bytes) | +# |----------------------------------------------| 253 +# | Reserved (2 bytes) | +# ------------------------------------------------ 255 +# +# +# ========================================================== +# QSFP-DD : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# +# ------------------------------------------------ 0 +# | ID and status (4 bytes) | +# |----------------------------------------------| 3 +# | Lane Flag Summary (4 bytes) | +# |----------------------------------------------| 7 +# | Module-Level Flags (6 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 13 +# | Module-Level Monitors (5 bytes) | +# |----------------------------------------------| 18 +# | Module Global Controls (5 bytes) | +# |----------------------------------------------| 23 +# | Module-Level Flag Masks (6 bytes) | <- get_power_override +# |----------------------------------------------| 29 +# | CDB Status Area (2 bytes) | +# |----------------------------------------------| 31 +# | Module Firmware Version (2 bytes) | +# |----------------------------------------------| 33 +# | CDB Status Area (2 bytes) | +# |----------------------------------------------| 35 +# | ~~~~~ | +# |----------------------------------------------| 125 +# | Bank Select Byte | +# |----------------------------------------------| 126 +# | Page Select Byte | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# +# Page 00h +# |----------------------------------------------| 128 +# | Base ID Filed (64 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 191 +# | Extended ID (32 bytes) | +# |----------------------------------------------| 223 +# | Vendor Specific ID (8 bytes) | +# ------------------------------------------------ 255 +# Page 01h (optional) +# |----------------------------------------------| 128 +# | ~~~~ (128 bytes) | +# ------------------------------------------------ 255 +# Page 02h (optional) +# |----------------------------------------------| 128 +# | User EEPROM Data (128 bytes) | +# ------------------------------------------------ 255 + +# Page 03h (optional on QSFP28) +# |----------------------------------------------| 128 +# | Module Threshold (48 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 175 +# | Channel Threshold (48 bytes) | +# |----------------------------------------------| 223 +# | Reserved (2 bytes) | +# |----------------------------------------------| 225 +# | Vendor Specific Channel Controls (16 bytes) | +# |----------------------------------------------| 241 +# | Channel Monitor Masks (12 bytes) | +# |----------------------------------------------| 253 +# | Reserved (2 bytes) | +# ------------------------------------------------ 255 +# +# +############################################################################# + +# function eunm +SFP_GET_PRESENCE=0 +SFP_RESET =1 +SFP_GET_LOW_POWER_MODE=2 +SFP_SET_LOW_POWER_MODE=3 + +# XCVR type definition +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" +QSFP_DD_TYPE = "QSFP_DD" + +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] +QSFP_DD_TYPE_CODE_LIST = [ + '18' # QSFP_DD +] + +# index for A0H, A2H sysfs file path +INDEX_A0H = 0 +INDEX_A2H = 1 + +# offset/width definition +OFFSET = 0 +WIDTH = 1 + +QSFP_UPPER_MEMORY_PAGE00_OFFSET = 128 +QSFP_UPPER_MEMORY_PAGE02_OFFSET = 384 +QSFP_UPPER_MEMORY_PAGE03_OFFSET = 512 + +QSFP_DD_PAGE11_OFFSET = 512 + +SFP_A0H_OFFSET = 0 +SFP_A2H_OFFSET = 0 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_DOM_CAPABILITY_OFFSET_QSFP_DD = 2 +XCVR_DOM_CAPABILITY_WIDTH_QSFP_DD = 1 + +ID_FIELD_WIDTH = 92 + +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 2 +QSFP_INTERFACE_BULK_WIDTH = 20 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 5], + 'DEVICE_TECH': [19, 1], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 2], + 'WAVELENGTH': [58, 2], + 'WAVELENGTH_TOLERANCE': [60, 2], + 'MAX_CASE_TEMP': [62, 1], + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 4], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [22, 2], + 'VOLTAGE': [26, 2], + 'CHANNEL_MON': [34, 24], + 'CONTROL': [86, 12], + # PAGE03 + 'MODULE_THRESHOLD': [0, 24], + 'CHANNEL_THRESHOLD': [50, 24] +} +SFP_INTERFACE_BULK_WIDTH = 21 +SFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 6], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 4], + 'WAVELENGTH': [60, 2], + # UNALLOCATED WIDDTH: 1 + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 2], + 'BITRATE_MAX': [66, 1], + # BITRATE_MAX ?? + 'BITRATE_MAX_1': [67, 1], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [96, 2], + 'VOLTAGE': [98, 2], + 'CHANNEL_MON': [100, 6], + 'MODULE_THRESHOLD': [0, 40] +} +QSFP_DD_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + # LOWER PAGE00 + 'MEDIA_TYPE': [85, 1], + 'FIRST_APPL_LIST': [86, 32], + + # UPPER PAGE00 + 'TYPE': [0, 1], + 'EXTID': [72, 2], + 'CONNECTOR': [75 , 1], + 'CABLE_LEN': [74, 5], + 'VENDOR_NAME': [1, 16], + 'VENDOR_OUI': [17, 3], + 'VENDOR_PN': [20, 16], + 'VENDOR_REV': [36, 2], + 'VENDOR_SN': [38, 16], + 'VENDOR_DATE': [54, 8], + # DOM + 'TEMPERATURE': [14, 2], + 'VOLTAGE': [16, 2], + 'CHANNEL_MON': [26, 48], + # PAGE01 + 'SECOND_APPL_LIST': [95, 28], + # PAGE02 + 'MODULE_THRESHOLD': [0, 72], + # PAGE11 + 'TX_BIAS': [42, 16], + 'RX_POWER': [58, 16], + 'TX_POWER': [26, 16] +} + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes','FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia','FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + def __init__(self, index, eeprom_path_list, sfp_type, ext_sysfile_list=None): + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + # ext_sysfile_list[0]: QSFP path + # ext_sysfile_list[1]: SFP path + self.index = index + self.eeprom_path_list = eeprom_path_list + + self.present_file = ext_sysfile_list[self.index-1][0] + self.lp_file = ext_sysfile_list[self.index-1][1] + self.reset_file = ext_sysfile_list[self.index-1][2] + # get actual type or use default type from input parameter + self._get_sfp_type(sfp_type) + self._dom_capability_detect() + + def _get_sfp_type(self, sfp_type): + ty = self._read_eeprom_bytes(SFP_ID_FIELDS['TYPE'][OFFSET], SFP_ID_FIELDS['TYPE'][WIDTH], INDEX_A0H) + if ty is not None: + if ty[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + elif ty[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + elif ty[0] in QSFP_DD_TYPE_CODE_LIST: + self.sfp_type = QSFP_DD_TYPE + else: + self.sfp_type = sfp_type + logger.log_warning("Unreganized sfp type of module {} . {} unsupported, treated as specified type {}".format(self.index, ty[0], sfp_type)) + else: + self.sfp_type = sfp_type + + + def _read_eeprom_bytes(self, offset, num_bytes, path_idx = INDEX_A0H): + eeprom_raw = [] + + eeprom = None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom = open(self.eeprom_path_list[path_idx], mode="rb", buffering=0) + eeprom.seek(offset) + raw_data = eeprom.read(num_bytes) + for nb in range(0, len(raw_data)): + eeprom_raw[nb] = hex(ord(raw_data[nb]))[2:].zfill(2) + except Exception as ex: + logger.log_error("Fail to read eeprom {}".format(self.eeprom_path_list[path_idx])) + logger.log_error(" {}".format(ex)) + if eeprom is not None: + eeprom.close() + return None + + return eeprom_raw + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + time.sleep(5) + + return None + + def __write_attr_file(self, filepath, data): + try: + with open(filepath,'w') as fd: + return fd.write(data) + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + return 0 + + def get_presence(self): + if self.present_file is not None: + data = self.__read_attr_file(self.present_file) + if data is not None: + if int(data) == 1: + return True + return False + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_rx_tx_power_bias_supported = False + self.calibration = 0 + return + + if self.sfp_type == QSFP_TYPE: + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self._read_eeprom_bytes((offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self._read_eeprom_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH,INDEX_A0H) + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + qspf_dom_capability = int(qsfp_dom_capability_raw[0], 16) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qspf_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qspf_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qspf_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + qsfp_option_value_raw = self._read_eeprom_bytes(QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH,INDEX_A0H) + if qsfp_option_value_raw is not None: + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + self.optional_capability = sfpd_obj.parse_option_params(qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = self.optional_capability['data']['TxDisable']['value'] == 'On' + dom_status_indicator = sfpd_obj.parse_dom_status_indicator(qsfp_version_compliance_raw, 1) + self.qsfp_page3_available = dom_status_indicator['data']['FlatMem']['value'] == 'Off' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.qsfp_page3_available = False + self.calibration = 0 + + elif self.sfp_type == SFP_TYPE: + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self._read_eeprom_bytes(XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = (int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + + elif self.sfp_type == QSFP_DD_TYPE: + sfpi_obj = qsfp_dd_InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + + qsfp_dd_dom_capability_raw = self._read_eeprom_bytes(XCVR_DOM_CAPABILITY_OFFSET_QSFP_DD, XCVR_DOM_CAPABILITY_WIDTH_QSFP_DD) + if qsfp_dd_dom_capability_raw is not None: + self.dom_temp_supported = True + self.dom_volt_supported = True + dom_capability = sfpi_obj.parse_qsfp_dom_capability(qsfp_dd_dom_capability_raw, 0) + #dom_capability = sfpi_obj.parse_dom_capability(qsfp_dd_dom_capability_raw, 0) + if dom_capability['data']['Flat_MEM']['value'] == 'Off': + self.dom_supported = True + self.second_application_list = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + self.dom_tx_bias_power_supported = True + self.dom_thresholds_supported = True + self.dom_rx_tx_power_bias_supported = True + else: + self.dom_supported = False + self.second_application_list = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_thresholds_supported = False + self.dom_rx_tx_power_bias_supported = False + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_thresholds_supported = False + self.dom_rx_tx_power_bias_supported = False + + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + transceiver_info_dict_keys = [ + 'type', 'hardware_rev', + 'serial', 'manufacturer', + 'model', 'connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui','application_advertisement'] + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE00_OFFSET # upper memory map: Page 00h + Id_field = QSFP_ID_FIELDS + info_bulk_width = QSFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8436InterfaceId() + + elif self.sfp_type == QSFP_DD_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE00_OFFSET # upper memory map: Page 00h + Id_field = QSFP_DD_ID_FIELDS + sfpi_obj = qsfp_dd_InterfaceId() + + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A0H_OFFSET # lower memory map: A0h (SFP i2c 0x50) + Id_field = SFP_ID_FIELDS + info_bulk_width = SFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8472InterfaceId() + else: + logger.log_error("Unsupported sfp type") + return None + + if sfpi_obj is None: + logger.log_error("sfpi_obj create fail") + return None + + if self.sfp_type != QSFP_DD_TYPE: + # read Base ID field + sfp_interface_bulk_raw = self._read_eeprom_bytes(field_offset, ID_FIELD_WIDTH, INDEX_A0H) + if sfp_interface_bulk_raw is None: + logger.log_error(" Fail to read BaseID field of module {}".format(self.index+1)) + return None + + start = 0 + end = start + info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_NAME'][OFFSET] + end = start + Id_field['VENDOR_NAME'][WIDTH] + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_PN'][OFFSET] + end = start + Id_field['VENDOR_PN'][WIDTH] + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_REV'][OFFSET] + end = start + Id_field['VENDOR_REV'][WIDTH] + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_SN'][OFFSET] + end = start + Id_field['VENDOR_SN'][WIDTH] + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_OUI'][OFFSET] + end = start + Id_field['VENDOR_OUI'][WIDTH] + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_DATE'][OFFSET] + end = start + Id_field['VENDOR_DATE'][WIDTH] + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + + compliance_code_dict = {} + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + else: + # QSFP-DD + sfp_type_raw = self._read_eeprom_bytes(Id_field['TYPE'][OFFSET], Id_field['TYPE'][WIDTH]) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + transceiver_info_dict['type'] = str(sfp_type_data['data']['type']['value']) + else: + return transceiver_info_dict + + sfp_vendor_name_raw = self._read_eeprom_bytes((field_offset + Id_field['VENDOR_NAME'][OFFSET]), Id_field['VENDOR_NAME'][WIDTH]) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + transceiver_info_dict['manufacturer'] = str(sfp_vendor_name_data['data']['Vendor Name']['value']) + else: + return transceiver_info_dict + + sfp_vendor_pn_raw = self._read_eeprom_bytes((field_offset + Id_field['VENDOR_PN'][OFFSET]), Id_field['VENDOR_PN'][WIDTH]) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + transceiver_info_dict['model'] = str(sfp_vendor_pn_data['data']['Vendor PN']['value']) + else: + return transceiver_info_dict + + sfp_vendor_rev_raw = self._read_eeprom_bytes((field_offset + Id_field['VENDOR_REV'][OFFSET]), Id_field['VENDOR_REV'][WIDTH]) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + transceiver_info_dict['hardware_rev'] = str(sfp_vendor_rev_data['data']['Vendor Rev']['value']) + else: + return transceiver_info_dict + + sfp_vendor_sn_raw = self._read_eeprom_bytes((field_offset + Id_field['VENDOR_SN'][OFFSET]), Id_field['VENDOR_SN'][WIDTH]) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + transceiver_info_dict['serial'] = str(sfp_vendor_sn_data['data']['Vendor SN']['value']) + else: + return transceiver_info_dict + + sfp_vendor_oui_raw = self._read_eeprom_bytes((field_offset + Id_field['VENDOR_OUI'][OFFSET]), Id_field['VENDOR_OUI'][WIDTH]) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + transceiver_info_dict['vendor_oui'] = str(sfp_vendor_oui_data['data']['Vendor OUI']['value']) + else: + return transceiver_info_dict + + sfp_vendor_date_raw = self._read_eeprom_bytes((field_offset + Id_field['VENDOR_DATE'][OFFSET]), Id_field['VENDOR_DATE'][WIDTH]) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + transceiver_info_dict['vendor_date'] = str(sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']) + else: + return transceiver_info_dict + + sfp_connector_raw = self._read_eeprom_bytes((field_offset + Id_field['CONNECTOR'][OFFSET]), Id_field['CONNECTOR'][WIDTH]) + if sfp_connector_raw is not None: + sfp_connector_data = sfpi_obj.parse_connector(sfp_connector_raw, 0) + transceiver_info_dict['connector'] = str(sfp_connector_data['data']['Connector']['value']) + else: + return transceiver_info_dict + + sfp_ext_identifier_raw = self._read_eeprom_bytes((field_offset + Id_field['EXTID'][OFFSET]), Id_field['EXTID'][WIDTH]) + if sfp_ext_identifier_raw is not None: + sfp_ext_identifier_data = sfpi_obj.parse_ext_iden(sfp_ext_identifier_raw, 0) + transceiver_info_dict['ext_identifier'] = str(sfp_ext_identifier_data['data']['Extended Identifier']['value']) + else: + return transceiver_info_dict + + sfp_cable_len_raw = self._read_eeprom_bytes((field_offset + Id_field['CABLE_LEN'][OFFSET]), Id_field['CABLE_LEN'][WIDTH]) + if sfp_cable_len_raw is not None: + sfp_cable_len_data = sfpi_obj.parse_cable_len(sfp_cable_len_raw, 0) + transceiver_info_dict['cable_length'] = str(sfp_cable_len_data['data']['Length Cable Assembly(m)']['value']) + else: + return transceiver_info_dict + + sfp_media_type_raw = self._read_eeprom_bytes(Id_field['MEDIA_TYPE'][OFFSET], Id_field['MEDIA_TYPE'][WIDTH]) + if sfp_media_type_raw is not None: + sfp_media_type_dict = sfpi_obj.parse_media_type(sfp_media_type_raw, 0) + if sfp_media_type_dict is None: + return transceiver_info_dict + + host_media_list = "" + sfp_application_type_first_list = self._read_eeprom_bytes(Id_field['FIRST_APPL_LIST'][OFFSET], Id_field['FIRST_APPL_LIST'][WIDTH]) + if self.second_application_list: + possible_application_count = 15 + sfp_application_type_second_list = self._read_eeprom_bytes((256 + Id_field['SECOND_APPL_LIST'][OFFSET]), Id_field['SECOND_APPL_LIST'][WIDTH]) + if sfp_application_type_first_list is not None and sfp_application_type_second_list is not None: + sfp_application_type_list = sfp_application_type_first_list + sfp_application_type_second_list + else: + return transceiver_info_dict + else: + possible_application_count = 8 + if sfp_application_type_first_list is not None: + sfp_application_type_list = sfp_application_type_first_list + else: + return transceiver_info_dict + + for i in range(0, possible_application_count): + if sfp_application_type_list[i * 4] == 'ff': + break + host_electrical, media_interface = sfpi_obj.parse_application(sfp_media_type_dict, sfp_application_type_list[i * 4], sfp_application_type_list[i * 4 + 1]) + host_media_list = host_media_list + host_electrical + ' - ' + media_interface + '\n\t\t\t\t ' + else: + return transceiver_info_dict + + transceiver_info_dict['encoding'] = "Not supported for CMIS cables" + transceiver_info_dict['ext_rateselect_compliance'] = "Not supported for CMIS cables" + transceiver_info_dict['specification_compliance'] = "Not supported for CMIS cables" + transceiver_info_dict['cable_type'] = "Length Cable Assembly(m)" + transceiver_info_dict['nominal_bit_rate'] = "Not supported for CMIS cables" + transceiver_info_dict['application_advertisement'] = host_media_list + + return transceiver_info_dict + + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = [ + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'rx5power', 'rx6power', + 'rx7power', 'rx8power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx5bias', 'tx6bias', + 'tx7bias', 'tx8bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power', + 'tx5power', 'tx6power', + 'tx7power', 'tx8power'] + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + + self._dom_capability_detect() + + path_idx = INDEX_A0H + + if not self.dom_supported: + return transceiver_dom_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + + elif self.sfp_type == QSFP_DD_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_DD_ID_FIELDS + sfpd_obj = qsfp_dd_Dom() + + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return transceiver_dom_info_dict + + if sfpd_obj is None: + return transceiver_dom_info_dict + + if self.sfp_type == SFP_TYPE: + sfpd_obj._calibration_type = self.calibration + + if self.dom_temp_supported: + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + transceiver_dom_info_dict['temperature'] = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + + if self.dom_volt_supported: + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + transceiver_dom_info_dict['voltage'] = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + + + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value']) + transceiver_dom_info_dict['tx2power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value']) + transceiver_dom_info_dict['tx3power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value']) + transceiver_dom_info_dict['tx4power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value']) + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value']) + transceiver_dom_info_dict['rx2power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value']) + transceiver_dom_info_dict['rx3power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value']) + transceiver_dom_info_dict['rx4power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value']) + + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + elif self.sfp_type == QSFP_DD_TYPE: + if self.dom_rx_tx_power_bias_supported: + dom_channel_monitor_raw = self._read_eeprom_bytes(QSFP_DD_PAGE11_OFFSET + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is None: + return transceiver_dom_info_dict + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + transceiver_dom_info_dict['tx2power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + transceiver_dom_info_dict['tx3power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + transceiver_dom_info_dict['tx4power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + transceiver_dom_info_dict['tx5power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX5Power']['value'])) + transceiver_dom_info_dict['tx6power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX6Power']['value'])) + transceiver_dom_info_dict['tx7power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX7Power']['value'])) + transceiver_dom_info_dict['tx8power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX8Power']['value'])) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + transceiver_dom_info_dict['rx2power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + transceiver_dom_info_dict['rx3power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + transceiver_dom_info_dict['rx4power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + transceiver_dom_info_dict['rx5power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX5Power']['value'])) + transceiver_dom_info_dict['rx6power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX6Power']['value'])) + transceiver_dom_info_dict['rx7power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX7Power']['value'])) + transceiver_dom_info_dict['rx8power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX8Power']['value'])) + + if self.dom_tx_bias_power_supported: + transceiver_dom_info_dict['tx1bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + transceiver_dom_info_dict['tx2bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + transceiver_dom_info_dict['tx3bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + transceiver_dom_info_dict['tx4bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + transceiver_dom_info_dict['tx5bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX5Bias']['value'])) + transceiver_dom_info_dict['tx6bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX6Bias']['value'])) + transceiver_dom_info_dict['tx7bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX7Bias']['value'])) + transceiver_dom_info_dict['tx8bias'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX8Bias']['value'])) + + elif self.sfp_type == SFP_TYPE: + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['rx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value']) + transceiver_dom_info_dict['tx1bias'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value']) + transceiver_dom_info_dict['tx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value']) + + + return transceiver_dom_info_dict + + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + dom_info_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + + transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + if not self.qsfp_page3_available: + return transceiver_dom_threshold_info_dict + field_offset = QSFP_UPPER_MEMORY_PAGE03_OFFSET # uppper memory map: Page 03h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + + elif self.sfp_type == QSFP_DD_TYPE: + if not self.dom_thresholds_supported: + return transceiver_dom_threshold_info_dict + field_offset = QSFP_UPPER_MEMORY_PAGE02_OFFSET # uppper memory map: Page 03h + Id_field = QSFP_DD_ID_FIELDS + sfpd_obj = qsfp_dd_Dom() + + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return transceiver_dom_threshold_info_dict + + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['MODULE_THRESHOLD'][OFFSET], Id_field['MODULE_THRESHOLD'][WIDTH], path_idx) + + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_THRESHOLD'][OFFSET], Id_field['CHANNEL_THRESHOLD'][WIDTH], path_idx) + + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + + elif self.sfp_type == QSFP_DD_TYPE: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['TxBiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TxPowerLowWarning']['value'] + + else: # SFP_TYPE + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + raise NotImplementedError + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + raise NotImplementedError + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + raise NotImplementedError + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + raise NotImplementedError + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + raise NotImplementedError + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.lp_file is not None: + data = self.__read_attr_file(self.lp_file, 0) + if data is not None: + if int(data) == 1: + return True + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.sfp_type == QSFP_TYPE: + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_bytes(Id_field['CONTROL'][OFFSET], Id_field['CONTROL'][WIDTH], INDEX_A0H) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + + return False + else: + raise NotImplementedError + + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + path_idx = INDEX_A0H + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + + elif self.sfp_type == QSFP_DD_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_DD_ID_FIELDS + sfpd_obj = qsfp_dd_Dom() + + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + + else: + return None + + if sfpd_obj is None: + return None + + if self.sfp_type == SFP_TYPE: + sfpd_obj._calibration_type = 1 + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + + return None + + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + if not self.dom_supported: + return None + path_idx = INDEX_A0H + if self.sfp_type == QSFP_TYPE: + if not self.dom_volt_supported: + return None + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + + elif self.sfp_type == QSFP_DD_TYPE: + if not self.dom_volt_supported: + return None + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_DD_ID_FIELDS + sfpd_obj = qsfp_dd_Dom() + + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + + if self.sfp_type == SFP_TYPE: + sfpd_obj._calibration_type = self.calibration + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + volt = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return volt + + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + path_idx = INDEX_A0H + tx_bias_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + + elif self.sfp_type == QSFP_DD_TYPE: + if not self.dom_rx_tx_power_bias_supported: + return None + field_offset = QSFP_DD_PAGE11_OFFSET + Id_field = QSFP_DD_ID_FIELDS + sfpd_obj = qsfp_dd_Dom() + + elif self.sfp_type == SFP_TYPE: + if not self.dom_supported: + return None + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + + elif self.sfp_type == QSFP_DD_TYPE: + dom_tx_bias_raw = self._read_eeprom_bytes(field_offset + Id_field['TX_BIAS'][OFFSET], Id_field['TX_BIAS'][WIDTH], path_idx) + dom_tx_bias_data = sfpd_obj.parse_dom_tx_bias(dom_tx_bias_raw, 0) + + if self.dom_tx_bias_power_supported: + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX4Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX5Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX6Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX7Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX8Bias']['value'])) + else: + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value'])) + + return tx_bias_list + + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + path_idx = INDEX_A0H + rx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + if not self.dom_rx_power_supported: + return + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + + elif self.sfp_type == QSFP_DD_TYPE: + if not self.dom_rx_tx_power_bias_supported: + return None + field_offset = QSFP_DD_PAGE11_OFFSET + Id_field = QSFP_DD_ID_FIELDS + sfpd_obj = qsfp_dd_Dom() + + elif self.sfp_type == SFP_TYPE: + if not self.dom_supported: + return + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + if self.sfp_type == SFP_TYPE: + sfpd_obj._calibration_type = self.calibration + + if self.sfp_type == QSFP_DD_TYPE: + dom_rx_power_raw = self._read_eeprom_bytes(field_offset + Id_field['RX_POWER'][OFFSET], Id_field['RX_POWER'][WIDTH]) + if dom_rx_power_raw is not None: + dom_rx_power_data = sfpd_obj.parse_dom_rx_power(dom_rx_power_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX4Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX5Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX6Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX7Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX8Power']['value'])) + + else: + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value'])) + + return rx_power_list + + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + path_idx = INDEX_A0H + tx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + if not self.dom_tx_power_supported: + return + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + + elif self.sfp_type == QSFP_DD_TYPE: + if not self.dom_rx_tx_power_bias_supported: + return None + field_offset = QSFP_DD_PAGE11_OFFSET + Id_field = QSFP_DD_ID_FIELDS + sfpd_obj = qsfp_dd_Dom() + elif self.sfp_type == SFP_TYPE: + if not self.dom_supported: + return + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + if self.sfp_type == SFP_TYPE: + sfpd_obj._calibration_type = self.calibration + + if self.sfp_type == QSFP_DD_TYPE: + dom_tx_power_raw = self._read_eeprom_bytes(field_offset + Id_field['TX_POWER'][OFFSET], Id_field['TX_POWER'][WIDTH]) + if dom_tx_power_raw is not None: + dom_tx_power_data = sfpd_obj.parse_dom_tx_power(dom_tx_power_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX4Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX5Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX6Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX7Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX8Power']['value'])) + else: + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value'])) + + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + if self.reset_file is not None: + ret = self.__write_attr_file(self.reset_file, '1') + if ret != 0: + return True + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.lp_file is not None: + if lpmode is True: + ret = self.__write_attr_file(self.lp_file, "1") + else: + ret = self.__write_attr_file(self.lp_file, "0") + if ret != 0: + return True + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + return False + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/thermal.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/thermal.py new file mode 100755 index 0000000000..3731edaa7b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/sonic_platform/thermal.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +logger = Logger("thermal") +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + def __init__(self, index, name, sysfile_path, is_bmc, support_mask=0x1, ext_sysfile_list=None): + # index is used to indicate the temp{} under sffile_path + # support_mask: 1:support 0:not support + # bit 0 : temperature (always 1) + # bit 1 : high threshold + # bit 2 : low threshold + # bit 3 : high critical threshold + # bit 4 : low critical threshold + # bit 7 : cpu internal sensor + # ext_sysfile_list: each specified path of each supported function, + # which not follows the general naming rule + + self.index = index + self.name = name + self.filepath = sysfile_path + self.support_mask = support_mask + self.is_bmc = is_bmc + + self.temperature_file = None + self.high_thershold_file = None + self.low_threshold_file = None + self.high_critical_file = None + self.low_critical_file = None + + if sysfile_path is None: + return + + if self.is_bmc ==False or support_mask & 0x80 == 0x80: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + "/temp{}_input".format(self.index) + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + "/temp{}_max".format(self.index) + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + "/temp{}_min".format(self.index) + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + "/temp{}_crit".format(self.index) + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + "/temp{}_lcrit".format(self.index) + elif self.is_bmc and ext_sysfile_list is not None: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + ext_sysfile_list[self.index][0] + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + ext_sysfile_list[self.index][1] + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + ext_sysfile_list[self.index][2] + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][3] + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][4] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.name + + def get_presence(self): + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.temperature_file is not None: + temp = self.__read_attr_file( self.temperature_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_thershold_file is not None: + temp = self.__read_attr_file( self.high_thershold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_threshold_file is not None: + temp = self.__read_attr_file( self.low_threshold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_file is not None: + temp = self.__read_attr_file( self.high_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_critical_file is not None: + temp = self.__read_attr_file( self.low_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/templates/cameo_esc600_util.py.j2 b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/templates/cameo_esc600_util.py.j2 index d83d07f5ac..2025627e3d 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/templates/cameo_esc600_util.py.j2 +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/templates/cameo_esc600_util.py.j2 @@ -14,6 +14,7 @@ command: install : install drivers and generate related sysfs nodes clean : uninstall drivers and remove related sysfs nodes show : show all systen status + version : driver version sff : dump SFP eeprom set : change board setting with fan|led|sfp """ @@ -24,22 +25,619 @@ import sys, getopt import logging import re import time -import install_slot_driver +import json PROJECT_NAME = 'esc600_128q' -version = '0.1.0' verbose = False DEBUG = False -args = [] -ALL_DEVICE = {} -DEVICE_NO = {'led': 5, 'fan': 5, 'thermal': 3, 'psu': 4, 'sfp': 128} FORCE = 0 +PLATFORM_INSTALL_INFO_FILE="/etc/sonic/platform_install.json" +BMC_EXIST_SYSFILE_PATH="/sys/class/hwmon/hwmon2/device/ESC600_SYS/bmc_present" +LED_CTRL_SYSFILE_PATH="/sys/class/hwmon/hwmon2/device/ESC600_LED/led_fiber" +SLOT_STATUS_CURRENT_FILE='/sys/class/hwmon/hwmon2/device/ESC600_SYS/module_{}_present' + +INPHI_100G="Inphi 100G" +INPHI_400G="Inphi 400G" +CREDO_100G="Credo 100G" +CREDO_400G="Credo 400G" + +# default is 'i2c-0', we will choose the correct one from 'i2c-0' and 'i2c-1'. +DEFAULT_BASE_BUS = 'i2c-0' +BASE_BUS = 'i2c-0' + +I2C_BASE_BUS = { + 'i2c-0':{ + 'path':'/sys/bus/i2c/devices/i2c-0', + 'status':'INSTALLED' + }, + 'i2c-1':{ + 'path':'/sys/bus/i2c/devices/i2c-1', + 'status':'INSTALLED' + } +} + +switch_install_order = [ +'PCA9548_0x73', # (i2c-1 ~ i2c-8) +'PCA9548_0x77', # (i2c-9 ~ i2c-16) +'PCA9548_0x75', # (i2c-17 ~ i2c-24) +'PCA9548_0x74', # (i2c-25 ~ i2c-32) +'PCA9548_0x71_1', +'PCA9548_0x72_1', +'PCA9548_0x71_2', +'PCA9548_0x72_2', +'PCA9548_0x71_3', +'PCA9548_0x72_3', +'PCA9548_0x71_4', +'PCA9548_0x72_4', +'PCA9548_0x71_5', +'PCA9548_0x72_5', +'PCA9548_0x71_6', +'PCA9548_0x72_6', +'PCA9548_0x71_7', +'PCA9548_0x72_7', +'PCA9548_0x71_8', +'PCA9548_0x72_8', +] + +I2C_SWITCH_LIST = { + # i2c switches + 'PCA9548_0x73': { + 'parent':'base', + 'driver':'pca9548', + 'i2caddr': '0x73', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x77': { + 'parent':'base', + 'driver':'pca9548', + 'i2caddr': '0x77', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x75': { + 'parent':'base', + 'driver':'pca9548', + 'i2caddr': '0x75', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x74': { + 'parent':'base', + 'driver':'pca9548', + 'i2caddr': '0x74', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_1': { + 'parent':'PCA9548_0x73', + 'parent_ch': 0, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_2': { + 'parent':'PCA9548_0x73', + 'parent_ch': 1, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_3': { + 'parent':'PCA9548_0x73', + 'parent_ch': 2, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_4': { + 'parent':'PCA9548_0x73', + 'parent_ch': 3, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_5': { + 'parent':'PCA9548_0x73', + 'parent_ch': 4, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_6': { + 'parent':'PCA9548_0x73', + 'parent_ch': 5, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_7': { + 'parent':'PCA9548_0x73', + 'parent_ch': 6, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_8': { + 'parent':'PCA9548_0x73', + 'parent_ch': 7, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_1': { + 'parent':'PCA9548_0x73', + 'parent_ch': 0, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_2': { + 'parent':'PCA9548_0x73', + 'parent_ch': 1, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_3': { + 'parent':'PCA9548_0x73', + 'parent_ch': 2, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_4': { + 'parent':'PCA9548_0x73', + 'parent_ch': 3, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_5': { + 'parent':'PCA9548_0x73', + 'parent_ch': 4, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_6': { + 'parent':'PCA9548_0x73', + 'parent_ch': 5, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_7': { + 'parent':'PCA9548_0x73', + 'parent_ch': 6, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x72_8': { + 'parent':'PCA9548_0x73', + 'parent_ch': 7, + 'driver':'pca9548', + 'i2caddr': '0x72', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + } +} + +PHY_MODULE_DEVICE = dict() + +I2C_DEVICES = { + # sys eeprom + 'SYS_EEPROM': { + 'parent':'base', + 'driver':'24c64smbus', + 'i2caddr': '0x56', + 'path': ' ', + 'status':'NOTINST' + }, + # NCT7511Y sensor & fan control + 'NCT7511Y(U2)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 0, + 'driver':'nct7511', + 'i2caddr': '0x2e', + 'path': ' ', + 'status':'NOTINST' + }, + # Sensors + 'G781(U1)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 1, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U11)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 2, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U16)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 3, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U17)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 5, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U6)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 6, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U49)': { + 'parent':'PCA9548_0x74', + 'parent_ch': 0, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U1x)': { + 'parent':'PCA9548_0x74', + 'parent_ch': 1, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U21)': { + 'parent':'PCA9548_0x74', + 'parent_ch': 2, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'MCP3425(U43)': { + 'parent':'PCA9548_0x74', + 'parent_ch': 3, + 'driver':'mcp3425_smbus', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + # PSU + 'PSU1': { + 'parent':'PCA9548_0x75', + 'parent_ch': 4, + 'driver':'zrh2800k2', + 'i2caddr': '0x58', + 'path': ' ', + 'status':'NOTINST' + }, + 'PSU2': { + 'parent':'PCA9548_0x75', + 'parent_ch': 4, + 'driver':'zrh2800k2', + 'i2caddr': '0x59', + 'path': ' ', + 'status':'NOTINST' + }, + 'PSU3': { + 'parent':'PCA9548_0x75', + 'parent_ch': 4, + 'driver':'zrh2800k2', + 'i2caddr': '0x5a', + 'path': ' ', + 'status':'NOTINST' + }, + 'PSU4': { + 'parent':'PCA9548_0x75', + 'parent_ch': 4, + 'driver':'zrh2800k2', + 'i2caddr': '0x5b', + 'path': ' ', + 'status':'NOTINST' + }, + #DC2DC + 'TPS53681(0x6E)': { + 'parent':'PCA9548_0x74', + 'parent_ch': 5, + 'driver':'tps53679', + 'i2caddr': '0x6e', + 'path': ' ', + 'status':'NOTINST' + }, + 'TPS53681(0x70)': { + 'parent':'PCA9548_0x74', + 'parent_ch': 5, + 'driver':'tps53679', + 'i2caddr': '0x70', + 'path': ' ', + 'status':'NOTINST' + }, + 'ISP1014A': { + 'parent':'PCA9548_0x74', + 'parent_ch': 6, + 'driver':'powr1014', + 'i2caddr': '0x04', + 'path': ' ', + 'status':'NOTINST' + }, + # CPLD on line cards + 'PHY_CPLD_1': { + 'parent':'PCA9548_0x73', + 'parent_ch': 0, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum': 0 + }, + 'PHY_CPLD_2': { + 'parent':'PCA9548_0x73', + 'parent_ch': 1, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum': 0 + }, + 'PHY_CPLD_3': { + 'parent':'PCA9548_0x73', + 'parent_ch': 2, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum': 0 + }, + 'PHY_CPLD_4': { + 'parent':'PCA9548_0x73', + 'parent_ch': 3, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum':0 + }, + 'PHY_CPLD_5': { + 'parent':'PCA9548_0x73', + 'parent_ch': 4, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum': 0 + }, + 'PHY_CPLD_6': { + 'parent':'PCA9548_0x73', + 'parent_ch': 5, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum': 0 + }, + 'PHY_CPLD_7': { + 'parent':'PCA9548_0x73', + 'parent_ch': 6, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum': 0 + }, + 'PHY_CPLD_8': { + 'parent':'PCA9548_0x73', + 'parent_ch': 7, + 'driver':'phy_cpld640', + 'i2caddr': '0x32', + 'path': ' ', + 'status':'NOTINST', + 'portnum': 0 + } +} + +SFP_GROUPS = { + 'SFP-G11' :{ + 'number': 8, + 'parent':'PCA9548_0x71_1', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G12' :{ + 'number': 8, + 'parent':'PCA9548_0x72_1', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G21' :{ + 'number': 8, + 'parent':'PCA9548_0x71_2', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G22' :{ + 'number': 8, + 'parent':'PCA9548_0x72_2', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G31' :{ + 'number': 8, + 'parent':'PCA9548_0x71_3', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G32' :{ + 'number': 8, + 'parent':'PCA9548_0x72_3', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G41' :{ + 'number': 8, + 'parent':'PCA9548_0x71_4', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G42' :{ + 'number': 8, + 'parent':'PCA9548_0x72_4', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G51' :{ + 'number': 8, + 'parent':'PCA9548_0x71_5', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G52' :{ + 'number': 8, + 'parent':'PCA9548_0x72_5', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G61' :{ + 'number': 8, + 'parent':'PCA9548_0x71_6', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G62' :{ + 'number': 8, + 'parent':'PCA9548_0x72_6', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G71' :{ + 'number': 8, + 'parent':'PCA9548_0x71_7', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G72' :{ + 'number': 8, + 'parent':'PCA9548_0x72_7', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G81' :{ + 'number': 8, + 'parent':'PCA9548_0x71_8', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G82' :{ + 'number': 8, + 'parent':'PCA9548_0x72_8', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + } +} + PLATFORM_DRIVER_VER = {{ env("PLATFORM_DRIVER_VER") }} -if DEBUG == True: - print sys.argv[0] - print 'ARGV :', sys.argv[1:] +if DEBUG: + print(sys.argv[0]) + print('ARGV :', sys.argv[1:]) def main(): @@ -54,10 +652,10 @@ def main(): 'debug', 'force', ]) - if DEBUG == True: - print options - print args - print len(sys.argv) + if DEBUG: + print(options) + print(args) + print(len(sys.argv)) for opt, arg in options: if opt in ('-h', '--help'): @@ -75,66 +673,37 @@ def main(): elif arg == 'clean': do_uninstall() elif arg == 'show': - device_traversal() + devices_info() elif arg == 'version': show_version() - elif arg == 'sff': - if len(args) != 2: - show_eeprom_help() - elif int(args[1]) == 0 or int(args[1]) > DEVICE_NO['sfp']: - show_eeprom_help() - else: - show_eeprom(args[1]) - return - elif arg == 'set': - if len(args) < 3: - show_set_help() - else: - set_device(args[1:]) - return else: show_help() - return 0 +def show_help(): + print(__doc__ % {'scriptName': sys.argv[0].split("/")[-1]}) + sys.exit(0) + def show_version(): print("platform driver version: {}\n".format(PLATFORM_DRIVER_VER)) -def show_help(): - print __doc__ % {'scriptName': sys.argv[0].split("/")[-1]} - sys.exit(0) - - def show_set_help(): cmd = sys.argv[0].split("/")[-1] + " " + args[0] - print cmd + " [led|sfp|fan]" - print " use \"" + cmd + " led 0-4 \" to set led color" - print " use \"" + cmd + " fan 0-100\" to set fan duty percetage" - print " use \"" + cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable" + print(cmd + " [led|sfp|fan]") + print(" use \"" + cmd + " led 0-4 \" to set led color") + print(" use \"" + cmd + " fan 0-100\" to set fan duty percetage") + print(" use \"" + cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable") sys.exit(0) - -def show_eeprom_help(): - cmd = sys.argv[0].split("/")[-1] + " " + args[0] - print " use \"" + cmd + " 1-54 \" to dump sfp# eeprom" - sys.exit(0) - - -def my_log(txt): - if DEBUG == True: - print "[ROY]" + txt - return - - def log_os_system(cmd, show): logging.info('Run :' + cmd) status, output = commands.getstatusoutput(cmd) - my_log(cmd + "with result:" + str(status)) - my_log(" output:" + output) + logging.info(cmd + "with result:" + str(status)) + logging.info(" output:" + output) if status: logging.info('Failed :' + cmd) if show: - print('Failed :' + cmd) + print('Failed ({}):'.format(status) + cmd) return status, output @@ -182,59 +751,406 @@ def driver_uninstall(): return status return 0 +def get_inserted_slots(): + """ return list of inserted slots """ + slots = [] + for i in range(1,9): + path = SLOT_STATUS_CURRENT_FILE.format(i) + value = get_attr_value(path) + if int(value) == 1: + slots.append(i) + return slots + +def check_base_bus(): + global I2C_SWITCH_LIST + global I2C_DEVICES + global SFP_GROUPS + global BASE_BUS + # we start check with the first i2c switch to install which on base bus + switch = I2C_SWITCH_LIST[switch_install_order[0]] + for bbus in I2C_BASE_BUS.keys(): + install_path = I2C_BASE_BUS[bbus]['path'] + cmd = "echo {} {} > {}/new_device".format(switch['driver'], switch['i2caddr'], install_path) + log_os_system(cmd, 1) + time.sleep(1) + cmd = "ls /sys/bus/i2c/devices/{}-00{}/channel-0".format(bbus[-1],switch['i2caddr'][-2:]) + result = log_os_system(cmd, 1)[0] + #uninstall + cmd = "echo {} > {}/delete_device".format(switch['i2caddr'], install_path) + log_os_system(cmd, 1) + if result == 0: + BASE_BUS = bbus + break + + logging.info('Base bus is {}'.format(BASE_BUS)) + + #exchange all base bus + for dev_name in I2C_SWITCH_LIST.keys(): + if I2C_SWITCH_LIST[dev_name]['parent'] == 'base': + I2C_SWITCH_LIST[dev_name]['parent'] = BASE_BUS + for dev_name in I2C_DEVICES.keys(): + if I2C_DEVICES[dev_name]['parent'] == 'base': + I2C_DEVICES[dev_name]['parent'] = BASE_BUS + for dev_name in SFP_GROUPS.keys(): + if SFP_GROUPS[dev_name]['parent'] == 'base': + SFP_GROUPS[dev_name]['parent'] = BASE_BUS + +def get_next_bus_num(): + num_list = [] + device_list = os.listdir("/sys/bus/i2c/devices") + for x in device_list: + t = re.match(r'i2c-(\d+)', x) + if t: + num_list.append(int(t.group(1))) + logging.info('next_bus_id is {}'.format(max(num_list)+1)) + return max(num_list)+1 + +def install_i2c_switch(): + + for switch_name in switch_install_order: + next_bus_id = get_next_bus_num() + switch = I2C_SWITCH_LIST[switch_name] + if switch['parent'] in I2C_BASE_BUS: + install_path = I2C_BASE_BUS[switch['parent']]['path'] + else: + install_path = I2C_SWITCH_LIST[switch['parent']]['path'] + + if 'parent_ch' in switch: + install_path = install_path+"/channel-{}".format(switch['parent_ch']) + if I2C_SWITCH_LIST[switch['parent']]['status'] != 'INSTALLED': + continue + + cmd = "echo {} {} > {}/new_device".format(switch['driver'], switch['i2caddr'], install_path) + status, output = log_os_system(cmd, 1) + if status != 0: + switch['status'] = 'FAILED' + continue + + if switch['parent'] in I2C_BASE_BUS: + switch['path'] = "/sys/bus/i2c/devices/{}-00{}".format(switch['parent'][-1],switch['i2caddr'][-2:]) + else: + switch['path'] = "/sys/bus/i2c/devices/{}-00{}".format(I2C_SWITCH_LIST[switch['parent']]['bus_map'][switch['parent_ch']],switch['i2caddr'][-2:]) + + # add delay to make sure the root switch for sfp is installed completely, + # so we can start the installation of next switch + if switch_name == 'PCA9548_0x73': + time.sleep(1) + + #Check if bus are actually created + for busid in range(next_bus_id,next_bus_id+8): + if not os.path.exists("/sys/bus/i2c/devices/i2c-{}".format(busid)): + print("Fail to create bus when install {}".format(switch_name)) + switch['status'] = 'FAILED' + break + else: + # exit loop normally; not breakout + switch['bus_map'] = list(range(next_bus_id,next_bus_id+8)) + switch['status'] = 'INSTALLED' + +def remove_install_status(): + if os.path.exists(PLATFORM_INSTALL_INFO_FILE): + os.remove(PLATFORM_INSTALL_INFO_FILE) + +def restore_install_status(): + output = list() + output.append(I2C_SWITCH_LIST) + output.append(I2C_DEVICES) + output.append(SFP_GROUPS) + output.append(PHY_MODULE_DEVICE) + jsondata = json.dumps(output) + with open(PLATFORM_INSTALL_INFO_FILE,'w') as fd: + fd.write(jsondata) + +def update_hwmon(inslist=None): + for dev_name in I2C_DEVICES.keys(): + dev = I2C_DEVICES[dev_name] + if dev['status'] == 'INSTALLED': + if os.path.exists(dev['path']+'/hwmon'): + dev['hwmon_path'] = os.path.join(dev['path']+'/hwmon', os.listdir(dev['path']+'/hwmon')[0]) + + +def install_i2c_device(inslist=None): + if inslist is None: + inslist = I2C_DEVICES + for dev_name in inslist.keys(): + dev = inslist[dev_name] + if dev['parent'] in I2C_BASE_BUS: + install_path = I2C_BASE_BUS[dev['parent']]['path'] + else: + install_path = I2C_SWITCH_LIST[dev['parent']]['path'] + + if 'parent_ch' in dev: + install_path = install_path+"/channel-{}".format(dev['parent_ch']) + if I2C_SWITCH_LIST[dev['parent']]['status'] != 'INSTALLED': + continue + + cmd = "echo {} {} > {}/new_device".format(dev['driver'], dev['i2caddr'], install_path) + status, output = log_os_system(cmd, 1) + if status != 0: + dev['status'] = 'FAILED' + continue + + if dev['parent'] in I2C_BASE_BUS: + dev['path'] = "/sys/bus/i2c/devices/{}-00{}".format(dev['parent'][-1],dev['i2caddr'][-2:]) + else: + dev['path'] = "/sys/bus/i2c/devices/{}-00{}".format(I2C_SWITCH_LIST[dev['parent']]['bus_map'][dev['parent_ch']],dev['i2caddr'][-2:]) + + dev['status'] = 'INSTALLED' + + +def install_phy_module_i2c_device(): + global I2C_DEVICES + global PHY_MODULE_DEVICE + inserted_slots = get_inserted_slots() + # if there is no inserted slots, do nothing + if len(inserted_slots) == 0: + return + + phy_module_devices = dict() + for slot in range(1,9): + I2C_DEVICES["PHY_CPLD_{}".format(slot)]['portnum'] = 0 + + for slot in inserted_slots: + cpld_path = I2C_DEVICES["PHY_CPLD_{}".format(slot)]['path'] + model_type = get_attr_value(cpld_path+"/model") + if model_type not in [INPHI_100G, INPHI_400G, CREDO_100G, CREDO_400G]: + print("Read model type failed! skip driver installation.") + return + if model_type == INPHI_100G or model_type == CREDO_100G: + I2C_DEVICES["PHY_CPLD_{}".format(slot)]['portnum'] = 16 + else: + I2C_DEVICES["PHY_CPLD_{}".format(slot)]['portnum'] = 4 + + phy_module_devices = { + 'CARD{}_G781'.format(slot): { + 'parent':'PCA9548_0x77', + 'parent_ch': slot-1, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'CARD{}_LM63'.format(slot): { + 'parent':'PCA9548_0x77', + 'parent_ch': slot-1, + 'driver':'lm63', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'CARD{}_D2D(0x11)'.format(slot): { + 'parent':'PCA9548_0x77', + 'parent_ch': slot-1, + 'driver':'tps40425', + 'i2caddr': '0x11', + 'path': ' ', + 'status':'NOTINST' + }, + 'CARD{}_D2D(0x12)'.format(slot): { + 'parent':'PCA9548_0x77', + 'parent_ch': slot-1, + 'driver':'tps40425', + 'i2caddr': '0x12', + 'path': ' ', + 'status':'NOTINST' + }, + 'CARD{}_D2D(0x13)'.format(slot): { + 'parent':'PCA9548_0x77', + 'parent_ch': slot-1, + 'driver':'tps40425', + 'i2caddr': '0x13', + 'path': ' ', + 'status':'NOTINST' + } + } + + if model_type == INPHI_100G: + phy_module_devices["CARD{}_G781".format(slot)]['i2caddr'] = '0x4d' + if model_type == INPHI_400G: + phy_module_devices["CARD{}_G781".format(slot)]['i2caddr'] = '0x4d' + phy_module_devices.pop('CARD{}_D2D(0x12)'.format(slot), None) + if model_type == CREDO_100G: + phy_module_devices.pop('CARD{}_LM63'.format(slot), None) + if model_type == CREDO_400G: + phy_module_devices.pop('CARD{}_LM63'.format(slot), None) + phy_module_devices.pop('CARD{}_D2D(0x12)'.format(slot), None) + + PHY_MODULE_DEVICE.update(phy_module_devices) + + install_i2c_device(PHY_MODULE_DEVICE) + +def get_slot_sfp_number(slot_id): + cpld_path = I2C_DEVICES["PHY_CPLD_{}".format(slot_id)]['path'] + portnum = get_attr_value(cpld_path+"/portnum") + + if portnum == 'ERR': + return 0 + else: + return int(portnum) + +def install_sfp(): + for sfp_group_name in SFP_GROUPS.keys(): + sfp_group = SFP_GROUPS[sfp_group_name] + if sfp_group['parent'] in I2C_BASE_BUS: + install_path = I2C_BASE_BUS[sfp_group['parent']]['path'] + else: + install_path = I2C_SWITCH_LIST[sfp_group['parent']]['path'] + sfp_group['number'] = 0 + # parent switch is not installed, skip this sfp group + if I2C_SWITCH_LIST[sfp_group['parent']]['status'] != 'INSTALLED': + sfp_group['paths'] = ['n/a']*sfp_group['number'] + continue + + sfp_num = get_slot_sfp_number(sfp_group_name[-2]) + + sfp_group['number'] = sfp_num + + if sfp_num == 4 and sfp_group_name[-1] == 2: + sfp_group['number'] = 0 + continue + + if sfp_num == 16: + sfp_group['number'] = 8 + + for n in range(0,sfp_group['number']): + sfp_install_path = install_path+"/channel-{}".format(sfp_group['channels'][n]) + cmd = "echo {} {} > {}/new_device".format(sfp_group['driver'], sfp_group['i2caddr'], sfp_install_path) + status, output = log_os_system(cmd, 1) + if status != 0: + sfp_group['status'] = 'FAILED' + sfp_group['paths'].append('n/a') + continue + + if sfp_group['parent'] in I2C_BASE_BUS: + sfp_group['paths'].append("/sys/bus/i2c/devices/{}-00{}".format(sfp_group['parent'][-1],sfp_group['i2caddr'][-2:])) + else: + sfp_group['paths'].append("/sys/bus/i2c/devices/{}-00{}".format(I2C_SWITCH_LIST[sfp_group['parent']]['bus_map'][sfp_group['channels'][n]],sfp_group['i2caddr'][-2:])) + + # if all sfps in a group are success + if len(sfp_group['paths']) == sfp_group['number']: + sfp_group['status'] = "INSTALLED" + +def uninstall_sfp(): + for sfp_group_name in SFP_GROUPS.keys(): + sfp_group = SFP_GROUPS[sfp_group_name] + if sfp_group['parent'] in I2C_BASE_BUS: + uninst_path = I2C_BASE_BUS[sfp_group['parent']]['path'] + else: + uninst_path = I2C_SWITCH_LIST[sfp_group['parent']]['path'] + + # sfp is not installed, skip this sfp group + if sfp_group['status'] != 'INSTALLED': + continue + + for n in range(0,sfp_group['number']): + sfp_uninst_path = uninst_path+"/channel-{}".format(sfp_group['channels'][n]) + cmd = "echo {} > {}/delete_device".format(sfp_group['i2caddr'], sfp_uninst_path) + log_os_system(cmd, 1) + +def uninstall_i2c_device(inslist=None): + for dev_name in I2C_DEVICES.keys(): + dev = I2C_DEVICES[dev_name] + if dev['parent'] in I2C_BASE_BUS: + uninst_path = I2C_BASE_BUS[dev['parent']]['path'] + else: + uninst_path = I2C_SWITCH_LIST[dev['parent']]['path'] + + # device is not installed, skip this device + if dev['status'] != 'INSTALLED': + continue + + if 'parent_ch' in dev: + uninst_path = uninst_path+"/channel-{}".format(dev['parent_ch']) + + cmd = "echo {} > {}/delete_device".format(dev['i2caddr'], uninst_path) + log_os_system(cmd, 1) + +def uninstall_i2c_switch(): + for switch_name in reversed(switch_install_order): + switch = I2C_SWITCH_LIST[switch_name] + if switch['parent'] in I2C_BASE_BUS: + uninst_path = I2C_BASE_BUS[switch['parent']]['path'] + else: + uninst_path = I2C_SWITCH_LIST[switch['parent']]['path'] + + # switch is not installed, skip this switch + if switch['status'] != 'INSTALLED': + continue + + if 'parent_ch' in switch: + uninst_path = uninst_path+"/channel-{}".format(switch['parent_ch']) + + cmd = "echo {} > {}/delete_device".format(switch['i2caddr'], uninst_path) + log_os_system(cmd, 1) + +def hw_adjustment(): + global SFP_GROUPS + global I2C_DEVICES + global switch_install_order + global I2C_SWITCH_LIST + if bmc_is_exist(): + switch_install_order.remove('PCA9548_0x75') + switch_install_order.remove('PCA9548_0x74') + switch_install_order.remove('PCA9548_0x77') + for device_name in I2C_DEVICES.keys(): + device = I2C_DEVICES[device_name] + if device['parent'] in ['PCA9548_0x75', 'PCA9548_0x74', 'PCA9548_0x77'] : + device['status'] = 'viaBMC' + + hw_ver = get_hw_version() + if hw_ver is not None: + print("HW version: {}".format(hw_ver)) + hw_ver = int(hw_ver, 16) + else: + print("Failed to get HW version") + hw_ver = 0x0 + +def set_led_control(): + cmd = "echo 1 > {}".format(LED_CTRL_SYSFILE_PATH) + status, output = log_os_system(cmd, 1) + if status: + print(output) + +def device_install(): + remove_install_status() + hw_adjustment() + check_base_bus() + set_led_control() + install_i2c_switch() + # add delay to make sure all switch is installed completely, + # so we can start install other slave device safely. + time.sleep(1) + install_i2c_device() + install_phy_module_i2c_device() + install_sfp() + update_hwmon() + restore_install_status() + return 0 + +def device_uninstall(): + global SFP_GROUPS + global I2C_DEVICES + global I2C_SWITCH_LIST + global PHY_MODULE_DEVICE + try: + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + PHY_MODULE_DEVICE = install_info[3] + SFP_GROUPS = install_info[2] + I2C_DEVICES = install_info[1] + I2C_SWITCH_LIST = install_info[0] + uninstall_sfp() + uninstall_i2c_device() + uninstall_i2c_switch() + remove_install_status() + return 0 + except IOError as e: + print(e) + print("Platform install information file is not exist, please do install first") + return 1 i2c_prefix = '/sys/bus/i2c/devices/' -# used when bmc exist -mknod_bmc = [ - # enable port led stream - 'echo 1 > /sys/class/hwmon/hwmon2/device/ESC600_LED/led_ctrl', - # sys eeprom - 'echo 24c64smbus 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', - # 0x73, connects QSFP (i2c-1 ~ i2c-8) - 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-0/new_device' -] - -mknod_without_bmc = [ - # enable port led stream - 'echo 1 > /sys/class/hwmon/hwmon2/device/ESC600_LED/led_ctrl', - # sys eeprom - 'echo 24c64smbus 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', - # 0x73, connects QSFP (i2c-1 ~ i2c-8) - 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-0/new_device', - # 0x77 channel 0 - 7 (i2c-9 ~ i2c-16) - 'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', - # 0x75 channel 0 - 7 (i2c-17 ~ i2c-24) - 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-0/new_device', - # 0x74 channel 0 - 7 (i2c-25 ~ i2c-32) - 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-0/new_device', - - # 0x75 -> NCT7511Y sensor & fan control - 'echo nct7511 0x2e > /sys/bus/i2c/devices/i2c-17/new_device', - # 0x75 -> G781 sensors - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-18/new_device', - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-19/new_device', - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-20/new_device', - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-22/new_device', - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-23/new_device', - # 0x75 -> zrh2800k2 psu - 'echo zrh2800k2 0x58 > /sys/bus/i2c/devices/i2c-21/new_device', - 'echo zrh2800k2 0x59 > /sys/bus/i2c/devices/i2c-21/new_device', - 'echo zrh2800k2 0x5A > /sys/bus/i2c/devices/i2c-21/new_device', - 'echo zrh2800k2 0x5B > /sys/bus/i2c/devices/i2c-21/new_device', - # 0x74 -> G781 sensors - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-25/new_device', - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-26/new_device', - 'echo g781 0x4c > /sys/bus/i2c/devices/i2c-27/new_device', - # 0x74 -> mcp3425 sensor - 'echo mcp3425_smbus 0x68 > /sys/bus/i2c/devices/i2c-28/new_device', - # 0x74 -> tps53681 - 'echo tps53679 0x6E > /sys/bus/i2c/devices/i2c-30/new_device', - 'echo tps53679 0x70 > /sys/bus/i2c/devices/i2c-30/new_device', - # 0x74 -> powr1014 - 'echo powr1014 0x04 > /sys/bus/i2c/devices/i2c-31/new_device' -] - def get_attr_value(attr_path): retval = 'ERR' if not os.path.isfile(attr_path): @@ -250,117 +1166,62 @@ def get_attr_value(attr_path): fd.close() return retval +def get_hw_version(): + filePath = '/sys/class/hwmon/hwmon2/device/ESC600_SYS/cpld_30_ver' + if os.path.exists(filePath): + value = get_attr_value(filePath) + return value[-1] + else: + return None + def bmc_is_exist(): value = '' - bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESC600_SYS/bmc_present' - if os.path.exists(bmc_filePath): - value = get_attr_value(bmc_filePath) - if value.find('not') < 0: + if os.path.exists(BMC_EXIST_SYSFILE_PATH): + value = get_attr_value(BMC_EXIST_SYSFILE_PATH) + if int(value) == 1: return True else: return False else: return False -def device_install(): - global FORCE - bmc_exist = False - - if bmc_is_exist(): - mknod = mknod_bmc - bmc_exist = True - else: - mknod = mknod_without_bmc - - for i in range(0, len(mknod)): - # for pca954x need times to built new i2c buses - if mknod[i].find('pca954') != -1: - time.sleep(1) - - status, output = log_os_system(mknod[i], 1) - if status: - print output - if FORCE == 0: - return status - - # for pca954x need times to built new i2c buses - time.sleep(2) - install_slot_driver.remove_card_devices(bmc_exist) - install_slot_driver.install_card_devices(bmc_exist) - - return - - -def device_uninstall(): - global FORCE - bmc_exist = False - - if bmc_is_exist(): - nodelist = mknod_bmc - bmc_exist = True - else: - nodelist = mknod_without_bmc - - install_slot_driver.remove_card_devices(bmc_exist) - - for i in range(len(nodelist)): - target = nodelist[-(i + 1)] - temp = target.split() - del temp[1] - temp[-1] = temp[-1].replace('new_device', 'delete_device') - status, output = log_os_system(" ".join(temp), 1) - if status: - print output - if FORCE == 0: - return status - - return - - -def system_ready(): - if driver_check() == False: - return False - if not device_exist(): - return False - return True - - def do_install(): - print "Checking system...." - if driver_check() == False: - print "No driver, installing...." + print("Checking system....") + if not driver_check() : + print("No driver, installing....") status = driver_install() if status: if FORCE == 0: return status else: - print PROJECT_NAME.upper() + " drivers detected...." + print(PROJECT_NAME.upper() + " drivers detected....") if not device_exist(): - print "No device, installing...." + print("No device, installing....") status = device_install() if status: if FORCE == 0: return status else: - print PROJECT_NAME.upper() + " devices detected...." + print (PROJECT_NAME.upper() + " devices detected....") return def do_uninstall(): - print "Checking system...." + print("Checking system....") if not device_exist(): - print PROJECT_NAME.upper() + " has no device installed...." + print(PROJECT_NAME.upper() + " has no device installed....") else: - print "Removing device...." + print ("Removing device....") status = device_uninstall() if status: + if FORCE == 0: return status - if driver_check() == False: - print PROJECT_NAME.upper() + " has no driver installed...." + if not driver_check(): + print(PROJECT_NAME.upper() + " has no driver installed....") else: - print "Removing installed driver...." + print("Removing installed driver....") status = driver_uninstall() if status: if FORCE == 0: @@ -368,40 +1229,40 @@ def do_uninstall(): return - def devices_info(): - return - - -def show_eeprom(index): - return - - -def set_device(args): - return - - -# get digits inside a string. -# Ex: 31 for "sfp31" -def get_value(input): - digit = re.findall('\d+', input) - return int(digit[0]) - - -def device_traversal(): - attr_path = '/sys/class/hwmon/hwmon2/device/ESC600_Sensor/sensor_temp' - try: - reg_file = open(attr_path, 'r') - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - print("Thermal sensors(1-4) temperature:\n") - for line in reg_file.readlines(): - print line - reg_file.close() - return - - + if not os.path.exists(PLATFORM_INSTALL_INFO_FILE): + print('Not found {} file'.format(PLATFORM_INSTALL_INFO_FILE)) + return + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for i in range(0,2): + for device_name in install_info[i].keys(): + device = install_info[i][device_name] + print("{} :".format(device_name)) + if device['parent'] in I2C_BASE_BUS: + print(" On Bus: {}".format(device['parent'])) + else: + print(" On Bus: i2c-{}".format(install_info[0][device['parent']]['bus_map'][device['parent_ch']])) + print(" i2c Address: {}".format(device['i2caddr'])) + print(" status: {}".format(device['status'])) + if device['status'] == 'INSTALLED': + print(" install path: {}".format(device['path'])) + if device.get('hwmon_path'): + print(" hwmon_path: {}".format(device['hwmon_path'])) + print(' ') + + for sfp_group_name in install_info[2].keys(): + bus_list = [] + sfp_group = install_info[2][sfp_group_name] + print("{} :".format(sfp_group_name)) + print(" sfp number: {}".format(sfp_group['number'])) + for n in range(0,sfp_group['number']): + bus_list.append("i2c-{}".format(install_info[0][sfp_group['parent']]['bus_map'][sfp_group['channels'][n]])) + print(" On Bus: {}".format(bus_list)) + print(" status: {}".format(sfp_group['status'])) + print(" install path: {}".format(', '.join(sfp_group['paths']))) + print(' ') + def device_exist(): ret1, log = log_os_system("ls " + i2c_prefix + "*0056", 0) return not ret1 diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_platform.sh b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_platform.sh new file mode 100755 index 0000000000..ddaf2198fb --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_platform.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Install esc600-128q python package +DEVICE="/usr/share/sonic/device" +PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + +if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl ]; then + pip install $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl +fi + +if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py3-none-any.whl ]; then + pip3 install $DEVICE/$PLATFORM/sonic_platform-1.0-py3-none-any.whl +fi \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_sensors.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_sensors.py index 319f350df9..5844ac3b3e 100755 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_sensors.py +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/cameo_esc600_sensors.py @@ -1,21 +1,56 @@ #!/usr/bin/python from __future__ import print_function +from tabulate import tabulate import os import sys import logging +import json -FAN_NUM = 5 +MAX_FAN_NUM = 4 MAX_PSU_NUM = 4 -fans_path = '/sys/class/hwmon/hwmon2/device/ESC600_FAN/' -sensors_path = '/sys/class/hwmon/hwmon2/device/ESC600_Sensor/' -cameo_psu_path = '/sys/class/hwmon/hwmon2/device/ESC600_PSU/' +PSU_LIST = ['PSU1','PSU2','PSU3','PSU4'] -psu_path = [ '/sys/bus/i2c/devices/21-0058/', - '/sys/bus/i2c/devices/21-0059/', - '/sys/bus/i2c/devices/21-005a/', - '/sys/bus/i2c/devices/21-005b/'] +THERMAL_SENSOR_LIST = ['NCT7511Y(U2)', 'G781(U49)', 'G781(U1)', 'G781(U21)', 'G781(U1x)', + 'G781(U11)', 'G781(U16)', 'G781(U17)', 'G781(U6)'] + +PLATFORM_INSTALL_INFO_FILE = '/etc/sonic/platform_install.json' +BMC_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESC600_SYS/' +FAN_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESC600_FAN/' +POWER_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESC600_POWER/' +THERMAL_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESC600_THERMAL/' + +def get_psu_path(): + """ + get psu path when without BMC control + """ + psu_path = [] + try: + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for psu_name in PSU_LIST: + psu = install_info[1][psu_name] + psu_path.append(psu['path']+'/') + return psu_path + except Exception: + print("Fail to get psu sysfsfile path") + + return psu_path + +def get_thermal_sensor_path(): + sensor_path = [] + try: + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for sensor_name in THERMAL_SENSOR_LIST: + sensor = install_info[1][sensor_name] + sensor_path.append(sensor['hwmon_path']+'/') + return sensor_path + except Exception: + print("Fail to get sensor sysfsfile path") + + return sensor_path # Get sysfs attribute def get_attr_value(attr_path): @@ -35,36 +70,16 @@ def get_attr_value(attr_path): def bmc_is_exist(): value = '' - bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESC600_SYS/bmc_present' + bmc_filePath = BMC_SYSFILE_PATH+'bmc_present' if os.path.exists(bmc_filePath): value = get_attr_value(bmc_filePath) - if value.find('not') < 0: + if int(value) == 1: return True else: return False else: return False -def calc_mac_temp(): - value = '' - try: - if bmc_is_exist(): - mac_temp_string = get_attr_value(sensors_path+'mac_temp').split(' ') - value = int(mac_temp_string[-1], 16) - mac_sensor= (((value&0xFF)<<8)|((value&0xFF00)>>8)) /1000.0 - else: - raw = get_attr_value('/sys/bus/i2c/devices/28-0068/iio:device0/in_voltage0_raw') - scale = get_attr_value('/sys/bus/i2c/devices/28-0068/iio:device0/in_voltage0_scale') - mac_sensor= int(raw,10)*float(scale) - except Exception as e: - print("Failed to get MAC sensor temp: {}".format(e.args[0])) - return 0 - - temp1 = -124.28 * mac_sensor * mac_sensor - temp2 = -422.03 * mac_sensor - temp_sensor = 384.62 + temp1 + temp2 - return round(temp_sensor,2) - def print_attr_value_lines(sys_path): retval = 'ERR' if not os.path.isfile(sys_path): @@ -79,182 +94,196 @@ def print_attr_value_lines(sys_path): fo.close() return retval -def get_fan_alert(number): - return +def show_sensor_table(): -def get_fan_inner_rpm(number): - return - -def get_fan_outer_rpm(number): - return - -def sensors_status(): - print ('SENSOR STATUS:') - if bmc_is_exist(): - sys_path = sensors_path + 'sensor_status' - print_attr_value_lines(sys_path) - - return - -def sensors_temp(): - print ('SENSOR TEMPERATURE:') - print (' MAC sensor temp:%.2f degrees (C)'% calc_mac_temp()) + headers = ['Sensor', 'Temperature(C)', 'High(C)', 'Low(C)', 'Critical High(C)', 'Critical Low(C)'] + table = list() + temp = list() if bmc_is_exist(): - sys_path = sensors_path + 'sensor_temp' - print_attr_value_lines(sys_path) - sys_path = sensors_path + 'module_temp' - print_attr_value_lines(sys_path) + sensor_table = [ + ['Sensor 1 MB Top' , 'nct7511_temp', 'temp_th0_t_max', 'temp_th0_t_min', 'temp_th0_t_crit', 'temp_th0_t_lcrit'], + ['Sensor 2 SB LB' , 'left_bot_sb_temp', 'temp_th0_b_max', 'temp_th0_b_min', 'temp_th0_b_crit', 'temp_th0_b_lcrit'], + ['Sensor 3 SB CT' , 'ctr_top_sb_temp', 'temp_th0_r_max', 'temp_th0_r_min', 'temp_th0_r_crit', 'temp_th0_r_lcrit'], + ['Sensor 4 SB Center' , 'ctr_sb_temp', 'temp_th1_t_max', 'temp_th1_t_min', 'temp_th1_t_crit', 'temp_th1_t_lcrit'], + ['Sensor 5 CB Top' , 'left_top_cb_temp', 'temp_th1_b_max', 'temp_th1_b_min', 'temp_th1_b_crit', 'temp_th1_b_lcrit'], + ['Sensor 6 CB Center' , 'ctr_cb_temp', 'temp_th2_t_max', 'temp_th2_t_min', 'temp_th2_t_crit', 'temp_th2_t_lcrit'], + ['Sensor 7 CB Bottom' , 'right_bot_cb_temp', 'temp_th2_b_max', 'temp_th2_b_min', 'temp_th2_b_crit', 'temp_th2_b_lcrit'], + ['Sensor 8 CB Left' , 'left_bot_cb_temp', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit'], + ['Sensor 9 IO Board' , 'io_board_temp', 'temp_th3_b_max', 'temp_th3_b_min', 'temp_th3_b_crit', 'temp_th3_b_lcrit'], + ] + else: + sensor_path = get_thermal_sensor_path() + sensor_table = [ + ['Sensor 1 MB Top' , sensor_path[0]+'temp4_input', sensor_path[0]+'temp4_max', sensor_path[0]+'temp4_min', sensor_path[0]+'temp4_crit', sensor_path[0]+'temp4_lcrit'], + ['Sensor 2 SB LB' , sensor_path[0]+'temp1_input', sensor_path[0]+'temp1_max', sensor_path[0]+'temp1_min', sensor_path[0]+'temp1_crit', sensor_path[0]+'temp1_lcrit'], + ['Sensor 3 SB CT' , sensor_path[0]+'temp2_input', sensor_path[0]+'temp2_max', sensor_path[0]+'temp2_min', sensor_path[0]+'temp2_crit', sensor_path[0]+'temp2_lcrit'], + ['Sensor 4 SB Center' , sensor_path[1]+'temp1_input', sensor_path[1]+'temp1_max', sensor_path[1]+'temp1_min', sensor_path[1]+'temp1_crit', sensor_path[1]+'temp1_lcrit'], + ['Sensor 5 CB Top' , sensor_path[1]+'temp2_input', sensor_path[1]+'temp2_max', sensor_path[1]+'temp2_min', sensor_path[1]+'temp2_crit', sensor_path[1]+'temp2_lcrit'], + ['Sensor 6 CB Cente' , sensor_path[2]+'temp1_input', sensor_path[2]+'temp1_max', sensor_path[2]+'temp1_min', sensor_path[2]+'temp1_crit', sensor_path[2]+'temp1_lcrit'], + ['Sensor 7 CB Bottom' , sensor_path[2]+'temp2_input', sensor_path[2]+'temp2_max', sensor_path[2]+'temp2_min', sensor_path[2]+'temp2_crit', sensor_path[2]+'temp2_lcrit'], + ['Sensor 8 CB Left' , sensor_path[3]+'temp1_input', sensor_path[3]+'temp1_max', sensor_path[3]+'temp1_min', sensor_path[3]+'temp1_crit', sensor_path[3]+'temp1_lcrit'], + ['Sensor 9 IO Board' , sensor_path[3]+'temp2_input', sensor_path[3]+'temp2_max', sensor_path[3]+'temp2_min', sensor_path[3]+'temp2_crit', sensor_path[3]+'temp2_lcrit'], + ] + + for index in range(len(sensor_table)): + name = sensor_table[index][0] + for x in range(0, 5): + if bmc_is_exist(): + sys_path = THERMAL_SYSFILE_PATH + sensor_table[index][x+1] + else: + sys_path = sensor_table[index][x+1] + t = get_attr_value(sys_path) + if t == 'ERR': + temp.append('N/A') + else: + if t.isdigit(): + t = int(t)/1000.0 + temp.append('{}'.format(t)) + + table.append([name, temp[0], temp[1], temp[2], temp[3], temp[4]]) + del temp[:] - return + print(tabulate(table, headers, tablefmt='simple', stralign='right')) + print('') -def get_voltage(): - return +def show_fan_table(): + headers = ['Fan', 'Speed(RPM)', 'Presence', 'Status', 'Power'] + table = [] + for index in range(1, MAX_FAN_NUM+1): + name_front = "FAN{}".format(index) + speed_front = fan_speed(index) + present = fan_present(index) + status = fan_status(index) + power = fan_power(index) + table.append( [name_front, speed_front, present, status, power] ) + + print(tabulate(table, headers, tablefmt='simple', stralign='right')) + print('') -def fan_status(): - sys_path = fans_path + 'fan_status' - print ('FAN STATUS:') - print_attr_value_lines(sys_path) - return +def fan_status(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_stat'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'OK' + elif ret == '0': + return 'NG' + else: + return 'N/A' + +def fan_present(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_present'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'Present' + elif ret == '0': + return 'Not Present' + else: + return 'N/A' -def fan_present(): - sys_path = fans_path + 'fan_insert' - print ('FAN PRESENT:') - print_attr_value_lines(sys_path) - return - -def fan_power(): - sys_path = fans_path + 'fan_power' - print ('FAN POWER:') - print_attr_value_lines(sys_path) - return - -def fan_speed(): - sys_path = fans_path + 'fan_speed_rpm' - print ('FAN SPEED:') - print_attr_value_lines(sys_path) - return +def fan_power(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_power'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'OK' + elif ret == '0': + return 'NG' + else: + return 'N/A' +def fan_speed(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_rpm'.format(index) + front_ret = get_attr_value(sys_path) + if front_ret == 'ERR': + front_ret = 'N/A' + return front_ret def is_psu_present(psu_number): - sys_path = cameo_psu_path + 'psu_present' - search_str = "PSU {} is present".format(psu_number) + sys_path = POWER_SYSFILE_PATH + 'psu{}_prnt'.format(psu_number) if os.path.exists(sys_path): value = get_attr_value(sys_path) - if search_str in value: + if value == '1': return True else: return False return False -def show_psu_status(path): - # [model, vin, vout, fan_speed, temperature, pin, pout, iin, iout, max_iout] - result_list = [0]*10 - if bmc_is_exist(): - try: - reg_file = open(path, 'r') - except IOError as e: - print( "Error: unable to open file: %s" % str(e)) - return False - - text_lines = reg_file.readlines() - reg_file.close() - - for line in text_lines: - spline = line.split(' ') - if "MFR_MODEL" in spline: - result_list[0] = spline[-1] - if "VIN" in spline: - result_list[1] = spline[-1] - if "VOUT" in spline: - result_list[2] = spline[-1] - if "FAN_SPEED" in spline: - result_list[3] = spline[-1] - if "TEMP_1" in spline: - result_list[4] = spline[-1] - if "PIN" in spline: - result_list[5] = spline[-1] - if "POUT" in spline: - result_list[6] = spline[-1] - if "IIN" in spline: - result_list[7] = spline[-1] - if "IOUT" in spline: - result_list[8] = spline[-1] - if "MFR_IOUT_MAX" in spline: - result_list[9] = spline[-1] - - else: - result_list[0] = get_attr_value(path+"psu_mfr_model") - result_list[1] = get_attr_value(path+"psu_vin") - result_list[2] = get_attr_value(path+"psu_vout") - result_list[3] = get_attr_value(path+"psu_fan_speed_1") - result_list[4] = get_attr_value(path+"psu_temp_1") - result_list[5] = get_attr_value(path+"psu_pin") - result_list[6] = get_attr_value(path+"psu_pout") - result_list[7] = get_attr_value(path+"psu_iin") - result_list[8] = get_attr_value(path+"psu_iout") - result_list[9] = get_attr_value(path+"psu_iout_max") - if result_list[0] != 'ERR': - print (' model: {}'.format(result_list[0])) +def is_psu_power_up(psu_number): + sys_path = POWER_SYSFILE_PATH + 'psu{}_good'.format(psu_number) + if os.path.exists(sys_path): + value = get_attr_value(sys_path) + if value == '1': + return True + else: + return False - if result_list[1] != 'ERR': - vin = int(result_list[1])/1000.0 - print (' Input Voltage: {:+3.2f} V'.format(vin)) - - if result_list[2] != 'ERR': - vout = int(result_list[2])/1000.0 - print (' Output Voltage: {:+3.2f} V'.format(vout)) + return False + +def show_psu_table(): + headers = ['PSU', 'Presence', 'Power', 'Fan Speed(RPM)', 'Temperature(C)', 'Vin(V)', 'Vout(V)', 'Pin(W)', 'Pout(W)', 'Iin(A)', 'Iout(A)', 'Max Iout(A)'] + table = [] + psu_sysfiles_list = [] + isbmc = bmc_is_exist() + if isbmc is False: + PSU_PATH = get_psu_path() - if result_list[3] != 'ERR': - fan_speed = int(result_list[3]) - print (' Fan Speed: {:3d} RPM'.format(fan_speed)) + for index in range(0, MAX_PSU_NUM): + if isbmc: + psu_sysfiles_list = [ + POWER_SYSFILE_PATH+'psu{}_fan_speed'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_temp'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_vin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_vout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_pin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_pout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_iin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_iout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_mfr_iout_max'.format(index+1) + ] + else: + psu_sysfiles_list = [ + PSU_PATH[index]+'psu_fan_speed_1', + PSU_PATH[index]+'psu_temp_1', + PSU_PATH[index]+'psu_vin', + PSU_PATH[index]+'psu_vout', + PSU_PATH[index]+'psu_pin', + PSU_PATH[index]+'psu_pout', + PSU_PATH[index]+'psu_iin', + PSU_PATH[index]+'psu_iout', + PSU_PATH[index]+'psu_iout_max' + ] + status_list = get_psu_status(index+1, psu_sysfiles_list) + table.append(status_list) - if result_list[4] != 'ERR': - temperature = int(result_list[4])/1000.0 - print (' Temperature: {:+3.1f} C'.format(temperature)) - - if result_list[5] != 'ERR': - pin = int(result_list[5])/1000000.0 - print (' Input Power: {:3.2f} W'.format(pin)) - - if result_list[6] != 'ERR': - pout = int(result_list[6])/1000000.0 - print (' Output Power: {:3.2f} W'.format(pout)) - - if result_list[7] != 'ERR': - iin = int(result_list[7])/1000.0 - print (' Input Current: {:+3.2f} A'.format(iin)) - - if result_list[8] != 'ERR': - iout = int(result_list[8])/1000.0 - print (' Output Current: {:+3.2f} A'.format(iout),end='') - - if result_list[9] != 'ERR': - max_iout = int(result_list[9])/1000.0 - print (' (max = {:+3.2f} A)'.format(max_iout)) - + print(tabulate(table, headers, tablefmt='simple', stralign='right')) print('') - return +def get_psu_status(index, sysfile_list): + # result_list: [name, presence, power, fanSpeed(RPM), temperature(C), vin(V), vout(V), pin(W), pout(W), iin(A), iout(A), maxIout(A)] + name = 'PSU{}'.format(index) + result_list = [name, 'Not Present', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A'] + result_mutipler = [None, None, None, None, 1000.0, 1000.0, 1000.0, 1000000.0, 1000000.0, 1000.0, 1000.0, 1000.0] + + if is_psu_present(index): + result_list[1] = 'Present' + else: + return result_list + + if is_psu_power_up(index): + result_list[2] = 'up' + else: + result_list[2] = 'down' -def show_psu_status_bmc(path): - print_attr_value_lines(path) - return - - -def psu_status(): - - for x in range(0,MAX_PSU_NUM): - if is_psu_present(x+1): - print("PSU{} present".format(x+1)) - if bmc_is_exist(): - show_psu_status(cameo_psu_path + 'psu_module_{}'.format(x+1)) - else: - show_psu_status(psu_path[x]) - - return - + for x in range(0, 9): + result_list[x+3] = get_attr_value(sysfile_list[x]) + + for x in range(0, 12): + if result_mutipler[x] is not None and result_list[x] != 'ERR': + result_list[x] = int(result_list[x]) / result_mutipler[x] + + return result_list + def main(): """ @@ -269,16 +298,11 @@ def main(): for arg in sys.argv[1:]: if arg == 'fan_status': - fan_status() - fan_present() - fan_power() - fan_speed() + show_fan_table() elif arg == 'sensor_status': - sensors_temp() - sensors_status() - psu_status() - - + show_sensor_table() + show_psu_table() + else: print (main.__doc__) diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_dynamic_hotswap.py b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_dynamic_hotswap.py index b306a84cb0..e110559d0a 100755 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_dynamic_hotswap.py +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_dynamic_hotswap.py @@ -6,11 +6,10 @@ import logging from multiprocessing import Process, Lock import time import subprocess -#import BaldEagleSdk_v2_14_18 as BE214 -#import BaldEagleSdk_v2_12_00_20190715_cameo_gearbox as BE212 +# import BaldEagleSdk_v2_18 as BE218 + from importlib import import_module -BE214 = import_module('esc600-128q.BaldEagleSdk_v2_14_18') -BE212 = import_module('esc600-128q.BaldEagleSdk_v2_12_00_20190715_cameo_gearbox') +BE218 = import_module('esc600-128q.BaldEagleSdk_v2_18') gMaxThreadNum=4 lock1 = Lock() @@ -34,7 +33,21 @@ def set_attr_value(attr_path,input_val): cmd = "echo %d > %s" %(input_val,attr_path) logging.debug(cmd) run_command(cmd) + +def get_attr_value(attr_path): + retval = 'ERR' + if not os.path.isfile(attr_path): + return retval + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + retval = retval.rstrip('\r\n') + fd.close() + return retval + def card_type_detect(card): sup_card_typed = ['Inphi 100G','Credo 100G','Inphi 400G','Credo 400G'] @@ -72,45 +85,29 @@ def card_reset(card): return True; def card_power_isgood(card): - filepath = "/sys/class/hwmon/hwmon2/device/ESC600_Module/module_power" + filepath = "/sys/class/hwmon/hwmon2/device/ESC600_SYS/module_%d_power" % card logging.debug(filepath) - status = False if os.path.exists(filepath): - with open(filepath) as fh: - for line in fh: - get_str = line.strip() - modulestr = "Module %d is power good" %(card) - val = get_str.find(modulestr); - if val != -1: - logging.debug(modulestr) - status = True - return True,status - status = False - return True,status - - return False,status + val = get_attr_value(filepath) + if val == '1': + return True, True + else: + return True, False + return False, False def card_12v_status(card): - filepath = "/sys/class/hwmon/hwmon2/device/ESC600_Module/module_12v_status" + filepath = "/sys/class/hwmon/hwmon2/device/ESC600_SYS/module_%d_power" % card logging.debug(filepath) - status = False if os.path.exists(filepath): - with open(filepath) as fh: - for line in fh: - get_str = line.strip() - modulestr = "Module %d 12V is enable" %(card) - val = get_str.find(modulestr); - if val != -1: - logging.debug(modulestr) - status = True - return True,status - status = False - return True,status - - return False,status + val = get_attr_value(filepath) + if val == '1': + return True, True + else: + return True, False + return False, False def light_led(act,card): - led_loc = ['switch_led_4_1', 'switch_led_4_2', 'switch_led_4_3', 'switch_led_4_4', 'switch_led_5_1','switch_led_5_2','switch_led_5_3','switch_led_5_4'] + led_loc = ['led_4_1', 'led_4_2', 'led_4_3', 'led_4_4', 'led_5_1','led_5_2','led_5_3','led_5_4'] value = 0 lock2.acquire() filepath = '/sys/class/hwmon/hwmon2/device/ESC600_LED/%s'%led_loc[card-1] @@ -138,30 +135,22 @@ def light_led(act,card): lock2.release() def card_inserted(card): - filepath = "/sys/class/hwmon/hwmon2/device/ESC600_Module/module_insert" + filepath = "/sys/class/hwmon/hwmon2/device/ESC600_SYS/module_%d_present" % card logging.debug(filepath) - status = False if os.path.exists(filepath): - with open(filepath) as fh: - for line in fh: - get_str = line.strip() - modulestr = "Module %d is present" %(card) - val = get_str.find(modulestr); - if val != -1: - logging.debug(modulestr) - status = True - return True,status - status = True - return True,status - - return False,status + val = get_attr_value(filepath) + if val == '1': + return True, True + else: + return True, False + return False, False def job(mdio): if mdio < 0 or mdio > 3: logging.error("MDIO [%d] out of range" % mdio) return False CardStatus = ['NA','NA'] - + FirstInitFlag = True while(1): for i in range(2): card = mdio*2+i+1 @@ -214,15 +203,18 @@ def job(mdio): for i in range(2): card = mdio*2+i+1 if CardStatus[i]=='Initializing' : - init_status = False + if FirstInitFlag: + BE218.cameo_fw_load_2_card(card) + FirstInitFlag = False + init_status = False card_type = card_type_detect(card) if card_type == 'Credo 100G': card_reset(card) - init_status = BE212.Cameo_credo100G(card) + init_status = BE218.cameo_main_100G(card) time.sleep(1) elif card_type == 'Credo 400G': card_reset(card) - init_status = BE214.Cameo_credo400G(card) + init_status = BE218.cameo_main_400G(card) time.sleep(1) logging.info( "Card [%d] [%s] %s" %(card,CardStatus[i],card_type) ) if init_status==True: @@ -266,4 +258,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_slot_power b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_slot_power index ef43649e63..47c240c457 100755 --- a/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_slot_power +++ b/platform/innovium/sonic-platform-modules-cameo/esc600-128q/utils/esc600_128q_slot_power @@ -16,7 +16,7 @@ def set_attr_value(attr_path,input_val): cmd='' if not os.path.isfile(attr_path): return - cmd = "echo 0x%x > %s" %(input_val,attr_path) + cmd = "echo %s > %s" %(input_val,attr_path) run_command(cmd) @@ -46,20 +46,18 @@ def main(card,power): print "Error: %s -c " %sys.argv[0] sys.exit(0) - filePath = '/sys/class/hwmon/hwmon2/device/ESC600_Module/module_enable' + filePath = '/sys/class/hwmon/hwmon2/device/ESC600_SYS/module_%d_enable'%card - card = card -1 + if os.path.exists(filePath): retval = get_attr_value(filePath) if retval == 'ERR': print "Fail to get value." - sys.exit(0) - value = int(retval[-4:],16) + sys.exit(0) if power == 'on': - value = value | (0x1 << card) + value = '1' elif power == 'off': - value = value ^ (0x1 << card) - + value = '0' #print "0x%x" %(value) set_attr_value(filePath,value) @@ -69,4 +67,4 @@ def main(card,power): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/setup.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/setup.py new file mode 100755 index 0000000000..0cdc947bf1 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='ESC601-32Q sonic platform API', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'esc601-32q/sonic_platform'}, +) \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/__init__.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/__init__.py new file mode 100755 index 0000000000..0b887c8c6b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/__init__.py @@ -0,0 +1 @@ +__all__ = ["platform", "chassis", "fan", "psu"] diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/chassis.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/chassis.py new file mode 100755 index 0000000000..110a57197e --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/chassis.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + import os + import time + import subprocess + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.platDev import PlatDev + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" + + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + _global_port_pres_dict = {} + + def __init__(self): + super(Chassis, self).__init__() + + # Initialize SKU name and Platform name + self.sku_name = self._get_sku_name() + self.platform_name = self._get_platform_name() + self.name = self.sku_name + + # get the device infomation of platform + self.platdev = PlatDev() + + #self._component_list = [] + #self._module_list = [] + #self._fan_drawer_list = [] + + self._eeprom = Eeprom() + # init component + for i in range(self.platdev.get_component_count()): + component = Component(i, self.platdev.get_component_name(i), self.platdev.get_component_descript(i)) + self._component_list.append(component) + # init fan list + if self.platdev.get_fan_support(): + fanlist = self.platdev.get_fan_list() + for index in range(0,len(fanlist)): + fan_name = fanlist[index] + for pos in range(0, self.platdev.get_fan_num_by_name(fan_name)): + fan = Fan( index, pos, [self.platdev.get_fan_sysfile_path_by_name(fan_name),'']) + self._fan_list.append(fan) + + # init psu list + psulist = self.platdev.get_psu_list() + for index in range(0, len(psulist)): + psu_name = psulist[index] + psu = Psu(index, [ self.platdev.get_psu_attr_path_by_name(psu_name), \ + self.platdev.get_psu_status_path_by_name(psu_name) ], \ + self.platdev.bmc_is_exist()) + self._psu_list.append(psu) + + # init thermal list + thermal_info_list = self.platdev.get_thermal_dev_info_all() + for index in range(0, len(thermal_info_list)): + if len(self.platdev.get_thermal_dev_tempidx_by_idx(index)) > 1: + for idx in self.platdev.get_thermal_dev_tempidx_by_idx(index): + thermal = Thermal(idx, self.platdev.get_thermal_dev_name_by_idx(index)+"-{}".format(idx), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(),\ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + else: + thermal = Thermal(1, self.platdev.get_thermal_dev_name_by_idx(index), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(), \ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + + # init sfp list + port_num = 1 + for sfpg_name in self.platdev.get_sfp_group_list(): + if self.platdev.get_sfp_group_type_by_name(sfpg_name) == 'QSFP28': + sfp_type = QSFP_TYPE + else: + sfp_type = SFP_TYPE + + for x in range(0,self.platdev.get_sfp_group_number_by_name(sfpg_name)): + eeprom_path_list = ['n/a','n/a'] + if self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] != 'n/a': + eeprom_path_list[0] = self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] + '/eeprom' + if os.path.exists(eeprom_path_list[0].replace("0050", "0051")): + eeprom_path_list[1] = eeprom_path_list[0].replace("0050", "0051") + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + sfp = Sfp(port_num, eeprom_path_list, sfp_type, self.platdev.get_sfp_ext_sysfile_list()) + port_num += 1 + self._sfp_list.append(sfp) + + self.init_global_port_presence() + + def _get_sku_name(self): + p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + + def _get_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.name + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr('') + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + # not support any hardware reboot, just return REBOOT_CAUSE_NON_HARDWARE + # to keep reboot cause as software reboot + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + ############################################## + # System LED methods + ############################################## + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + return False + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + raise NotImplementedError + + ############################################## + # Other methods + ############################################## + + def init_global_port_presence(self): + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + port_dict = {} + while True: + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, {'sfp':port_dict} + + time.sleep(1) + + + def sfp_debugger(self): + """ + Try to show all parameters read from eeprom with sfp methods + """ + print("SFP EEPROM data:") + for n in range(0, len(self._sfp_list)): + print("======SFP{}==TYPE {}====".format(n, self._sfp_list[n].sfp_type)) + print("get_transceiver_info:") + print(self._sfp_list[n].get_transceiver_info()) + print(" ") + + print("get_transceiver_threshold_info:") + print(self._sfp_list[n].get_transceiver_threshold_info()) + print(" ") + + print("get_transceiver_bulk_status:") + print(self._sfp_list[n].get_transceiver_bulk_status()) + print(" ") + + print("get_lpmode:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_lpmode())) + # set_lpmode + + print("get_power_override:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_power_override())) + + print("get_temperature:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_temperature())) + + print("get_voltage") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_voltage())) + + print("get_tx_bias") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_bias())) + + print("get_rx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_rx_power())) + + print("get_tx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_power())) + + + + + + + \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/component.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/component.py new file mode 100644 index 0000000000..ca353da682 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/component.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +######################################################################## +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + def __init__(self, idx,name,descript): + self.index = idx + self.name = name + self.description = descript + + def _get_cpld_register(self, syspath): + rv = 'ERR' + if (not os.path.isfile(syspath)): + return rv + # noinspection PyBroadException + try: + with open(syspath, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def _get_cpld_version(self, cpld_number): + cpld_version_reg = { + 1: "/sys/class/hwmon/hwmon2/device/ESC601_SYS/hw_version", + 2: "master_cpld_ver", + 3: "slave_cpld_ver" + } + + cpld_version = self._get_cpld_register(cpld_version_reg[cpld_number]) + + if cpld_version != 'ERR': + return cpld_version[-4:] + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + bios_ver = self._get_bios_version() + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index <= 3: + return self._get_cpld_version(self.index) + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/eeprom.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/eeprom.py new file mode 100755 index 0000000000..8740c4c11a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/eeprom.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +try: + import os + import sys + import re + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + # noinspection PyBroadException + try: + match = re.search( + '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) + if match is not None: + idx = match.group(1) + value = match.group(3).rstrip('\0') + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + err = self.read_eeprom_db() + if err: + # Failed to read EEPROM information from database. Read from cache file + pass + else: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + return self.__parse_output(decode_output) + + status = self.check_status() + if status < 'ok': + return {} + + if not os.path.exists(CACHE_ROOT): + # noinspection PyBroadException + try: + os.makedirs(CACHE_ROOT) + except Exception: + pass + + # + # only the eeprom classes that inherit from eeprom_base + # support caching. Others will work normally + # + # noinspection PyBroadException + try: + self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE)) + except Exception: + pass + + data = self.read_eeprom() + if data is None: + return 0 + # noinspection PyBroadException + try: + self.update_cache(data) + except Exception: + pass + + self.decode_eeprom(data) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(data) + if not is_valid: + return {} + + return self.__parse_output(decode_output) + + def get_eeprom(self): + return self._eeprom + + + def serial_number_str(self): + """ + Returns the serial number + """ + return self._eeprom.get('0x23', "Undefined.") + + def base_mac_addr(self, e): + """ + Returns the base mac address found in the system EEPROM + """ + return self._eeprom.get('0x24', "Undefined.") + + def modelstr(self): + """ + Returns the Model name + """ + return self._eeprom.get('0x28', "Undefined.") + + def part_number_str(self): + """ + Returns the part number + """ + return self._eeprom.get('0x22', "Undefined.") + + def revision_str(self): + """ + Returns the device revision + """ + return self._eeprom.get('0x26', "Undefined.") + + def serial_str(self): + return self._eeprom.get('0x2F', "Undefined.") + + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self._eeprom \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/fan.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/fan.py new file mode 100755 index 0000000000..1a4d8f8f8f --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/fan.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +FAN_POSITION_NAME = ["Front","Rear"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_index, position_index, attr_path, psu_fan = False): + # fan_index: the index of a fan module belongs to + # position_index : position of the fan in a fan module, 0 -> front, 1 -> rear, + # position_index : index of PSU belongs to if psu_fan is True, start from 0 + super(Fan, self).__init__() + self.index = fan_index + 1 + self.position = position_index + self.is_psu_fan = psu_fan + self.attr_path = attr_path[0] + + if psu_fan is True: + self.fan_name = "PSU{}_FAN{}".format(self.index, self.position+1) + self.speed_file = attr_path[1] + else: + self.fan_name = "FAN{}-{}".format(self.index, FAN_POSITION_NAME[self.position]) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_presence(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu_present') + if "PSU {} is not".format(self.index) in data: + return False + else: + return True + + data = self.__read_attr_file(self.attr_path + 'fan_present', self.index-1) + if data is not None : + search_str = "Fan {} is present".format(self.index) + if search_str in data: + return True + + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.fan_name + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + return self.FAN_DIRECTION_NOT_APPLICABLE + + def get_status(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu_status') + if "PSU {} is not".format(self.index) in data: + return False + else: + return True + + + data = self.__read_attr_file(self.attr_path + 'fan_status', self.index-1) + if data is not None : + search_str = "Fan {} is Good".format(self.index) + if search_str in data: + return True + + return False + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan is True and self.get_presence(): + if 'psu_fan_speed_1' in self.speed_file: #no bmc + speed = self.__read_attr_file( self.speed_file, 0) + if speed is not None: + return (int(speed)*100)//16000 + else: + return 0 + else: + line = self.__read_attr_file( self.speed_file, 3) + speed = line.split(' ') + if "FAN_SPEED" in speed: + return (int(speed[-1])*100)//16000 + else: + return 0 + if self.get_presence(): + data = self.__read_attr_file(self.attr_path + 'fan_speed_rpm', (self.index-1)*2 + self.position) + if data is not None: + for sdata in data.split(' '): + if sdata.isdigit(): + return (int(sdata)*100)//16000 + + return 0 + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + return self.get_speed() + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + """ + raise NotImplementedError + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platDev.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platDev.py new file mode 100755 index 0000000000..3e224a7bfd --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platDev.py @@ -0,0 +1,364 @@ +#!/usr/bin/env python + +try: + import os + import copy + import json + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("paltDev") +PLATFORM_INSTALL_INFO_FILE = "/etc/sonic/platform_install.json" +PLATFORM_NAME = "esc601_32q" +MAX_FAN_MODULE = 5 +MAX_FAN = 2 + +# THERMAL_SENSOR_LIST +# index is used to indicate the default temp{}_* under sysfile_path +# support_mask: 1:support 0:not support +# bit 0 : temperature (always 1) +# bit 1 : high threshold +# bit 2 : low threshold +# bit 3 : high critical threshold +# bit 4 : low critical threshold +# bit 7 : cpu internal sensor +# ext_sysfile_list: each specified path of each supported function, +# which not follows the (default) genernal naming rule +# [0] ext_temp_file : temperature +# [1] ext_high_thr : high threshold +# [2] ext_low_thr : low threshold +# [3] ext_high_cri_thr : high critical threshold +# [4] ext_low_cri_thr : low critical threshold + +THERMAL_SENSOR_LIST = [ + { + 'name': "pch_haswell", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon0/", + 'support_mask': 0x81, + 'ext_sysfile_list': None + }, + { + 'name': "CPU core temp", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon1/", + 'support_mask': 0x8B, + 'ext_sysfile_list': None + }, + { + 'name': "NCT7511Y(U73)", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon6/", + 'support_mask': 0x01, + 'ext_sysfile_list': {1:['bmc_sersor_1', 'temp_r_b_f_max', 'temp_r_b_f_min', 'temp_r_b_f_crit', 'temp_r_b_f_lcrit']} + }, + { + 'name': "G781(U94)", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon3/", + 'support_mask': 0x01, + 'ext_sysfile_list': {1:['bmc_sersor_2', 'temp_r_b_f_max', 'temp_r_b_f_min', 'temp_r_b_f_crit', 'temp_r_b_f_lcrit']} + }, + { + 'name': "G781(U4)", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon4/", + 'support_mask': 0x01, + 'ext_sysfile_list': {1:['bmc_sersor_3', 'temp_r_b_f_max', 'temp_r_b_f_min', 'temp_r_b_f_crit', 'temp_r_b_f_lcrit']} + }, + { + 'name': "G781(U34)", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon5/", + 'support_mask': 0x01, + 'ext_sysfile_list': {1:['bmc_sersor_4', 'temp_r_b_f_max', 'temp_r_b_f_min', 'temp_r_b_f_crit', 'temp_r_b_f_lcrit']} + } + + +] + +# PSU LIST +# ext_sysfile_list +# [0] : sysfile path for present +# [1] : sysfile path for status +# +PSU_LIST = ['PSU1', 'PSU2'] + +PSU_INFO = { + 'PSU1': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC601_PSU/" + }, + 'PSU2': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC601_PSU/" + } +} + +# SFP LIST +# +# +FAN_LIST = ['FAN1', 'FAN2', 'FAN3', 'FAN4', 'FAN5'] + +FAN_INFO = { + 'FAN1': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC601_FAN/' + }, + 'FAN2': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC601_FAN/' + }, + 'FAN3': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC601_FAN/' + }, + 'FAN4': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC601_FAN/' + }, + 'FAN5': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC601_FAN/' + } +} + + +# SFP LIST +# +# +# 0: QSFP +# 1: SFP +# sfp not port on 602 platform + +SFP_EXT_SYSFILE_LIST = ["/sys/class/hwmon/hwmon2/device/ESC601_QSFP/",""] + +SFP_GROUP_LIST = ['SFP-G01', 'SFP-G02', 'SFP-G03', 'SFP-G04'] + +PORT_NUM = 32 + +SFP_GROUP_INFO = { + "SFP-G01": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G02": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G03": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G04": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + } +} + +# +#Component +# ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " +# "modules (1-16)")], +# ["Slave-CPLD", "Used for managing QSFP modules (17-32)"] + +CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["System-CPLD", "Used for managing CPU board devices and power"] +] + +class PlatDev(): + def __init__(self): + self.plat_name = PLATFORM_NAME + self.psu_info = copy.deepcopy(PSU_INFO) + self.thermal_info = [] + self.fan_info = copy.deepcopy(FAN_INFO) + self.sfp_info = copy.deepcopy(SFP_GROUP_INFO) + self.device_install_info = dict() + self.sfp_install_info = dict() + + # get install info + self.get_dev_install_info() + # update path info with install info + # Item 1/2 not changed, append directly + self.thermal_info.append(THERMAL_SENSOR_LIST[0]) + self.thermal_info.append(THERMAL_SENSOR_LIST[1]) + + for i in range(2, len(THERMAL_SENSOR_LIST)): + install_info = self.device_install_info.get(THERMAL_SENSOR_LIST[i]['name']) + if install_info and install_info.get('hwmon_path'): + if self.bmc_is_exist(): + THERMAL_SENSOR_LIST[i]['sysfile_path'] = '/sys/class/hwmon/hwmon2/device/ESC601_BMC/' + else: + if install_info.get('hwmon_path') is None: + continue + THERMAL_SENSOR_LIST[i]['sysfile_path'] = install_info.get('hwmon_path') + self.thermal_info.append(THERMAL_SENSOR_LIST[i]) + + for psu_name in PSU_LIST: + install_info = self.device_install_info.get(psu_name) + if install_info: + if self.bmc_is_exist(): + self.psu_info[psu_name]['attr_path']= '/sys/class/hwmon/hwmon2/device/ESC601_PSU/' + else: + self.psu_info[psu_name]['attr_path'] = install_info.get('hwmon_path')+ '/device/' + + for sfp_group_name in SFP_GROUP_LIST: + install_info = self.sfp_install_info.get(sfp_group_name) + if install_info: + self.sfp_info[sfp_group_name]['paths'] = install_info.get('paths') + + def get_dev_install_info(self): + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + self.sfp_install_info = install_info[2] + self.device_install_info = install_info[1] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def bmc_is_exist(self): + bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESC601_BMC/bmc_present' + if os.path.exists(bmc_filePath): + value = self.__read_attr_file(bmc_filePath) + if value.find('not') < 0: + return True + else: + return False + else: + return False + + ######Componet method ##### + def get_component_count(self): + return len(CHASSIS_COMPONENTS) + + def get_component_name(self,idx): + return CHASSIS_COMPONENTS[idx][0] + + def get_component_descript(self,idx): + return CHASSIS_COMPONENTS[idx][1] + + ###### PSU method ###### + def get_psu_list(self): + return PSU_LIST + + def get_psu_info_all(self): + return self.psu_info + + def get_psu_info_by_name(self, name): + return self.psu_info.get(name) + + def get_psu_attr_path_by_name(self, name): + return self.psu_info[name].get('attr_path') + + def get_psu_status_path_by_name(self, name): + return self.psu_info[name].get('status_path') + + ###### Thermal method ###### + def get_thermal_dev_info_all(self): + return self.thermal_info + + def get_thermal_dev_name_by_idx(self, index): + return self.thermal_info[index].get('name') + + def get_thermal_dev_tempidx_by_idx(self, index): + return self.thermal_info[index].get('temp_index') + + def get_thermal_dev_sysfile_path_by_idx(self, index): + return self.thermal_info[index].get('sysfile_path') + + def get_thermal_dev_support_mask_by_idx(self, index): + return self.thermal_info[index].get('support_mask') + + def get_thermal_dev_ext_sysfile_list_by_idx(self, index): + return self.thermal_info[index].get('ext_sysfile_list') + + ###### Fan method ###### + def get_fan_support(self): + filePath = '/sys/class/hwmon/hwmon2/device/ESC601_SYS/cpld4_version' + if os.path.exists(filePath): + value = self.__read_attr_file(filePath) + if value == 'ERR': + return False + if int(value,16) >= 0x02: + return True + return False + + def get_fan_list(self): + return FAN_LIST + + def get_fan_info_all(self): + return self.fan_info + + def get_fan_info_by_name(self, name): + return self.fan_info.get(name) + + def get_fan_sysfile_path_by_name(self, name): + return self.fan_info[name].get('attr_path') + + def get_fan_is_draw_by_name(self, name): + return self.fan_info[name].get('isdraw') + + def get_fan_num_by_name(self, name): + return self.fan_info[name].get('fan_num') + + ###### SFP method ###### + def get_sfp_num(self): + return PORT_NUM + + def get_sfp_group_list(self): + return SFP_GROUP_LIST + + def get_sfp_group_info(self): + return self.sfp_info + + def get_sfp_group_info_by_name(self, name): + return self.sfp_info.get(name) + + def get_sfp_group_type_by_name(self, name): + return self.sfp_info[name].get('type') + + def get_sfp_group_path_by_name(self, name): + return self.sfp_info[name].get('paths') + + def get_sfp_group_number_by_name(self, name): + return self.sfp_info[name].get('number') + + def get_sfp_ext_sysfile_list(self): + return SFP_EXT_SYSFILE_LIST + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platform.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platform.py new file mode 100755 index 0000000000..2456a6f2e7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/platform.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/psu.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/psu.py new file mode 100755 index 0000000000..8842125d09 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/psu.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common.logger import Logger + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +# To do: should be defined in platDev +PSU_MAX_VOUT = 12.0 # voltage +PSU_MIN_VOUT = 3.3 # voltage +PSU_MAX_TEMP = 50.0 # C + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, index, info_list,is_bmc): + PsuBase.__init__(self) + self.index = index + self.is_bmc = is_bmc + self.attr_path = info_list[0] + self.status_path = info_list[1] + if is_bmc: + speed_file = self.attr_path + 'psu_module_{}'.format(index+1) + else: + speed_file = self.attr_path + 'psu_fan_speed_1' + + fan = Fan( index, 0, [self.status_path, speed_file ],True) + self._fan_list.append(fan) + self.psu_name = "PSU{}".format(self.index+1) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.psu_name + + def get_presence(self): + """ + Retrieves the presence status of power supply unit (PSU) defined + Returns: + bool: True if PSU is present, False if not + """ + data = self.__read_attr_file(self.status_path + 'psu_present') + if "PSU {} is not".format(self.index+1) in data: + return False + else: + return True + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + data = self.__read_attr_file(self.status_path + 'psu_status') + if "PSU {} is not".format(self.index+1) in data: + return False + else: + return True + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.is_bmc: + path_file = self.attr_path + 'psu_module_{}'.format(self.index+1) + line = self.__read_attr_file( path_file, 2) + vout = line.split(' ') + if "VOUT" in vout: + return float(vout[-1]) + else: + return False + else: + if self.get_presence(): + path_file = self.attr_path + "/psu_vout" + vout = self.__read_attr_file(path_file, 0) + if vout is not None: + return float(vout) / 1000 + return False + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + if self.is_bmc: + path_file = self.attr_path + 'psu_module_{}'.format(self.index+1) + line = self.__read_attr_file( path_file, 8) + iout = line.split(' ') + if "IOUT" in iout: + return float(iout[-1]) + else: + return 0 + else: + if self.get_presence(): + path_file = self.attr_path+"/psu_iout" + iout = self.__read_attr_file( path_file, 0) + if iout is not None: + return float(iout) / 1000 + + return False + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + if self.is_bmc: + path_file = self.attr_path + 'psu_module_{}'.format(self.index+1) + line = self.__read_attr_file( path_file, 6) + pout = line.split(' ') + if "POUT" in pout: + return float(pout[-1]) + else: + return 0 + else: + if self.get_presence(): + path_file = self.attr_path+"/psu_pout" + pout = self.__read_attr_file( path_file, 0) + if pout is not None: + return float(pout) / 1000000 + + return False + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + raise NotImplementedError + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.is_bmc: + path = self.attr_path + 'psu_module_{}'.format(self.index+1) + line = self.__read_attr_file( path, 4) + temp = line.split(' ') + if "TEMP_1" in temp: + return float(temp[-1]) + else: + return 0 + else: + if self.get_presence(): + path = self.attr_path+"/psu_temp_1" + temperature = self.__read_attr_file( path, 0) + if temperature is not None: + return float(temperature) / 1000 + return False + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return PSU_MAX_TEMP + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MAX_VOUT + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MIN_VOUT \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/sfp.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/sfp.py new file mode 100755 index 0000000000..3a2d1adb09 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/sfp.py @@ -0,0 +1,1179 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common.logger import Logger + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("sfp") + +############################################################################# +# +# SFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# ------------------------------------------------ 0 +# | Serial ID Defined by SFP MSA (96 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 95 +# | Vendor Specific (32 bytes) | +# |----------------------------------------------| 127 +# | Reserved, SFF-8079 (128 byte) | +# ------------------------------------------------ 255 +# +# 2 wire address 1010001x (A2h) (i2c 0x51) +# ------------------------------------------------ 0 +# | Alarm and Warning Threshold (56 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 55 +# | Cal Constants (40 bytes) | +# |----------------------------------------------| 95 +# | Real Time Diagnostic Interface(24 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 119 +# | Vendor Specific (7 bytes) | +# |----------------------------------------------| 126 +# | Page Select Byte (Optional) | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# Page 00h/01h +# |----------------------------------------------| 128 +# | User Writeable EEPROM (120 bytes) | +# |----------------------------------------------| 247 +# | Vendor Specific (8 bytes) | +# ------------------------------------------------ 255 +# Page 02h +# |----------------------------------------------| 128 +# | Control Function (128 bytes) | +# ------------------------------------------------ 255 +# Page 03h-7Fh +# |----------------------------------------------| 128 +# | Reserved (128 bytes) | +# ------------------------------------------------ 255 +# Page 80h-FFh +# |----------------------------------------------| 128 +# | Vendor Specific (128 bytes) | +# ------------------------------------------------ 255 +# +# ========================================================== +# QSFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# +# ------------------------------------------------ 0 +# | ID and status (3 bytes) | +# |----------------------------------------------| 2 +# | Interrupt Flags (19 bytes) | +# |----------------------------------------------| 21 +# | Module Monitors (12 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 33 +# | Channel Monitors (12 bytes) | +# |----------------------------------------------| 81 +# | Reserved (4 bytes) | +# |----------------------------------------------| 85 +# | Control (12 bytes) | <- get_power_override +# |----------------------------------------------| 97 +# | ~~~ | +# |----------------------------------------------| 126 +# | Page Select Byte | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# +# Page 00h +# |----------------------------------------------| 128 +# | Base ID Filed (64 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 191 +# | Extended ID (32 bytes) | +# |----------------------------------------------| 223 +# | Vendor Specific ID (8 bytes) | +# ------------------------------------------------ 255 +# Page 01h (optional) +# |----------------------------------------------| 128 +# | ~~~~ (128 bytes) | +# ------------------------------------------------ 255 +# Page 02h (optional) +# |----------------------------------------------| 128 +# | User EEPROM Data (128 bytes) | +# ------------------------------------------------ 255 + +# Page 03h (optional on QSFP28) +# |----------------------------------------------| 128 +# | Module Threshold (48 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 175 +# | Channel Threshold (48 bytes) | +# |----------------------------------------------| 223 +# | Reserved (2 bytes) | +# |----------------------------------------------| 225 +# | Vendor Specific Channel Controls (16 bytes) | +# |----------------------------------------------| 241 +# | Channel Monitor Masks (12 bytes) | +# |----------------------------------------------| 253 +# | Reserved (2 bytes) | +# ------------------------------------------------ 255 +# +# +# +# +# +# +# +# +############################################################################# + +# function eunm +SFP_GET_PRESENCE=0 +SFP_RESET =1 +SFP_GET_LOW_POWER_MODE=2 +SFP_SET_LOW_POWER_MODE=3 + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] + +# index for A0H, A2H sysfs file path +INDEX_A0H = 0 +INDEX_A2H = 1 + +# offset/width definition +OFFSET = 0 +WIDTH = 1 + +QSFP_UPPER_MEMORY_PAGE00_OFFSET = 128 +QSFP_UPPER_MEMORY_PAGE03_OFFSET = 512 + +SFP_A0H_OFFSET = 0 +SFP_A2H_OFFSET = 0 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 +ID_FIELD_WIDTH = 92 + +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 1 +QSFP_INTERFACE_BULK_WIDTH = 20 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 5], + 'DEVICE_TECH': [19, 1], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 2], + 'WAVELENGTH': [58, 2], + 'WAVELENGTH_TOLERANCE': [60, 2], + 'MAX_CASE_TEMP': [62, 1], + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 4], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [22, 2], + 'VOLTAGE': [26, 2], + 'CHANNEL_MON': [34, 24], + 'CONTROL': [86, 12], + # PAGE03 + 'MODULE_THRESHOLD': [0, 24], + 'CHANNEL_THRESHOLD': [50, 24] +} +SFP_INTERFACE_BULK_WIDTH = 21 +SFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 6], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 4], + 'WAVELENGTH': [60, 2], + # UNALLOCATED WIDDTH: 1 + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 2], + 'BITRATE_MAX': [66, 1], + # BITRATE_MAX ?? + 'BITRATE_MAX_1': [67, 1], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [96, 2], + 'VOLTAGE': [98, 2], + 'CHANNEL_MON': [100, 6], + 'MODULE_THRESHOLD': [0, 40] +} + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes','FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia','FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + def __init__(self, index, eeprom_path_list, sfp_type, ext_sysfile_list=None): + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + # ext_sysfile_list[0]: QSFP path + # ext_sysfile_list[1]: SFP path + self.index = index + self.eeprom_path_list = eeprom_path_list + #self._get_sfp_type(sfp_type) + self.sfp_type = sfp_type + if self.sfp_type == QSFP_TYPE: + self.present_file = ext_sysfile_list[0]+ 'QSFP_present' + self.reset_file = ext_sysfile_list[0]+ 'QSFP_reset' + self.lp_file = ext_sysfile_list[0]+ 'QSFP_low_power_{}'.format(self.index) + else: + self.present_file = ext_sysfile_list[1]+ 'sfp{}_present'.format(self.index) + self.reset_file = None + self.lp_file = None + + def _get_sfp_type(self, sfp_type): + ty = self._read_eeprom_bytes(SFP_ID_FIELDS['TYPE'][OFFSET], SFP_ID_FIELDS['TYPE'][WIDTH], INDEX_A0H) + if ty is not None: + if ty[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + if ty[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + else: + self.sfp_type = sfp_type + logger.log_warning("Unreganized sfp type of module {} . unsupported, treated as specified type {}".format(self.index, sfp_type)) + else: + self.sfp_type = sfp_type + + + def _read_eeprom_bytes(self, offset, num_bytes, path_idx): + eeprom_raw = [] + + eeprom = None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom = open(self.eeprom_path_list[path_idx], mode="rb", buffering=0) + eeprom.seek(offset) + raw_data = eeprom.read(num_bytes) + for nb in range(0, len(raw_data)): + eeprom_raw[nb] = hex(ord(raw_data[nb]))[2:].zfill(2) + except Exception as ex: + logger.log_error("Fail to read eeprom {}".format(self.eeprom_path_list[path_idx])) + logger.log_error(" {}".format(ex)) + if eeprom is not None: + eeprom.close() + return None + + return eeprom_raw + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def __write_attr_file(self, filepath, data): + try: + with open(filepath,'w') as fd: + return fd.write(data) + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + return 0 + + def get_presence(self): + if self.present_file is not None: + data = self.__read_attr_file(self.present_file, self.index-1) + if data is not None: + if "not" in data: + return False + else: + return True + return False + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return '-inf' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == QSFP_TYPE: + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self._read_eeprom_bytes((offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self._read_eeprom_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH,INDEX_A0H) + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + qspf_dom_capability = int(qsfp_dom_capability_raw[0], 16) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qspf_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qspf_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qspf_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + qsfp_option_value_raw = self._read_eeprom_bytes(QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH,INDEX_A0H) + if qsfp_option_value_raw is not None: + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + self.optional_capability = sfpd_obj.parse_option_params(qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = self.optional_capability['data']['TxDisable']['value'] == 'On' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + elif self.sfp_type == SFP_TYPE: + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self._read_eeprom_bytes(XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = (int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + transceiver_info_dict_keys = [ + 'type', 'hardware_rev', + 'serial', 'manufacturer', + 'model', 'connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui','application_advertisement'] + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE00_OFFSET # upper memory map: Page 00h + Id_field = QSFP_ID_FIELDS + info_bulk_width = QSFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8436InterfaceId() + + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A0H_OFFSET # lower memory map: A0h (SFP i2c 0x50) + Id_field = SFP_ID_FIELDS + info_bulk_width = SFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8472InterfaceId() + else: + logger.log_error("Unsupported sfp type") + return None + + if sfpi_obj is None: + logger.log_error("sfpi_obj create fail") + return None + + # read Base ID field + sfp_interface_bulk_raw = self._read_eeprom_bytes(field_offset, ID_FIELD_WIDTH, INDEX_A0H) + if sfp_interface_bulk_raw is None: + logger.log_error(" Fail to read BaseID field of module {}".format(self.index+1)) + return None + + start = 0 + end = start + info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_NAME'][OFFSET] + end = start + Id_field['VENDOR_NAME'][WIDTH] + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_PN'][OFFSET] + end = start + Id_field['VENDOR_PN'][WIDTH] + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_REV'][OFFSET] + end = start + Id_field['VENDOR_REV'][WIDTH] + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_SN'][OFFSET] + end = start + Id_field['VENDOR_SN'][WIDTH] + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_OUI'][OFFSET] + end = start + Id_field['VENDOR_OUI'][WIDTH] + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_DATE'][OFFSET] + end = start + Id_field['VENDOR_DATE'][WIDTH] + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + + compliance_code_dict = {} + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = [ + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] + transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] + transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] + transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] + transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] + transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] + transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num(transceiver_dom_info_dict[key]) + + return transceiver_dom_info_dict + + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + dom_info_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + + transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE03_OFFSET # uppper memory map: Page 03h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return transceiver_dom_threshold_info_dict + + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['MODULE_THRESHOLD'][OFFSET], Id_field['MODULE_THRESHOLD'][WIDTH], path_idx) + + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_THRESHOLD'][OFFSET], Id_field['CHANNEL_THRESHOLD'][WIDTH], path_idx) + + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + else: # SFP_TYPE + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + raise NotImplementedError + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + raise NotImplementedError + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + raise NotImplementedError + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + raise NotImplementedError + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + raise NotImplementedError + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.lp_file is not None: + data = self.__read_attr_file(self.lp_file, 0) + if data is not None: + if "ON" in data: + return True + + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + + if self.sfp_type == QSFP_TYPE: + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_bytes(Id_field['CONTROL'][OFFSET], Id_field['CONTROL'][WIDTH], INDEX_A0H) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + + return False + else: + return NotImplementedError + + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + path_idx = INDEX_A0H + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + + return None + + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + path_idx = INDEX_A0H + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + volt = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return volt + + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + path_idx = INDEX_A0H + tx_bias_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value'])) + + return tx_bias_list + + return None + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + path_idx = INDEX_A0H + rx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value'])) + + return rx_power_list + + return None + + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + path_idx = INDEX_A0H + tx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value'])) + + return tx_power_list + + return None + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + if self.reset_file is not None: + ret = self.__write_attr_file(self.reset_file, str(self.index+1)) + if ret != 0: + return True + + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.lp_file is not None: + if lpmode is True: + ret = self.__write_attr_file(self.lp_file, "1") + else: + ret = self.__write_attr_file(self.lp_file, "0") + if ret != 0: + return True + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + return False + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/thermal.py b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/thermal.py new file mode 100755 index 0000000000..2e2b4fed78 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc601-32q/sonic_platform/thermal.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +logger = Logger("thermal") +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + def __init__(self, index, name, sysfile_path, is_bmc, support_mask=0x1, ext_sysfile_list=None): + # index is used to indicate the temp{} under sffile_path + # support_mask: 1:support 0:not support + # bit 0 : temperature (always 1) + # bit 1 : high threshold + # bit 2 : low threshold + # bit 3 : high critical threshold + # bit 4 : low critical threshold + # bit 7 : cpu internal sensor + # ext_sysfile_list: each specified path of each supported function, + # which not follows the general naming rule + + self.index = index + self.name = name + self.filepath = sysfile_path + self.support_mask = support_mask + self.is_bmc = is_bmc + + self.temperature_file = None + self.high_thershold_file = None + self.low_threshold_file = None + self.high_critical_file = None + self.low_critical_file = None + + if sysfile_path is None: + return + + if self.is_bmc ==False or support_mask & 0x80 == 0x80: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + "/temp{}_input".format(self.index) + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + "/temp{}_max".format(self.index) + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + "/temp{}_min".format(self.index) + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + "/temp{}_crit".format(self.index) + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + "/temp{}_lcrit".format(self.index) + elif self.is_bmc and ext_sysfile_list is not None: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + ext_sysfile_list[self.index][0] + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + ext_sysfile_list[self.index][1] + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + ext_sysfile_list[self.index][2] + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][3] + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][4] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.name + + def get_presence(self): + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.temperature_file is not None: + temp = self.__read_attr_file( self.temperature_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_thershold_file is not None: + temp = self.__read_attr_file( self.high_thershold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_threshold_file is not None: + temp = self.__read_attr_file( self.low_threshold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_file is not None: + temp = self.__read_attr_file( self.high_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_critical_file is not None: + temp = self.__read_attr_file( self.low_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.c b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.c index ae830e33fc..2c9faba733 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.c +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.c @@ -197,11 +197,11 @@ ssize_t psu_vout_get(struct device *dev, struct device_attribute *da, char *buf) switch(attr->index) { case PSU1_VOUT: - u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VOMDE_REG); + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_VOUT_REG); break; case PSU2_VOUT: - u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VOMDE_REG); + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_VOUT_REG); break; } @@ -417,7 +417,7 @@ ssize_t psu_pin_get(struct device *dev, struct device_attribute *da, char *buf) ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char *buf) { u16 u16_val = 0; - char model[2]; + char model[I2C_SMBUS_BLOCK_MAX] = {0}; struct sensor_device_attribute *attr = to_sensor_dev_attr(da); sprintf(buf, ""); @@ -426,19 +426,21 @@ ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char switch(attr->index) { case PSU1_MFR_MODEL: - u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_MFR_MODEL_REG); + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_1_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); break; case PSU2_MFR_MODEL: - u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_MFR_MODEL_REG); + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_2_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); break; } - if(u16_val == 0xffff || u16_val == -1) + if(u16_val != I2C_SMBUS_BLOCK_MAX) { - return sprintf(buf, "%s0\n", buf); + return sprintf(buf, "%sERROR\n", buf); } - model[0] = u16_val >> 8; - model[1] = u16_val; - sprintf(buf, "%s%c%c\n", buf, model[0], model[1]); + if (model[1] < 0x20 || model[1] > 0x7f) + { + return sprintf(buf, "%sERROR\n", buf); + } + sprintf(buf, "%s%s", buf, model); } else { @@ -495,11 +497,11 @@ ssize_t psu_vmode_get(struct device *dev, struct device_attribute *da, char *buf { switch(attr->index) { - case PSU1_VOMDE: - u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VOMDE_REG); + case PSU1_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); break; - case PSU2_VOMDE: - u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VOMDE_REG); + case PSU2_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); break; } if(u16_vmode == 0xffff || u16_vmode == -1) diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.h b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.h index 6164179b2a..2290699ff9 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.h +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-power.h @@ -11,7 +11,7 @@ #define PSU_1_PIN_REG 0x57 #define PSU_1_MFR_MODEL_REG 0x58 #define PSU_1_MFR_IOUT_MAX_REG 0x59 -#define PSU_1_VOMDE_REG 0x5a +#define PSU_1_VMODE_REG 0x5a #define PSU_2_VIN_REG 0x60 #define PSU_2_IIN_REG 0x61 #define PSU_2_VOUT_REG 0x62 @@ -22,7 +22,7 @@ #define PSU_2_PIN_REG 0x67 #define PSU_2_MFR_MODEL_REG 0x68 #define PSU_2_MFR_IOUT_MAX_REG 0x69 -#define PSU_2_VOMDE_REG 0x6a +#define PSU_2_VMODE_REG 0x6a #define DC_CHIP_6E_P0_VOUT_REG 0x90 #define DC_CHIP_6E_P0_IOUT_REG 0x91 #define DC_CHIP_6E_P0_POUT_REG 0x92 diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-sys.c b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-sys.c index 0556a5377b..dca74653f2 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-sys.c +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q-sys.c @@ -32,12 +32,16 @@ ssize_t cpld_hw_ver_get(struct device *dev, struct device_attribute *da, char *b { status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, CPLD_VER_REG); } + break; case 30: status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, CPLD_VER_REG); + break; case 31: status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, CPLD_VER_REG); + break; case 32: status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, CPLD_VER_REG); + break; } if(status < 0) { @@ -187,7 +191,7 @@ ssize_t usb_enable_get(struct device *dev, struct device_attribute *da, char *bu sprintf(buf, ""); if (attr->index == USB_EN) { - if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG) & BIT_2_MASK) + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG) & BIT_1_MASK) { sprintf(buf, "%s%d\n", buf, ENABLE); } diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.h b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.h index 48e1faf2bd..3d9b7c8556 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.h +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.h @@ -12,7 +12,7 @@ #include #include -#define DRIVER_VERSION "1.0.1" +#define DRIVER_VERSION "1.0.3" struct i2c_adap { int nr; @@ -223,7 +223,7 @@ enum Cameo_i2c_sysfs_attributes PSU1_PIN, PSU1_MFR_MODEL, PSU1_MFR_IOUT_MAX, - PSU1_VOMDE, + PSU1_VMODE, PSU2_VIN, PSU2_IIN, PSU2_VOUT, @@ -234,7 +234,7 @@ enum Cameo_i2c_sysfs_attributes PSU2_PIN, PSU2_MFR_MODEL, PSU2_MFR_IOUT_MAX, - PSU2_VOMDE, + PSU2_VMODE, DC6E_P0_VOUT, DC6E_P0_IOUT, DC6E_P0_POUT, @@ -515,7 +515,7 @@ static SENSOR_DEVICE_ATTR(psu1_pout , S_IRUGO , psu_pout_g static SENSOR_DEVICE_ATTR(psu1_pin , S_IRUGO , psu_pin_get , NULL , PSU1_PIN); static SENSOR_DEVICE_ATTR(psu1_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU1_MFR_MODEL); static SENSOR_DEVICE_ATTR(psu1_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU1_MFR_IOUT_MAX); -static SENSOR_DEVICE_ATTR(psu1_vomde , S_IRUGO , psu_vmode_get , NULL , PSU1_VOMDE); +static SENSOR_DEVICE_ATTR(psu1_vmode , S_IRUGO , psu_vmode_get , NULL , PSU1_VMODE); static SENSOR_DEVICE_ATTR(psu2_vin , S_IRUGO , psu_vin_get , NULL , PSU2_VIN); static SENSOR_DEVICE_ATTR(psu2_iin , S_IRUGO , psu_iin_get , NULL , PSU2_IIN); static SENSOR_DEVICE_ATTR(psu2_vout , S_IRUGO , psu_vout_get , NULL , PSU2_VOUT); @@ -526,7 +526,7 @@ static SENSOR_DEVICE_ATTR(psu2_pout , S_IRUGO , psu_pout_g static SENSOR_DEVICE_ATTR(psu2_pin , S_IRUGO , psu_pin_get , NULL , PSU2_PIN); static SENSOR_DEVICE_ATTR(psu2_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU2_MFR_MODEL); static SENSOR_DEVICE_ATTR(psu2_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU2_MFR_IOUT_MAX); -static SENSOR_DEVICE_ATTR(psu2_vomde , S_IRUGO , psu_vmode_get , NULL , PSU2_VOMDE); +static SENSOR_DEVICE_ATTR(psu2_vmode , S_IRUGO , psu_vmode_get , NULL , PSU2_VMODE); static SENSOR_DEVICE_ATTR(dc6e_p0_vout , S_IRUGO , dc_vout_get , NULL , DC6E_P0_VOUT); static SENSOR_DEVICE_ATTR(dc6e_p0_iout , S_IRUGO , dc_iout_get , NULL , DC6E_P0_IOUT); static SENSOR_DEVICE_ATTR(dc6e_p0_pout , S_IRUGO , dc_pout_get , NULL , DC6E_P0_POUT); @@ -825,7 +825,7 @@ static struct attribute *ESC602_POWER_attributes[] = &sensor_dev_attr_psu1_pin.dev_attr.attr, &sensor_dev_attr_psu1_mfr_model.dev_attr.attr, &sensor_dev_attr_psu1_mfr_iout_max.dev_attr.attr, - &sensor_dev_attr_psu1_vomde.dev_attr.attr, + &sensor_dev_attr_psu1_vmode.dev_attr.attr, &sensor_dev_attr_psu2_vin.dev_attr.attr, &sensor_dev_attr_psu2_iin.dev_attr.attr, &sensor_dev_attr_psu2_vout.dev_attr.attr, @@ -836,7 +836,7 @@ static struct attribute *ESC602_POWER_attributes[] = &sensor_dev_attr_psu2_pin.dev_attr.attr, &sensor_dev_attr_psu2_mfr_model.dev_attr.attr, &sensor_dev_attr_psu2_mfr_iout_max.dev_attr.attr, - &sensor_dev_attr_psu2_vomde.dev_attr.attr, + &sensor_dev_attr_psu2_vmode.dev_attr.attr, &sensor_dev_attr_dc6e_p0_vout.dev_attr.attr, &sensor_dev_attr_dc6e_p0_iout.dev_attr.attr, &sensor_dev_attr_dc6e_p0_pout.dev_attr.attr, diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.txt b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.txt deleted file mode 100644 index 0e423a8abf..0000000000 --- a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/modules/x86-64-cameo-esc602-32q.txt +++ /dev/null @@ -1,38 +0,0 @@ -/*------------------------ Software Release Note ------------------------------ - * - * This document is the Standard Format for Software Release Note. - * - *----------------------------------------------------------------------------*/ - -******************************************************************************** -*[PRODUCT NAME] : ESQC610 56SQ * -******************************************************************************** -_______________________________________________________________________________ - RELEASE VERSION : 1.0 - RELEASE DATE : 2020/08/18 - RELEASE BY : Weian Tien -_______________________________________________________________________________ - -1. New Features: -------------- -Initial version for ESC602-32Q -------------- - -2. Bug Fixed: -------------- -N/A -------------- - -3. Known Issue: -------------- -N/A -------------- - -4. Changed (Spec Changed info): -------------- -N/A -------------- - -Note: -------------- -_____________________________________[END]______________________________________ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/setup.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/setup.py new file mode 100755 index 0000000000..a93f769c66 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='ESC602-32Q sonic platform API', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'esc602-32q/sonic_platform'}, +) \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/__init__.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/__init__.py new file mode 100755 index 0000000000..0b887c8c6b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/__init__.py @@ -0,0 +1 @@ +__all__ = ["platform", "chassis", "fan", "psu"] diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/chassis.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/chassis.py new file mode 100755 index 0000000000..1fb378b51b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/chassis.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + import os + import time + import subprocess + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.platDev import PlatDev + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" + + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + _global_port_pres_dict = {} + + def __init__(self): + super(Chassis, self).__init__() + + # Initialize SKU name and Platform name + self.sku_name = self._get_sku_name() + self.platform_name = self._get_platform_name() + self.name = self.sku_name + + # get the device infomation of platform + self.platdev = PlatDev() + + #self._component_list = [] + #self._module_list = [] + #self._fan_drawer_list = [] + + self._eeprom = Eeprom() + # init component + for i in range(self.platdev.get_component_count()): + component = Component(i, self.platdev.get_component_name(i), self.platdev.get_component_descript(i)) + self._component_list.append(component) + # init fan list + if self.platdev.get_fan_support(): + fanlist = self.platdev.get_fan_list() + for index in range(0,len(fanlist)): + fan_name = fanlist[index] + for pos in range(0, self.platdev.get_fan_num_by_name(fan_name)): + fan = Fan( index, pos, [self.platdev.get_fan_sysfile_path_by_name(fan_name),'']) + self._fan_list.append(fan) + + # init psu list + psulist = self.platdev.get_psu_list() + for index in range(0, len(psulist)): + psu_name = psulist[index] + psu = Psu(index, [ self.platdev.get_psu_attr_path_by_name(psu_name), \ + self.platdev.get_psu_status_path_by_name(psu_name) ], \ + self.platdev.bmc_is_exist()) + self._psu_list.append(psu) + + # init thermal list + thermal_info_list = self.platdev.get_thermal_dev_info_all() + for index in range(0, len(thermal_info_list)): + if len(self.platdev.get_thermal_dev_tempidx_by_idx(index)) > 1: + for idx in self.platdev.get_thermal_dev_tempidx_by_idx(index): + thermal = Thermal(idx, self.platdev.get_thermal_dev_name_by_idx(index)+"-{}".format(idx), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(),\ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + else: + thermal = Thermal(1, self.platdev.get_thermal_dev_name_by_idx(index), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(), \ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + + # init sfp list + port_num = 1 + for sfpg_name in self.platdev.get_sfp_group_list(): + if self.platdev.get_sfp_group_type_by_name(sfpg_name) == 'QSFP28': + sfp_type = QSFP_TYPE + else: + sfp_type = SFP_TYPE + + for x in range(0,self.platdev.get_sfp_group_number_by_name(sfpg_name)): + eeprom_path_list = ['n/a','n/a'] + if self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] != 'n/a': + eeprom_path_list[0] = self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] + '/eeprom' + if os.path.exists(eeprom_path_list[0].replace("0050", "0051")): + eeprom_path_list[1] = eeprom_path_list[0].replace("0050", "0051") + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + sfp = Sfp(port_num, eeprom_path_list, sfp_type, self.platdev.get_sfp_ext_sysfile_list()) + port_num += 1 + self._sfp_list.append(sfp) + + self.init_global_port_presence() + + def _get_sku_name(self): + p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + + def _get_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.name + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr('') + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + # not support any hardware reboot, just return REBOOT_CAUSE_NON_HARDWARE + # to keep reboot cause as software reboot + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + ############################################## + # System LED methods + ############################################## + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + return False + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + raise NotImplementedError + + ############################################## + # Other methods + ############################################## + + def init_global_port_presence(self): + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + port_dict = {} + while True: + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, {'sfp':port_dict} + + time.sleep(1) + + + def sfp_debugger(self): + """ + Try to show all parameters read from eeprom with sfp methods + """ + print("SFP EEPROM data:") + for n in range(0, len(self._sfp_list)): + print("======SFP{}==TYPE {}====".format(n, self._sfp_list[n].sfp_type)) + print("get_transceiver_info:") + print(self._sfp_list[n].get_transceiver_info()) + print(" ") + + print("get_transceiver_threshold_info:") + print(self._sfp_list[n].get_transceiver_threshold_info()) + print(" ") + + print("get_transceiver_bulk_status:") + print(self._sfp_list[n].get_transceiver_bulk_status()) + print(" ") + + print("get_lpmode:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_lpmode())) + # set_lpmode + + print("get_power_override:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_power_override())) + + print("get_temperature:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_temperature())) + + print("get_voltage") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_voltage())) + + print("get_tx_bias") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_bias())) + + print("get_rx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_rx_power())) + + print("get_tx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_power())) + + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/component.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/component.py new file mode 100755 index 0000000000..0aa79383ac --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/component.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +######################################################################## +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + def __init__(self, idx,name,descript): + self.index = idx + self.name = name + self.description = descript + + def _get_cpld_register(self, syspath): + rv = 'ERR' + if (not os.path.isfile(syspath)): + return rv + # noinspection PyBroadException + try: + with open(syspath, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def _get_cpld_version(self, cpld_number): + cpld_version_reg = { + 1: "/sys/class/hwmon/hwmon2/device/ESC602_SYS/cpld_30_ver", + 2: "master_cpld_ver", + 3: "slave_cpld_ver" + } + + cpld_version = self._get_cpld_register(cpld_version_reg[cpld_number]) + + if cpld_version != 'ERR': + return cpld_version[-4:] + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + bios_ver = self._get_bios_version() + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index <= 3: + return self._get_cpld_version(self.index) + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/eeprom.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/eeprom.py new file mode 100755 index 0000000000..8740c4c11a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/eeprom.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +try: + import os + import sys + import re + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + # noinspection PyBroadException + try: + match = re.search( + '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) + if match is not None: + idx = match.group(1) + value = match.group(3).rstrip('\0') + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + err = self.read_eeprom_db() + if err: + # Failed to read EEPROM information from database. Read from cache file + pass + else: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + return self.__parse_output(decode_output) + + status = self.check_status() + if status < 'ok': + return {} + + if not os.path.exists(CACHE_ROOT): + # noinspection PyBroadException + try: + os.makedirs(CACHE_ROOT) + except Exception: + pass + + # + # only the eeprom classes that inherit from eeprom_base + # support caching. Others will work normally + # + # noinspection PyBroadException + try: + self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE)) + except Exception: + pass + + data = self.read_eeprom() + if data is None: + return 0 + # noinspection PyBroadException + try: + self.update_cache(data) + except Exception: + pass + + self.decode_eeprom(data) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(data) + if not is_valid: + return {} + + return self.__parse_output(decode_output) + + def get_eeprom(self): + return self._eeprom + + + def serial_number_str(self): + """ + Returns the serial number + """ + return self._eeprom.get('0x23', "Undefined.") + + def base_mac_addr(self, e): + """ + Returns the base mac address found in the system EEPROM + """ + return self._eeprom.get('0x24', "Undefined.") + + def modelstr(self): + """ + Returns the Model name + """ + return self._eeprom.get('0x28', "Undefined.") + + def part_number_str(self): + """ + Returns the part number + """ + return self._eeprom.get('0x22', "Undefined.") + + def revision_str(self): + """ + Returns the device revision + """ + return self._eeprom.get('0x26', "Undefined.") + + def serial_str(self): + return self._eeprom.get('0x2F', "Undefined.") + + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self._eeprom \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/fan.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/fan.py new file mode 100755 index 0000000000..278b5cb998 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/fan.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +FAN_POSITION_NAME = ["Front","Rear"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_index, position_index, attr_path, psu_fan = False): + # fan_index: the index of a fan module belongs to + # position_index : position of the fan in a fan module, 0 -> front, 1 -> rear, + # position_index : index of PSU belongs to if psu_fan is True, start from 0 + super(Fan, self).__init__() + self.index = fan_index + 1 + self.position = position_index + self.is_psu_fan = psu_fan + self.attr_path = attr_path[0] + + if psu_fan is True: + self.fan_name = "PSU{}_FAN{}".format(self.index, self.position+1) + self.speed_file = attr_path[1] + else: + self.fan_name = "FAN{}-{}".format(self.index, FAN_POSITION_NAME[self.position]) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_presence(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_prnt'.format(self.index)) + if data == '1': + return True + else: + return False + ret = self.__read_attr_file(self.attr_path + 'fan{}_present'.format(self.index)) + if ret == '1': + return True + elif ret == '0': + return False + else: + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.fan_name + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + return self.FAN_DIRECTION_NOT_APPLICABLE + + def get_status(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_good'.format(self.index)) + if data == '1': + return True + else: + return False + data = self.__read_attr_file(self.attr_path + 'fan{}_stat'.format(self.index)) + if data == '1': + return True + elif data == '0': + return False + else: + return False + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan is True and self.get_presence(): + speed = self.__read_attr_file( self.speed_file, 0) + if speed is not None: + return (int(speed)*100)//16000 + else: + return 0 + + if self.get_presence(): + if self.position ==0: + speed_file =self.attr_path + 'fan{}_front_rpm'.format(self.index) + else: + speed_file =self.attr_path + 'fan{}_rear_rpm'.format(self.index) + data = self.__read_attr_file(speed_file) + if data is not None: + for sdata in data.split(' '): + if sdata.isdigit(): + return (int(sdata)*100)//18000 + return 0 + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + return self.get_speed() + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + """ + raise NotImplementedError + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platDev.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platDev.py new file mode 100755 index 0000000000..c5d0fe3087 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platDev.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python + +try: + import os + import copy + import json + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("paltDev") +PLATFORM_INSTALL_INFO_FILE = "/etc/sonic/platform_install.json" +PLATFORM_NAME = "esc602_32q" +MAX_FAN_MODULE = 5 +MAX_FAN = 2 + +# THERMAL_SENSOR_LIST +# index is used to indicate the default temp{}_* under sysfile_path +# support_mask: 1:support 0:not support +# bit 0 : temperature (always 1) +# bit 1 : high threshold +# bit 2 : low threshold +# bit 3 : high critical threshold +# bit 4 : low critical threshold +# bit 7 : cpu internal sensor +# ext_sysfile_list: each specified path of each supported function, +# which not follows the (default) genernal naming rule +# [0] ext_temp_file : temperature +# [1] ext_high_thr : high threshold +# [2] ext_low_thr : low threshold +# [3] ext_high_cri_thr : high critical threshold +# [4] ext_low_cri_thr : low critical threshold + +THERMAL_SENSOR_LIST = [ + { + 'name': "pch_haswell", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon0/", + 'support_mask': 0x81, + 'ext_sysfile_list': None + }, + { + 'name': "CPU core temp", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon1/", + 'support_mask': 0x8B, + 'ext_sysfile_list': None + }, + { + 'name': "NCT7511Y(U73)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon6/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_r_b_f', 'temp_r_b_f_max', 'temp_r_b_f_min', 'temp_r_b_f_crit', 'temp_r_b_f_lcrit'], + 2:['temp_r_b_b', 'temp_r_b_b_max', 'temp_r_b_b_min', 'temp_r_b_b_crit', 'temp_r_b_b_lcrit']} + }, + { + 'name': "G781(U94)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon3/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_l_b_f', 'temp_l_b_f_max', 'temp_l_b_f_min', 'temp_l_b_f_crit', 'temp_l_b_f_lcrit'], + 2:['temp_l_b_b', 'temp_l_b_b_max', 'temp_l_b_b_min', 'temp_l_b_b_crit', 'temp_l_b_b_lcrit']} + }, + { + 'name': "G781(U34)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon5/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_r_t_f', 'temp_r_t_f_max', 'temp_r_t_f_min', 'temp_r_t_f_crit', 'temp_r_t_f_lcrit'], + 2:['temp_r_t_b', 'temp_r_t_b_max', 'temp_r_t_b_min', 'temp_r_t_b_crit', 'temp_r_t_b_lcrit']} + }, + { + 'name': "G781(U4)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon4/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_l_t_f', 'temp_l_t_f_max', 'temp_l_t_f_min', 'temp_l_t_f_crit', 'temp_l_t_f_lcrit'], + 2:['temp_l_t_b', 'temp_l_t_b_max', 'temp_l_t_b_min', 'temp_l_t_b_crit', 'temp_l_t_b_lcrit']} + } +] + +# PSU LIST +# ext_sysfile_list +# [0] : sysfile path for present +# [1] : sysfile path for status +# +PSU_LIST = ['PSU1', 'PSU2'] + +PSU_INFO = { + 'PSU1': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC602_POWER/" + }, + 'PSU2': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESC602_POWER/" + } +} + +# SFP LIST +# +# +FAN_LIST = ['FAN1', 'FAN2', 'FAN3', 'FAN4', 'FAN5'] + +FAN_INFO = { + 'FAN1': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC602_FAN/' + }, + 'FAN2': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC602_FAN/' + }, + 'FAN3': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC602_FAN/' + }, + 'FAN4': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC602_FAN/' + }, + 'FAN5': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESC602_FAN/' + } +} + + +# SFP LIST +# +# +# 0: QSFP +# 1: SFP +# sfp not port on 602 platform + +SFP_EXT_SYSFILE_LIST = ["/sys/class/hwmon/hwmon2/device/ESC602_QSFP/", ""] + +SFP_GROUP_LIST = ['SFP-G01', 'SFP-G02', 'SFP-G03', 'SFP-G04'] + +PORT_NUM = 32 + +# SFP-eeprom paths /sys/bus/i2c/devices/XX-0050 +SFP_GROUP_INFO = { + "SFP-G01": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G02": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G03": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G04": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + } +} + +# +#Component +# ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " +# "modules (1-16)")], +# ["Slave-CPLD", "Used for managing QSFP modules (17-32)"] + +CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["System-CPLD", "Used for managing CPU board devices and power"] +] + +class PlatDev(): + def __init__(self): + self.plat_name = PLATFORM_NAME + self.psu_info = copy.deepcopy(PSU_INFO) + self.thermal_info = [] + self.fan_info = copy.deepcopy(FAN_INFO) + self.sfp_info = copy.deepcopy(SFP_GROUP_INFO) + self.device_install_info = dict() + self.sfp_install_info = dict() + + # get install info + self.get_dev_install_info() + # update path info with install info + # Item 1/2 not changed, append directly + self.thermal_info.append(THERMAL_SENSOR_LIST[0]) + self.thermal_info.append(THERMAL_SENSOR_LIST[1]) + + for i in range(2, len(THERMAL_SENSOR_LIST)): + install_info = self.device_install_info.get(THERMAL_SENSOR_LIST[i]['name']) + if install_info : + if self.bmc_is_exist(): + THERMAL_SENSOR_LIST[i]['sysfile_path'] = '/sys/class/hwmon/hwmon2/device/ESC602_THERMAL/' + else: + if install_info.get('hwmon_path') is None: + continue + THERMAL_SENSOR_LIST[i]['sysfile_path'] = install_info.get('hwmon_path') + self.thermal_info.append(THERMAL_SENSOR_LIST[i]) + + for psu_name in PSU_LIST: + install_info = self.device_install_info.get(psu_name) + if install_info: + if self.bmc_is_exist(): + self.psu_info[psu_name]['attr_path']= '/sys/class/hwmon/hwmon2/device/ESC602_POWER/' + else: + self.psu_info[psu_name]['attr_path'] = install_info.get('hwmon_path')+ '/device/' + + for sfp_group_name in SFP_GROUP_LIST: + install_info = self.sfp_install_info.get(sfp_group_name) + if install_info: + self.sfp_info[sfp_group_name]['paths'] = install_info.get('paths') + + def get_dev_install_info(self): + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + self.sfp_install_info = install_info[2] + self.device_install_info = install_info[1] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def bmc_is_exist(self): + bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESC602_SYS/bmc_present' + if os.path.exists(bmc_filePath): + value = self.__read_attr_file(bmc_filePath) + if int(value) == 1: + return True + else: + return False + else: + return False + ######Componet method ##### + def get_component_count(self): + return len(CHASSIS_COMPONENTS) + + def get_component_name(self,idx): + return CHASSIS_COMPONENTS[idx][0] + + def get_component_descript(self,idx): + return CHASSIS_COMPONENTS[idx][1] + + ###### PSU method ###### + def get_psu_list(self): + return PSU_LIST + + def get_psu_info_all(self): + return self.psu_info + + def get_psu_info_by_name(self, name): + return self.psu_info.get(name) + + def get_psu_attr_path_by_name(self, name): + return self.psu_info[name].get('attr_path') + + def get_psu_status_path_by_name(self, name): + return self.psu_info[name].get('status_path') + + ###### Thermal method ###### + def get_thermal_dev_info_all(self): + return self.thermal_info + + def get_thermal_dev_name_by_idx(self, index): + return self.thermal_info[index].get('name') + + def get_thermal_dev_tempidx_by_idx(self, index): + return self.thermal_info[index].get('temp_index') + + def get_thermal_dev_sysfile_path_by_idx(self, index): + return self.thermal_info[index].get('sysfile_path') + + def get_thermal_dev_support_mask_by_idx(self, index): + return self.thermal_info[index].get('support_mask') + + def get_thermal_dev_ext_sysfile_list_by_idx(self, index): + return self.thermal_info[index].get('ext_sysfile_list') + + ###### Fan method ###### + def get_fan_support(self): + return True + + def get_fan_list(self): + return FAN_LIST + + def get_fan_info_all(self): + return self.fan_info + + def get_fan_info_by_name(self, name): + return self.fan_info.get(name) + + def get_fan_sysfile_path_by_name(self, name): + return self.fan_info[name].get('attr_path') + + def get_fan_is_draw_by_name(self, name): + return self.fan_info[name].get('isdraw') + + def get_fan_num_by_name(self, name): + return self.fan_info[name].get('fan_num') + + ###### SFP method ###### + def get_sfp_num(self): + return PORT_NUM + + def get_sfp_group_list(self): + return SFP_GROUP_LIST + + def get_sfp_group_info(self): + return self.sfp_info + + def get_sfp_group_info_by_name(self, name): + return self.sfp_info.get(name) + + def get_sfp_group_type_by_name(self, name): + return self.sfp_info[name].get('type') + + def get_sfp_group_path_by_name(self, name): + return self.sfp_info[name].get('paths') + + def get_sfp_group_number_by_name(self, name): + return self.sfp_info[name].get('number') + + def get_sfp_ext_sysfile_list(self): + return SFP_EXT_SYSFILE_LIST + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platform.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platform.py new file mode 100755 index 0000000000..2456a6f2e7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/platform.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/psu.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/psu.py new file mode 100755 index 0000000000..20e365e73d --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/psu.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common.logger import Logger + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +# To do: should be defined in platDev +PSU_MAX_VOUT = 12.0 # voltage +PSU_MIN_VOUT = 3.3 # voltage +PSU_MAX_TEMP = 50.0 # C + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, index, info_list,is_bmc): + PsuBase.__init__(self) + self.index = index + self.is_bmc = is_bmc + self.attr_path = info_list[0] + self.status_path = info_list[1] + if is_bmc: + speed_file = self.attr_path + 'psu{}_fan_speed'.format(index+1) + else: + speed_file = self.attr_path + 'psu_fan_speed_1' + + fan = Fan( index, 0, [self.status_path, speed_file ],True) + self._fan_list.append(fan) + self.psu_name = "PSU{}".format(self.index+1) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.psu_name + + def get_presence(self): + """ + Retrieves the presence status of power supply unit (PSU) defined + Returns: + bool: True if PSU is present, False if not + """ + data = self.__read_attr_file(self.status_path + 'psu{}_prnt'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + data = self.__read_attr_file(self.status_path + 'psu{}_good'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_vout'.format(self.index+1) + else: + path = self.attr_path + "/psu_vout" + vout = self.__read_attr_file( path, 0) + if vout is not None: + return float(vout) / 1000 + + return False + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_iout'.format(self.index+1) + else: + path = self.attr_path + "/psu_iout" + iout = self.__read_attr_file( path, 0) + if iout is not None: + return float(iout) / 1000 + return False + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_pout'.format(self.index+1) + else: + path = self.attr_path + "/psu_pout" + pout = self.__read_attr_file( path, 0) + if pout is not None: + return float(pout) / 1000000 + return False + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + raise NotImplementedError + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.is_bmc: + path = self.attr_path+'psu{}_temp'.format(self.index+1) + else: + path = self.attr_path + "/psu_temp_1" + temperature = self.__read_attr_file( path, 0) + if temperature is not None: + return float(temperature) / 1000 + + return False + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return PSU_MAX_TEMP + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MAX_VOUT + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MIN_VOUT diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/sfp.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/sfp.py new file mode 100755 index 0000000000..76dda53aab --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/sfp.py @@ -0,0 +1,1175 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common.logger import Logger + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("sfp") + +############################################################################# +# +# SFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# ------------------------------------------------ 0 +# | Serial ID Defined by SFP MSA (96 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 95 +# | Vendor Specific (32 bytes) | +# |----------------------------------------------| 127 +# | Reserved, SFF-8079 (128 byte) | +# ------------------------------------------------ 255 +# +# 2 wire address 1010001x (A2h) (i2c 0x51) +# ------------------------------------------------ 0 +# | Alarm and Warning Threshold (56 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 55 +# | Cal Constants (40 bytes) | +# |----------------------------------------------| 95 +# | Real Time Diagnostic Interface(24 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 119 +# | Vendor Specific (7 bytes) | +# |----------------------------------------------| 126 +# | Page Select Byte (Optional) | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# Page 00h/01h +# |----------------------------------------------| 128 +# | User Writeable EEPROM (120 bytes) | +# |----------------------------------------------| 247 +# | Vendor Specific (8 bytes) | +# ------------------------------------------------ 255 +# Page 02h +# |----------------------------------------------| 128 +# | Control Function (128 bytes) | +# ------------------------------------------------ 255 +# Page 03h-7Fh +# |----------------------------------------------| 128 +# | Reserved (128 bytes) | +# ------------------------------------------------ 255 +# Page 80h-FFh +# |----------------------------------------------| 128 +# | Vendor Specific (128 bytes) | +# ------------------------------------------------ 255 +# +# ========================================================== +# QSFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# +# ------------------------------------------------ 0 +# | ID and status (3 bytes) | +# |----------------------------------------------| 2 +# | Interrupt Flags (19 bytes) | +# |----------------------------------------------| 21 +# | Module Monitors (12 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 33 +# | Channel Monitors (12 bytes) | +# |----------------------------------------------| 81 +# | Reserved (4 bytes) | +# |----------------------------------------------| 85 +# | Control (12 bytes) | <- get_power_override +# |----------------------------------------------| 97 +# | ~~~ | +# |----------------------------------------------| 126 +# | Page Select Byte | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# +# Page 00h +# |----------------------------------------------| 128 +# | Base ID Filed (64 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 191 +# | Extended ID (32 bytes) | +# |----------------------------------------------| 223 +# | Vendor Specific ID (8 bytes) | +# ------------------------------------------------ 255 +# Page 01h (optional) +# |----------------------------------------------| 128 +# | ~~~~ (128 bytes) | +# ------------------------------------------------ 255 +# Page 02h (optional) +# |----------------------------------------------| 128 +# | User EEPROM Data (128 bytes) | +# ------------------------------------------------ 255 + +# Page 03h (optional on QSFP28) +# |----------------------------------------------| 128 +# | Module Threshold (48 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 175 +# | Channel Threshold (48 bytes) | +# |----------------------------------------------| 223 +# | Reserved (2 bytes) | +# |----------------------------------------------| 225 +# | Vendor Specific Channel Controls (16 bytes) | +# |----------------------------------------------| 241 +# | Channel Monitor Masks (12 bytes) | +# |----------------------------------------------| 253 +# | Reserved (2 bytes) | +# ------------------------------------------------ 255 +# +# +# +# +# +# +# +# +############################################################################# + +# function eunm +SFP_GET_PRESENCE=0 +SFP_RESET =1 +SFP_GET_LOW_POWER_MODE=2 +SFP_SET_LOW_POWER_MODE=3 + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] + +# index for A0H, A2H sysfs file path +INDEX_A0H = 0 +INDEX_A2H = 1 + +# offset/width definition +OFFSET = 0 +WIDTH = 1 + +QSFP_UPPER_MEMORY_PAGE00_OFFSET = 128 +QSFP_UPPER_MEMORY_PAGE03_OFFSET = 512 + +SFP_A0H_OFFSET = 0 +SFP_A2H_OFFSET = 0 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 +ID_FIELD_WIDTH = 92 + +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 1 +QSFP_INTERFACE_BULK_WIDTH = 20 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 5], + 'DEVICE_TECH': [19, 1], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 2], + 'WAVELENGTH': [58, 2], + 'WAVELENGTH_TOLERANCE': [60, 2], + 'MAX_CASE_TEMP': [62, 1], + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 4], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [22, 2], + 'VOLTAGE': [26, 2], + 'CHANNEL_MON': [34, 24], + 'CONTROL': [86, 12], + # PAGE03 + 'MODULE_THRESHOLD': [0, 24], + 'CHANNEL_THRESHOLD': [50, 24] +} +SFP_INTERFACE_BULK_WIDTH = 21 +SFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 6], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 4], + 'WAVELENGTH': [60, 2], + # UNALLOCATED WIDDTH: 1 + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 2], + 'BITRATE_MAX': [66, 1], + # BITRATE_MAX ?? + 'BITRATE_MAX_1': [67, 1], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [96, 2], + 'VOLTAGE': [98, 2], + 'CHANNEL_MON': [100, 6], + 'MODULE_THRESHOLD': [0, 40] +} + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes','FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia','FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + def __init__(self, index, eeprom_path_list, sfp_type, ext_sysfile_list=None): + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + # ext_sysfile_list[0]: QSFP path + # ext_sysfile_list[1]: SFP path + self.index = index + self.eeprom_path_list = eeprom_path_list + #self._get_sfp_type(sfp_type) + self.sfp_type = sfp_type + if self.sfp_type == QSFP_TYPE: + self.present_file = ext_sysfile_list[0]+ 'qsfp{}_present'.format(self.index) + self.reset_file = ext_sysfile_list[0]+ 'qsfp{}_reset'.format(self.index) + self.lp_file = ext_sysfile_list[0]+ 'qsfp{}_low_power'.format(self.index) + else: + self.present_file = ext_sysfile_list[1]+ 'sfp{}_present'.format(self.index) + self.reset_file = None + self.lp_file = None + + def _get_sfp_type(self, sfp_type): + ty = self._read_eeprom_bytes(SFP_ID_FIELDS['TYPE'][OFFSET], SFP_ID_FIELDS['TYPE'][WIDTH], INDEX_A0H) + if ty is not None: + if ty[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + if ty[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + else: + self.sfp_type = sfp_type + logger.log_warning("Unreganized sfp type of module {} . unsupported, treated as specified type {}".format(self.index, sfp_type)) + else: + self.sfp_type = sfp_type + + + def _read_eeprom_bytes(self, offset, num_bytes, path_idx): + eeprom_raw = [] + + eeprom = None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom = open(self.eeprom_path_list[path_idx], mode="rb", buffering=0) + eeprom.seek(offset) + raw_data = eeprom.read(num_bytes) + for nb in range(0, len(raw_data)): + eeprom_raw[nb] = hex(ord(raw_data[nb]))[2:].zfill(2) + except Exception as ex: + logger.log_error("Fail to read eeprom {}".format(self.eeprom_path_list[path_idx])) + logger.log_error(" {}".format(ex)) + if eeprom is not None: + eeprom.close() + return None + + return eeprom_raw + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def __write_attr_file(self, filepath, data): + try: + with open(filepath,'w') as fd: + return fd.write(data) + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + return 0 + + def get_presence(self): + if self.present_file is not None: + data = self.__read_attr_file(self.present_file) + if data is not None: + if int(data) == 1: + return True + return False + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return '-inf' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == QSFP_TYPE: + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self._read_eeprom_bytes((offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self._read_eeprom_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH,INDEX_A0H) + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + qspf_dom_capability = int(qsfp_dom_capability_raw[0], 16) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qspf_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qspf_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qspf_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + qsfp_option_value_raw = self._read_eeprom_bytes(QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH,INDEX_A0H) + if qsfp_option_value_raw is not None: + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + self.optional_capability = sfpd_obj.parse_option_params(qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = self.optional_capability['data']['TxDisable']['value'] == 'On' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + elif self.sfp_type == SFP_TYPE: + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self._read_eeprom_bytes(XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = (int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + transceiver_info_dict_keys = [ + 'type', 'hardware_rev', + 'serial', 'manufacturer', + 'model', 'connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui','application_advertisement'] + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE00_OFFSET # upper memory map: Page 00h + Id_field = QSFP_ID_FIELDS + info_bulk_width = QSFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8436InterfaceId() + + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A0H_OFFSET # lower memory map: A0h (SFP i2c 0x50) + Id_field = SFP_ID_FIELDS + info_bulk_width = SFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8472InterfaceId() + else: + logger.log_error("Unsupported sfp type") + return None + + if sfpi_obj is None: + logger.log_error("sfpi_obj create fail") + return None + + # read Base ID field + sfp_interface_bulk_raw = self._read_eeprom_bytes(field_offset, ID_FIELD_WIDTH, INDEX_A0H) + if sfp_interface_bulk_raw is None: + logger.log_error(" Fail to read BaseID field of module {}".format(self.index+1)) + return None + + start = 0 + end = start + info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_NAME'][OFFSET] + end = start + Id_field['VENDOR_NAME'][WIDTH] + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_PN'][OFFSET] + end = start + Id_field['VENDOR_PN'][WIDTH] + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_REV'][OFFSET] + end = start + Id_field['VENDOR_REV'][WIDTH] + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_SN'][OFFSET] + end = start + Id_field['VENDOR_SN'][WIDTH] + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_OUI'][OFFSET] + end = start + Id_field['VENDOR_OUI'][WIDTH] + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_DATE'][OFFSET] + end = start + Id_field['VENDOR_DATE'][WIDTH] + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + + compliance_code_dict = {} + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = [ + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] + transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] + transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] + transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] + transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] + transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] + transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num(transceiver_dom_info_dict[key]) + + return transceiver_dom_info_dict + + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + dom_info_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + + transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE03_OFFSET # uppper memory map: Page 03h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return transceiver_dom_threshold_info_dict + + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['MODULE_THRESHOLD'][OFFSET], Id_field['MODULE_THRESHOLD'][WIDTH], path_idx) + + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_THRESHOLD'][OFFSET], Id_field['CHANNEL_THRESHOLD'][WIDTH], path_idx) + + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + else: # SFP_TYPE + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + raise NotImplementedError + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + raise NotImplementedError + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + raise NotImplementedError + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + raise NotImplementedError + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + raise NotImplementedError + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.lp_file is not None: + data = self.__read_attr_file(self.lp_file, 0) + if data is not None: + if int(data) == 1: + return True + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + + if self.sfp_type == QSFP_TYPE: + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_bytes(Id_field['CONTROL'][OFFSET], Id_field['CONTROL'][WIDTH], INDEX_A0H) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + + return False + else: + return NotImplementedError + + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + path_idx = INDEX_A0H + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + + return None + + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + path_idx = INDEX_A0H + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + volt = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return volt + + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + path_idx = INDEX_A0H + tx_bias_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value'])) + + return tx_bias_list + + return None + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + path_idx = INDEX_A0H + rx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value'])) + + return rx_power_list + + return None + + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + path_idx = INDEX_A0H + tx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value'])) + + return tx_power_list + + return None + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + if self.reset_file is not None: + ret = self.__write_attr_file(self.reset_file, '1') + if ret != 0: + return True + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.lp_file is not None: + if lpmode is True: + ret = self.__write_attr_file(self.lp_file, "1") + else: + ret = self.__write_attr_file(self.lp_file, "0") + if ret != 0: + return True + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + return False + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/thermal.py b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/thermal.py new file mode 100755 index 0000000000..3731edaa7b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esc602-32q/sonic_platform/thermal.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +logger = Logger("thermal") +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + def __init__(self, index, name, sysfile_path, is_bmc, support_mask=0x1, ext_sysfile_list=None): + # index is used to indicate the temp{} under sffile_path + # support_mask: 1:support 0:not support + # bit 0 : temperature (always 1) + # bit 1 : high threshold + # bit 2 : low threshold + # bit 3 : high critical threshold + # bit 4 : low critical threshold + # bit 7 : cpu internal sensor + # ext_sysfile_list: each specified path of each supported function, + # which not follows the general naming rule + + self.index = index + self.name = name + self.filepath = sysfile_path + self.support_mask = support_mask + self.is_bmc = is_bmc + + self.temperature_file = None + self.high_thershold_file = None + self.low_threshold_file = None + self.high_critical_file = None + self.low_critical_file = None + + if sysfile_path is None: + return + + if self.is_bmc ==False or support_mask & 0x80 == 0x80: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + "/temp{}_input".format(self.index) + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + "/temp{}_max".format(self.index) + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + "/temp{}_min".format(self.index) + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + "/temp{}_crit".format(self.index) + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + "/temp{}_lcrit".format(self.index) + elif self.is_bmc and ext_sysfile_list is not None: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + ext_sysfile_list[self.index][0] + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + ext_sysfile_list[self.index][1] + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + ext_sysfile_list[self.index][2] + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][3] + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][4] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.name + + def get_presence(self): + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.temperature_file is not None: + temp = self.__read_attr_file( self.temperature_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_thershold_file is not None: + temp = self.__read_attr_file( self.high_thershold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_threshold_file is not None: + temp = self.__read_attr_file( self.low_threshold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_file is not None: + temp = self.__read_attr_file( self.high_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_critical_file is not None: + temp = self.__read_attr_file( self.low_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/Makefile b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/Makefile new file mode 100644 index 0000000000..2020904011 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/Makefile @@ -0,0 +1,5 @@ +obj-m := nct7511.o at24_smbus.o zrh2800k2.o +obj-m += x86-64-cameo-escc601-32q.o +x86-64-cameo-escc601-32q-objs := x86-64-cameo-escc601-32q-common.o x86-64-cameo-escc601-32q-sys.o \ +x86-64-cameo-escc601-32q-led.o x86-64-cameo-escc601-32q-fan.o x86-64-cameo-escc601-32q-power.o \ +x86-64-cameo-escc601-32q-thermal.o x86-64-cameo-escc601-32q-qsfp.o \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/at24_smbus.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/at24_smbus.c new file mode 100644 index 0000000000..16d6594746 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/at24_smbus.c @@ -0,0 +1,847 @@ +/* + * at24.c - handle most I2C EEPROMs + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + int use_smbus; + int use_smbus_write; + + ssize_t (*read_func)(struct at24_data *, char *, unsigned int, size_t); + ssize_t (*write_func)(struct at24_data *, + const char *, unsigned int, size_t); + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + struct nvmem_config nvmem_config; + struct nvmem_device *nvmem; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +/* + * Both reads and writes fail if the previous write didn't complete yet. This + * macro loops a few times waiting at least long enough for one entire page + * write to work while making sure that at least one iteration is run before + * checking the break condition. + * + * It takes two parameters: a variable in which the future timeout in jiffies + * will be stored and a temporary variable holding the time of the last + * iteration of processing the request. Both should be unsigned integers + * holding at least 32 bits. + */ +#define loop_until_timeout(tout, op_time) \ + for (tout = jiffies + msecs_to_jiffies(write_timeout), op_time = 0; \ + op_time ? time_before(op_time, tout) : true; \ + usleep_range(1000, 1500), op_time = jiffies) + +static const struct i2c_device_id at24_ids[] = { + { "24c64smbus", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ids); + +static const struct acpi_device_id at24_acpi_ids[] = { + { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) }, + { } +}; +MODULE_DEVICE_TABLE(acpi, at24_acpi_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + * + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + * + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned int *offset) +{ + unsigned i; + + if (at24->chip.flags & AT24_FLAG_ADDR16) { + i = *offset >> 16; + *offset &= 0xffff; + } else { + i = *offset >> 8; + *offset &= 0xff; + } + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, read_time; + struct i2c_client *client; + int status,i,j; + + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + /* Smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + + if(at24->chip.flags & AT24_FLAG_ADDR16){ + + + status = i2c_smbus_write_byte_data(client, offset>>8, + offset&0xff); + if(status < 0) + return status; + + mdelay(7); + for (i = 0; i < count; i++) { + j = i2c_smbus_read_byte(client); + if (j < 0) { + return j; + } + buf[i] = j; + } + return count; + + }else{ + + loop_until_timeout(timeout, read_time) { + status = i2c_smbus_read_i2c_block_data_or_emulated(client, + offset, + count, buf); + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + } + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, read_time; + struct i2c_client *client; + struct i2c_msg msg[2]; + int status, i; + u8 msgbuf[2]; + + memset(msg, 0, sizeof(msg)); + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + /* + * When we have a better choice than SMBus calls, use a combined I2C + * message. Write address; then read up to io_limit data bytes. Note + * that read page rollover helps us here (unlike writes). msgbuf is + * u8 and will cast to our needs. + */ + i = 0; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msgbuf[i++] = offset >> 8; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + loop_until_timeout(timeout, read_time) { + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_read_serial(struct at24_data *at24, char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, read_time; + struct i2c_client *client; + struct i2c_msg msg[2]; + u8 addrbuf[2]; + int status; + + client = at24_translate_offset(at24, &offset); + + memset(msg, 0, sizeof(msg)); + msg[0].addr = client->addr; + msg[0].buf = addrbuf; + + /* + * The address pointer of the device is shared between the regular + * EEPROM array and the serial number block. The dummy write (part of + * the sequential read protocol) ensures the address pointer is reset + * to the desired position. + */ + if (at24->chip.flags & AT24_FLAG_ADDR16) { + /* + * For 16 bit address pointers, the word address must contain + * a '10' sequence in bits 11 and 10 regardless of the + * intended position of the address pointer. + */ + addrbuf[0] = 0x08; + addrbuf[1] = offset; + msg[0].len = 2; + } else { + /* + * Otherwise the word address must begin with a '10' sequence, + * regardless of the intended address. + */ + addrbuf[0] = 0x80 + offset; + msg[0].len = 1; + } + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + loop_until_timeout(timeout, read_time) { + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_read_mac(struct at24_data *at24, char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, read_time; + struct i2c_client *client; + struct i2c_msg msg[2]; + u8 addrbuf[2]; + int status; + + client = at24_translate_offset(at24, &offset); + + memset(msg, 0, sizeof(msg)); + msg[0].addr = client->addr; + msg[0].buf = addrbuf; + /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */ + addrbuf[0] = 0xa0 - at24->chip.byte_len + offset; + msg[0].len = 1; + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + loop_until_timeout(timeout, read_time) { + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + return count; + } + + return -ETIMEDOUT; +} + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. These routines + * write at most one page. + */ + +static size_t at24_adjust_write_count(struct at24_data *at24, + unsigned int offset, size_t count) +{ + unsigned next_page; + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + return count; +} + +static ssize_t at24_eeprom_write_smbus_block(struct at24_data *at24, + const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + ssize_t status = 0; + + client = at24_translate_offset(at24, &offset); + count = at24_adjust_write_count(at24, offset, count); + + loop_until_timeout(timeout, write_time) { + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24, + const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + ssize_t status = 0; + + client = at24_translate_offset(at24, &offset); + + loop_until_timeout(timeout, write_time) { + status = i2c_smbus_write_byte_data(client, offset, buf[0]); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + struct i2c_msg msg; + ssize_t status = 0; + int i = 0; + + client = at24_translate_offset(at24, &offset); + count = at24_adjust_write_count(at24, offset, count); + + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = at24->writebuf; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msg.buf[i++] = offset >> 8; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + loop_until_timeout(timeout, write_time) { + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static int at24_read(void *priv, unsigned int off, void *val, size_t count) +{ + struct at24_data *at24 = priv; + char *buf = val; + + if (unlikely(!count)) + return count; + + if (off + count > at24->chip.byte_len) + return -EINVAL; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + int status; + + status = at24->read_func(at24, buf, off, count); + if (status < 0) { + mutex_unlock(&at24->lock); + return status; + } + buf += status; + off += status; + count -= status; + } + + mutex_unlock(&at24->lock); + + return 0; +} + +static int at24_write(void *priv, unsigned int off, void *val, size_t count) +{ + struct at24_data *at24 = priv; + char *buf = val; + + if (unlikely(!count)) + return -EINVAL; + + if (off + count > at24->chip.byte_len) + return -EINVAL; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + int status; + + status = at24->write_func(at24, buf, off, count); + if (status < 0) { + mutex_unlock(&at24->lock); + return status; + } + buf += status; + off += status; + count -= status; + } + + mutex_unlock(&at24->lock); + + return 0; +} + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + kernel_ulong_t magic = 0; + bool writable; + int use_smbus = 0; + int use_smbus_write = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + u8 test_byte; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (id) { + magic = id->driver_data; + } else { + const struct acpi_device_id *aid; + + aid = acpi_match_device(at24_acpi_ids, &client->dev); + if (aid) + magic = aid->driver_data; + } + if (!magic) + return -ENODEV; + + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* + * REVISIT: the size of the EUI-48 byte array is 6 in at24mac402, while + * the call to ilog2() in AT24_DEVICE_MAGIC() rounds it down to 4. + * + * Eventually we'll get rid of the magic values altoghether in favor of + * real structs, but for now just manually set the right size. + */ + if (chip.flags & AT24_FLAG_MAC && chip.byte_len == 4) + chip.byte_len = 6; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + //if (chip.flags & AT24_FLAG_ADDR16) + // return -EPFNOSUPPORT; + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + use_smbus_write = I2C_SMBUS_BYTE_DATA; + chip.page_size = 1; + } + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, + (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->use_smbus_write = use_smbus_write; + at24->chip = chip; + at24->num_addresses = num_addresses; + + if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) { + dev_err(&client->dev, + "invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC."); + return -EINVAL; + } + + if (chip.flags & AT24_FLAG_SERIAL) { + at24->read_func = at24_eeprom_read_serial; + } else if (chip.flags & AT24_FLAG_MAC) { + at24->read_func = at24_eeprom_read_mac; + } else { + at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus + : at24_eeprom_read_i2c; + } + + if (at24->use_smbus) { + if (at24->use_smbus_write == I2C_SMBUS_I2C_BLOCK_DATA) + at24->write_func = at24_eeprom_write_smbus_block; + else + at24->write_func = at24_eeprom_write_smbus_byte; + } else { + at24->write_func = at24_eeprom_write_i2c; + } + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || use_smbus_write) { + + unsigned write_max = chip.page_size; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, + write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, + client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", + client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + i2c_set_clientdata(client, at24); + + /* + * Perform a one-byte test read to verify that the + * chip is functional. + */ + err = at24_read(at24, 0, &test_byte, 1); + if (err) { + err = -ENODEV; + goto err_clients; + } + + at24->nvmem_config.name = dev_name(&client->dev); + at24->nvmem_config.dev = &client->dev; + at24->nvmem_config.read_only = !writable; + at24->nvmem_config.root_only = true; + at24->nvmem_config.owner = THIS_MODULE; + at24->nvmem_config.compat = true; + at24->nvmem_config.base_dev = &client->dev; + at24->nvmem_config.reg_read = at24_read; + at24->nvmem_config.reg_write = at24_write; + at24->nvmem_config.priv = at24; + at24->nvmem_config.stride = 1; + at24->nvmem_config.word_size = 1; + at24->nvmem_config.size = chip.byte_len; + + at24->nvmem = nvmem_register(&at24->nvmem_config); + + if (IS_ERR(at24->nvmem)) { + err = PTR_ERR(at24->nvmem); + goto err_clients; + } + + dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n", + chip.byte_len, client->name, + writable ? "writable" : "read-only", at24->write_max); + if (use_smbus == I2C_SMBUS_WORD_DATA || + use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } + + /* export data to kernel code */ + if (chip.setup) + chip.setup(at24->nvmem, chip.context); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + + nvmem_unregister(at24->nvmem); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_driver at24_driver = { + .driver = { + .name = "at24_smbus", + .acpi_match_table = ACPI_PTR(at24_acpi_ids), + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ids, +}; + +static int __init at24_init(void) +{ + if (!io_limit) { + pr_err("at24: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + return i2c_add_driver(&at24_driver); +} +module_init(at24_init); + +static void __exit at24_exit(void) +{ + i2c_del_driver(&at24_driver); +} +module_exit(at24_exit); + +MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); +MODULE_AUTHOR("David Brownell and Wolfram Sang"); +MODULE_LICENSE("GPL"); diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/nct7511.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/nct7511.c new file mode 100644 index 0000000000..8ddf1919f5 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/nct7511.c @@ -0,0 +1,765 @@ +/* + + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "nct7511" + + +#define REG_BANK 0x00 +#define REG_TEMP_LSB 0x05 +#define REG_FANCOUNT_LOW 0x13 +#define REG_START 0x21 +#define REG_MODE 0x22 /* 7.2.32 Mode Selection Register */ +#define REG_FAN_ENABLE 0x24 +#define REG_PWM(x) (0x60 + (x)) +#define REG_SMARTFAN_EN(x) (0x64 + (x) / 2) +#define SMARTFAN_EN_SHIFT(x) ((x) % 2 * 4) +#define REG_VENDOR_ID 0xfd +#define REG_CHIP_ID 0xfe +#define REG_VERSION_ID 0xff + +/* + * Data structures and manipulation thereof + */ + +struct nct7511_data { + struct regmap *regmap; + struct mutex access_lock; /* for multi-byte read and write operations */ +}; + +static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct nct7511_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + unsigned int mode; + int ret; + + ret = regmap_read(data->regmap, REG_MODE, &mode); + if (ret < 0) + return ret; + + return sprintf(buf, "%u\n", (mode >> (2 * sattr->index) & 3) + 2); +} + +static ssize_t store_temp_type(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct nct7511_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + unsigned int type; + int err; + + err = kstrtouint(buf, 0, &type); + if (err < 0) + return err; + if (sattr->index == 2 && type != 4) /* RD3 */ + return -EINVAL; + if (type < 3 || type > 4) + return -EINVAL; + err = regmap_update_bits(data->regmap, REG_MODE, + 3 << 2 * sattr->index, (type - 2) << 2 * sattr->index); + return err ? : count; +} + +static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + struct nct7511_data *data = dev_get_drvdata(dev); + unsigned int regval; + int ret; + + if (sattr->index > 1) + return sprintf(buf, "1\n"); + + ret = regmap_read(data->regmap, 0x5E, ®val); + if (ret < 0) + return ret; + + return sprintf(buf, "%u\n", !(regval & (1 << sattr->index))); +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct nct7511_data *data = dev_get_drvdata(dev); + unsigned int val; + int ret; + + if (!attr->index) + return sprintf(buf, "255\n"); + + ret = regmap_read(data->regmap, attr->index, &val); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", val); +} + +static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct nct7511_data *data = dev_get_drvdata(dev); + int err; + u8 val; + + err = kstrtou8(buf, 0, &val); + if (err < 0) + return err; + + err = regmap_write(data->regmap, attr->index, val); + return err ? : count; +} + +static ssize_t show_pwm_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nct7511_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + unsigned int reg, enabled; + int ret; + + ret = regmap_read(data->regmap, REG_SMARTFAN_EN(sattr->index), ®); + if (ret < 0) + return ret; + enabled = reg >> SMARTFAN_EN_SHIFT(sattr->index) & 1; + return sprintf(buf, "%u\n", enabled + 1); +} + +static ssize_t store_pwm_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct nct7511_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + u8 val; + int ret; + + ret = kstrtou8(buf, 0, &val); + if (ret < 0) + return ret; + if (val < 1 || val > 2) + return -EINVAL; + ret = regmap_update_bits(data->regmap, REG_SMARTFAN_EN(sattr->index), + 1 << SMARTFAN_EN_SHIFT(sattr->index), + (val - 1) << SMARTFAN_EN_SHIFT(sattr->index)); + return ret ? : count; +} + +static int nct7511_read_temp(struct nct7511_data *data, + u8 reg_temp, u8 reg_temp_low, int *temp) +{ + unsigned int t1, t2 = 0; + int err; + + *temp = 0; + + mutex_lock(&data->access_lock); + err = regmap_read(data->regmap, reg_temp, &t1); + if (err < 0) + goto abort; + t1 <<= 8; + if (reg_temp_low) { /* 11 bit data */ + err = regmap_read(data->regmap, reg_temp_low, &t2); + if (err < 0) + goto abort; + } + t1 |= t2 & 0xe0; + *temp = (s16)t1 / 32 * 125; +abort: + mutex_unlock(&data->access_lock); + return err; +} + +static int nct7511_read_fan(struct nct7511_data *data, u8 reg_fan) +{ + unsigned int f1, f2; + int ret; + + mutex_lock(&data->access_lock); + ret = regmap_read(data->regmap, reg_fan, &f1); + if (ret < 0) + goto abort; + ret = regmap_read(data->regmap, REG_FANCOUNT_LOW, &f2); + if (ret < 0) + goto abort; + ret = (f1 << 5) | (f2 >> 3); + /* convert fan count to rpm */ + if (ret == 0x1fff) /* maximum value, assume fan is stopped */ + ret = 0; + else if (ret) + ret = DIV_ROUND_CLOSEST(1350000U, ret); +abort: + mutex_unlock(&data->access_lock); + return ret; +} + +static int nct7511_read_fan_min(struct nct7511_data *data, u8 reg_fan_low, + u8 reg_fan_high) +{ + unsigned int f1, f2; + int ret; + + mutex_lock(&data->access_lock); + ret = regmap_read(data->regmap, reg_fan_low, &f1); + if (ret < 0) + goto abort; + ret = regmap_read(data->regmap, reg_fan_high, &f2); + if (ret < 0) + goto abort; + ret = f1 | ((f2 & 0xf8) << 5); + /* convert fan count to rpm */ + if (ret == 0x1fff) /* maximum value, assume no limit */ + ret = 0; + else if (ret) + ret = DIV_ROUND_CLOSEST(1350000U, ret); + else + ret = 1350000U; +abort: + mutex_unlock(&data->access_lock); + return ret; +} + +static int nct7511_write_fan_min(struct nct7511_data *data, u8 reg_fan_low, + u8 reg_fan_high, unsigned long limit) +{ + int err; + + if (limit) + limit = DIV_ROUND_CLOSEST(1350000U, limit); + else + limit = 0x1fff; + limit = clamp_val(limit, 0, 0x1fff); + + mutex_lock(&data->access_lock); + err = regmap_write(data->regmap, reg_fan_low, limit & 0xff); + if (err < 0) + goto abort; + + err = regmap_write(data->regmap, reg_fan_high, (limit & 0x1f00) >> 5); +abort: + mutex_unlock(&data->access_lock); + return err; +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct nct7511_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int err, temp; + + err = nct7511_read_temp(data, sattr->nr, sattr->index, &temp); + if (err < 0) + return err; + + return sprintf(buf, "%d\n", temp); +} + +static ssize_t store_temp(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct7511_data *data = dev_get_drvdata(dev); + int nr = sattr->nr; + long val; + int err; + + err = kstrtol(buf, 10, &val); + if (err < 0) + return err; + + val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000); + + err = regmap_write(data->regmap, nr, val & 0xff); + return err ? : count; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + struct nct7511_data *data = dev_get_drvdata(dev); + int speed; + + speed = nct7511_read_fan(data, sattr->index); + if (speed < 0) + return speed; + + return sprintf(buf, "%d\n", speed); +} + +static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct7511_data *data = dev_get_drvdata(dev); + int speed; + + speed = nct7511_read_fan_min(data, sattr->nr, sattr->index); + if (speed < 0) + return speed; + + return sprintf(buf, "%d\n", speed); +} + +static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct7511_data *data = dev_get_drvdata(dev); + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err < 0) + return err; + + err = nct7511_write_fan_min(data, sattr->nr, sattr->index, val); + return err ? : count; +} + +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct nct7511_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int bit = sattr->index; + unsigned int val; + int ret; + + ret = regmap_read(data->regmap, sattr->nr, &val); + if (ret < 0) + return ret; + + return sprintf(buf, "%u\n", !!(val & (1 << bit))); +} + +static ssize_t +show_beep(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct7511_data *data = dev_get_drvdata(dev); + unsigned int regval; + int err; + + err = regmap_read(data->regmap, sattr->nr, ®val); + if (err) + return err; + + return sprintf(buf, "%u\n", !!(regval & (1 << sattr->index))); +} + +static ssize_t +store_beep(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct7511_data *data = dev_get_drvdata(dev); + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err < 0) + return err; + if (val > 1) + return -EINVAL; + + err = regmap_update_bits(data->regmap, sattr->nr, 1 << sattr->index, + val ? 1 << sattr->index : 0); + return err ? : count; +} + +static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, + show_temp_type, store_temp_type, 0); +static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0x01, + REG_TEMP_LSB); +static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x31, 0); +static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x30, 0); +static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x3a, 0); + +static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, + show_temp_type, store_temp_type, 1); +static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0x02, + REG_TEMP_LSB); +static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x33, 0); +static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x32, 0); +static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x3b, 0); + +static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, + show_temp_type, store_temp_type, 2); +static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0x03, + REG_TEMP_LSB); +static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x35, 0); +static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x34, 0); +static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x3c, 0); + +static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 0x04, 0); +static SENSOR_DEVICE_ATTR_2(temp4_min, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x37, 0); +static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x36, 0); +static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, + store_temp, 0x3d, 0); + + +static SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO, show_alarm, NULL, + 0x18, 0); +static SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO, show_alarm, NULL, + 0x18, 1); +static SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO, show_alarm, NULL, + 0x18, 2); +static SENSOR_DEVICE_ATTR_2(temp4_min_alarm, S_IRUGO, show_alarm, NULL, + 0x18, 3); + +static SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO, show_alarm, NULL, + 0x19, 0); +static SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO, show_alarm, NULL, + 0x19, 1); +static SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO, show_alarm, NULL, + 0x19, 2); +static SENSOR_DEVICE_ATTR_2(temp4_max_alarm, S_IRUGO, show_alarm, NULL, + 0x19, 3); + + +static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, + 0x1b, 0); +static SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, + 0x1b, 1); +static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, + 0x1b, 2); +static SENSOR_DEVICE_ATTR_2(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, + 0x1b, 3); + +static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_alarm, NULL, 0x17, 0); +static SENSOR_DEVICE_ATTR_2(temp2_fault, S_IRUGO, show_alarm, NULL, 0x17, 1); +static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_alarm, NULL, 0x17, 2); + +static SENSOR_DEVICE_ATTR_2(temp1_beep, S_IRUGO | S_IWUSR, show_beep, + store_beep, 0x5c, 0); +static SENSOR_DEVICE_ATTR_2(temp2_beep, S_IRUGO | S_IWUSR, show_beep, + store_beep, 0x5c, 1); +static SENSOR_DEVICE_ATTR_2(temp3_beep, S_IRUGO | S_IWUSR, show_beep, + store_beep, 0x5c, 2); +static SENSOR_DEVICE_ATTR_2(temp4_beep, S_IRUGO | S_IWUSR, show_beep, + store_beep, 0x5c, 3); + +static struct attribute *nct7511_temp_attrs[] = { + &sensor_dev_attr_temp1_type.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + &sensor_dev_attr_temp1_beep.dev_attr.attr, + + &sensor_dev_attr_temp2_type.dev_attr.attr, /* 10 */ + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_crit.dev_attr.attr, + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, + &sensor_dev_attr_temp2_beep.dev_attr.attr, + + &sensor_dev_attr_temp3_type.dev_attr.attr, /* 20 */ + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_crit.dev_attr.attr, + &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, + &sensor_dev_attr_temp3_beep.dev_attr.attr, + + &sensor_dev_attr_temp4_input.dev_attr.attr, /* 30 */ + &sensor_dev_attr_temp4_min.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp4_crit.dev_attr.attr, + &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_beep.dev_attr.attr, + + NULL +}; + +static umode_t nct7511_temp_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct nct7511_data *data = dev_get_drvdata(dev); + unsigned int reg; + int err; + + err = regmap_read(data->regmap, REG_MODE, ®); + if (err < 0) + return 0; + + if (index < 10 && + (reg & 03) != 0x01 && (reg & 0x03) != 0x02) /* RD1 */ + return 0; + + if (index >= 10 && index < 20 && + (reg & 0x0c) != 0x04 && (reg & 0x0c) != 0x08) /* RD2 */ + return 0; + if (index >= 20 && index < 30 && (reg & 0x30) != 0x20) /* RD3 */ + return 0; + + if (index >= 30 && index < 38) /* local */ + return attr->mode; + + return attr->mode; +} + +static struct attribute_group nct7511_temp_group = { + .attrs = nct7511_temp_attrs, + .is_visible = nct7511_temp_is_visible, +}; + + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0x10); +static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan_min, + store_fan_min, 0x49, 0x4c); +static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, show_alarm, NULL, 0x1a, 0); +static SENSOR_DEVICE_ATTR_2(fan1_beep, S_IRUGO | S_IWUSR, show_beep, store_beep, + 0x5b, 0); + +/* 7.2.89 Fan Control Output Type */ +static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0); + +/* 7.2.91... Fan Control Output Value */ +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, + REG_PWM(0)); + + +/* 7.2.95... Temperature to Fan mapping Relationships Register */ +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, + store_pwm_enable, 0); + + +static struct attribute *nct7511_fan_attrs[] = { + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_beep.dev_attr.attr, + NULL +}; + +static umode_t nct7511_fan_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct nct7511_data *data = dev_get_drvdata(dev); + int fan = index / 4; /* 4 attributes per fan */ + unsigned int reg; + int err; + + err = regmap_read(data->regmap, REG_FAN_ENABLE, ®); + if (err < 0 || !(reg & (1 << fan))) + return 0; + + return attr->mode; +} + +static struct attribute_group nct7511_fan_group = { + .attrs = nct7511_fan_attrs, + .is_visible = nct7511_fan_is_visible, +}; + +static struct attribute *nct7511_pwm_attrs[] = { + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm1_mode.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + NULL +}; + +static struct attribute_group nct7511_pwm_group = { + .attrs = nct7511_pwm_attrs, +}; + +/* 7.2.115... 0x80-0x83, 0x84 Temperature (X-axis) transition */ +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR, + show_temp, store_temp, 0x80, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR, + show_temp, store_temp, 0x81, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR, + show_temp, store_temp, 0x82, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR, + show_temp, store_temp, 0x83, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point5_temp, S_IRUGO | S_IWUSR, + show_temp, store_temp, 0x84, 0); + +/* 7.2.120... 0x85-0x88 PWM (Y-axis) transition */ +static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, + show_pwm, store_pwm, 0x85); +static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, + show_pwm, store_pwm, 0x86); +static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO | S_IWUSR, + show_pwm, store_pwm, 0x87); +static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO | S_IWUSR, + show_pwm, store_pwm, 0x88); +static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm, NULL, 0); + + +static struct attribute *nct7511_auto_point_attrs[] = { + &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr, + + &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr, + + NULL +}; + +static struct attribute_group nct7511_auto_point_group = { + .attrs = nct7511_auto_point_attrs, +}; + +static const struct attribute_group *nct7511_groups[] = { + &nct7511_temp_group, + &nct7511_fan_group, + &nct7511_pwm_group, + &nct7511_auto_point_group, + NULL +}; + +static int nct7511_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + int reg; + + reg = i2c_smbus_read_byte_data(client, REG_VENDOR_ID); + if (reg != 0x50) + return -ENODEV; + + reg = i2c_smbus_read_byte_data(client, REG_CHIP_ID); + if (reg != 0xc3) + return -ENODEV; + + reg = i2c_smbus_read_byte_data(client, REG_VERSION_ID); + if (reg < 0 || (reg & 0xf0) != 0x20) + return -ENODEV; + + /* Also validate lower bits of voltage and temperature registers */ + reg = i2c_smbus_read_byte_data(client, REG_TEMP_LSB); + if (reg < 0 || (reg & 0x1f)) + return -ENODEV; + + strlcpy(info->type, "nct7511", I2C_NAME_SIZE); + return 0; +} + +static bool nct7511_regmap_is_volatile(struct device *dev, unsigned int reg) +{ + return (reg != REG_BANK && reg <= 0x20) || + (reg >= REG_PWM(0) && reg <= REG_PWM(2)); +} + +static const struct regmap_config nct7511_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = nct7511_regmap_is_volatile, +}; + +static int nct7511_init_chip(struct nct7511_data *data) +{ + int err; + + /* Enable ADC */ + err = regmap_update_bits(data->regmap, REG_START, 0x01, 0x01); + if (err) + return err; + /* Enable local temperature sensor */ + return regmap_update_bits(data->regmap, REG_MODE, 0x40, 0x40); +} + +static int nct7511_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct nct7511_data *data; + struct device *hwmon_dev; + int ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->regmap = devm_regmap_init_i2c(client, &nct7511_regmap_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + + mutex_init(&data->access_lock); + + ret = nct7511_init_chip(data); + if (ret < 0) + return ret; + + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + nct7511_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} + + +static const struct i2c_device_id nct7511_idtable[] = { + { "nct7511", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nct7511_idtable); + +static struct i2c_driver nct7511_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .detect = nct7511_detect, + .probe = nct7511_probe, + .id_table = nct7511_idtable, +}; + +module_i2c_driver(nct7511_driver); + +MODULE_AUTHOR("Cameo "); +MODULE_DESCRIPTION("NCT7511Y Hardware Monitoring Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.c new file mode 100644 index 0000000000..ec2d4370fb --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.c @@ -0,0 +1,368 @@ +/* An hwmon driver for Cameo escc601-32Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-escc601-32q.h" +#include "x86-64-cameo-escc601-32q-common.h" + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x30, 0x31, 0x32, I2C_CLIENT_END }; +static int debug = 0; + + +/* i2c_client Declaration */ +struct i2c_client *Cameo_CPLD_30_client; //0x30 for SYS CPLD +struct i2c_client *Cameo_CPLD_31_client; //0x31 for Port 01-16 +struct i2c_client *Cameo_CPLD_32_client; //0x32 for Port 17-32 +struct i2c_client *Cameo_CPLD_23_client; //0x23 for Fan CPLD +struct i2c_client *Cameo_CPLD_35_client; //0x35 for Power CPLD +struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of i2c_client Declaration */ + +/* register offset define */ +#define BMC_EN_REG 0xA4 +/* end of register offset define */ + +/* common function */ +int bmc_enable(void) +{ + if ((i2c_smbus_read_byte_data(Cameo_CPLD_30_client, BMC_EN_REG) & BIT_0_MASK) == 0x01) + { + return ENABLE; + } + else + { + return DISABLE; + } +} + +int read_8bit_temp(u8 sign,u8 value) +{ + int result = 0; + if(sign) + { + //printf("read_8bit_temp UP %d\n", value & 0x80); + value = ~(value)+1; + result = value; + return result; + } + else + { + //printf("read_8bit_temp DOWN %d\n", value & 0x80); + result = value; + return result; + } +} + +/* end of common function*/ + +static int Cameo_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + struct Cameo_i2c_data *Cameo_CPLD_30_data; + struct Cameo_i2c_data *Cameo_CPLD_31_data; + struct Cameo_i2c_data *Cameo_CPLD_32_data; + struct Cameo_i2c_data *Cameo_CPLD_23_data; + struct Cameo_i2c_data *Cameo_CPLD_35_data; + struct Cameo_i2c_data *Cameo_BMC_14_data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + { + status = -EIO; + goto exit; + } + Cameo_CPLD_30_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_30_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_31_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_31_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_32_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_32_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_23_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_23_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_35_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_35_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_BMC_14_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_BMC_14_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(Cameo_CPLD_30_client, Cameo_CPLD_30_data); + i2c_set_clientdata(Cameo_CPLD_31_client, Cameo_CPLD_31_data); + i2c_set_clientdata(Cameo_CPLD_32_client, Cameo_CPLD_32_data); + i2c_set_clientdata(Cameo_CPLD_23_client, Cameo_CPLD_23_data); + i2c_set_clientdata(Cameo_CPLD_35_client, Cameo_CPLD_35_data); + i2c_set_clientdata(Cameo_BMC_14_client , Cameo_BMC_14_data); + + mutex_init(&Cameo_CPLD_30_data->update_lock); + mutex_init(&Cameo_CPLD_31_data->update_lock); + mutex_init(&Cameo_CPLD_32_data->update_lock); + mutex_init(&Cameo_CPLD_23_data->update_lock); + mutex_init(&Cameo_CPLD_35_data->update_lock); + mutex_init(&Cameo_BMC_14_data->update_lock); + + Cameo_CPLD_30_data->valid = 0; + mutex_init(&Cameo_CPLD_30_data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ESCC601_SYS_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESCC601_LED_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESCC601_FAN_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESCC601_THERMAL_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESCC601_POWER_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESCC601_QSFP_group); + if (status) + { + goto exit_free; + } + + Cameo_CPLD_30_data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(Cameo_CPLD_30_data->hwmon_dev)) + { + status = PTR_ERR(Cameo_CPLD_30_data->hwmon_dev); + goto exit_remove; + } + dev_info(&client->dev, "%s: '%s'\n", dev_name(Cameo_CPLD_30_data->hwmon_dev), client->name); + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ESCC601_SYS_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_LED_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_FAN_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_THERMAL_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_POWER_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_QSFP_group); + +exit_free: + kfree(Cameo_CPLD_30_data); + +exit: + return status; +} + +static int Cameo_i2c_remove(struct i2c_client *client) +{ + struct Cameo_i2c_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ESCC601_SYS_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_LED_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_FAN_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_THERMAL_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_POWER_group); + sysfs_remove_group(&client->dev.kobj, &ESCC601_QSFP_group); + + kfree(data); + return 0; +} + +static const struct i2c_device_id Cameo_i2c_id[] = +{ + { "Cameo_CPLD_30", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, Cameo_i2c_id); + +static struct i2c_driver Cameo_i2c_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = + { + .name = "ESCC_601_i2c", + }, + .probe = Cameo_i2c_probe, + .remove = Cameo_i2c_remove, + .id_table = Cameo_i2c_id, + .address_list = normal_i2c, +}; + +/*For main Switch board*/ +static struct i2c_board_info Cameo_CPLD_30_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_30", 0x30), + .platform_data = NULL, + }, +}; + +/*For QSFP Port 01 - 16*/ +static struct i2c_board_info Cameo_CPLD_31_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_31", 0x31), + .platform_data = NULL, + }, +}; +/*For QSFP Port 17 - 32*/ +static struct i2c_board_info Cameo_CPLD_32_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_32", 0x32), + .platform_data = NULL, + }, +}; +/*For Fan status*/ +static struct i2c_board_info Cameo_CPLD_23_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_23", 0x23), + .platform_data = NULL, + }, +}; +/*For Power status*/ +static struct i2c_board_info Cameo_CPLD_35_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_35", 0x35), + .platform_data = NULL, + }, +}; +/*For BMC Slave*/ +static struct i2c_board_info Cameo_BMC_14_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_BMC_14", 0x14), + .platform_data = NULL, + }, +}; + +static int __init Cameo_i2c_init(void) +{ + int ret; + int cmp; + char keyword[] = "SMBus I801"; + char buf1[128]; + struct i2c_adapter *i2c_adap; + struct file *fp; + mm_segment_t fs; + loff_t pos; + + printk("Open file...\n"); + fp = filp_open("/sys/class/i2c-dev/i2c-0/name", O_RDONLY , 0644); + if (IS_ERR(fp)) { + printk("Open file FAILED\n"); + return -1; + } + + fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_read(fp, buf1, sizeof(buf1), &pos); + printk("Detect %s\n", buf1); + cmp = strncmp(keyword, buf1, sizeof(keyword)-1); + set_fs(fs); + + filp_close(fp, NULL); + + if(cmp == 0) + { + i2c_adap = i2c_get_adapter(0); + printk("SMBus I801 is at bus 0\n"); + } + else + { + i2c_adap = i2c_get_adapter(1); + printk("SMBus I801 is at bus 1\n"); + } + + if (i2c_adap == NULL) + { + printk("ERROR: i2c_get_adapter FAILED!\n"); + return -1; + } + Cameo_CPLD_30_client = i2c_new_device(i2c_adap, &Cameo_CPLD_30_info[0]); + Cameo_CPLD_31_client = i2c_new_device(i2c_adap, &Cameo_CPLD_31_info[0]); + Cameo_CPLD_32_client = i2c_new_device(i2c_adap, &Cameo_CPLD_32_info[0]); + Cameo_CPLD_23_client = i2c_new_device(i2c_adap, &Cameo_CPLD_23_info[0]); + Cameo_CPLD_35_client = i2c_new_device(i2c_adap, &Cameo_CPLD_35_info[0]); + Cameo_BMC_14_client = i2c_new_device(i2c_adap, &Cameo_BMC_14_info[0]); + + if (Cameo_CPLD_30_info == NULL || Cameo_CPLD_31_info == NULL || Cameo_CPLD_32_info == NULL + || Cameo_CPLD_23_info == NULL || Cameo_CPLD_35_info == NULL || Cameo_BMC_14_info == NULL) + { + printk("ERROR: i2c_new_device FAILED!\n"); + return -1; + } + + i2c_put_adapter(i2c_adap); + ret = i2c_add_driver(&Cameo_i2c_driver); + printk(KERN_ALERT "ESCC601-32Q i2c Driver Version: %s\n", DRIVER_VERSION); + printk(KERN_ALERT "ESCC601-32Q i2c Driver INSTALL SUCCESS\n"); + return ret; +} + +static void __exit Cameo_i2c_exit(void) +{ + i2c_unregister_device(Cameo_CPLD_30_client); + i2c_unregister_device(Cameo_CPLD_31_client); + i2c_unregister_device(Cameo_CPLD_32_client); + i2c_unregister_device(Cameo_CPLD_23_client); + i2c_unregister_device(Cameo_CPLD_35_client); + i2c_unregister_device(Cameo_BMC_14_client); + i2c_del_driver(&Cameo_i2c_driver); + printk(KERN_ALERT "ESCC601-32Q i2c Driver UNINSTALL SUCCESS\n"); +} + +MODULE_AUTHOR("Cameo Inc."); +MODULE_DESCRIPTION("Cameo ESCC601-32Q i2c Driver"); +MODULE_LICENSE("GPL"); +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Enable debugging (0-1)"); + +module_init(Cameo_i2c_init); +module_exit(Cameo_i2c_exit); diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.h new file mode 100644 index 0000000000..39e5ab15e9 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-common.h @@ -0,0 +1,25 @@ +/* register offset define */ +#define ENABLE 1 +#define DISABLE 0 + +#define PASSED 1 +#define FAILED 0 + +#define TRUE 1 +#define FALSE 0 + +#define ABNORMAL 1 +#define NORMAL 0 + +#define BIT_0_MASK 0x01 +#define BIT_1_MASK 0x02 +#define BIT_2_MASK 0x04 +#define BIT_3_MASK 0x08 +#define BIT_4_MASK 0x10 +#define BIT_5_MASK 0x20 +#define BIT_6_MASK 0x40 +#define BIT_7_MASK 0x80 +/* end of register offset define */ + +int bmc_enable(void); +int read_8bit_temp(u8 sign,u8 value); \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.c new file mode 100644 index 0000000000..7ad84f817b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.c @@ -0,0 +1,365 @@ +/* An hwmon driver for Cameo escc601-32Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-escc601-32q.h" +#include "x86-64-cameo-escc601-32q-common.h" +#include "x86-64-cameo-escc601-32q-fan.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_23_client; //0x23 for Fan CPLD +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t fan_ctrl_mode_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_BMC_14_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == FANCTRL_MODE) + { + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, FANCTRL_MODE_REG); + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s0x%x\n", buf, status); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t fan_ctrl_rpm_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_BMC_14_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == FANCTRL_RPM) + { + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, FANCTRL_RPM_REG); + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s0x%x\n", buf, status); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_23_data = i2c_get_clientdata(Cameo_CPLD_23_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_23_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, FAN_STAT_REG); + mutex_unlock(&Cameo_CPLD_23_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = PASSED; + } + break; + case 5: + if(status & BIT_4_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_23_data = i2c_get_clientdata(Cameo_CPLD_23_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_PRESENT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_23_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, FAN_PRESENT_REG); + mutex_unlock(&Cameo_CPLD_23_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = PASSED; + } + break; + case 5: + if(status & BIT_4_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_23_data = i2c_get_clientdata(Cameo_CPLD_23_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_POWER_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_23_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, FAN_POWER_REG); + mutex_unlock(&Cameo_CPLD_23_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = PASSED; + } + break; + case 5: + if(status & BIT_4_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_rpm_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int fan_location = 0; + int fan_offset = 0; + u16 fan_speed = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *target_client = NULL; + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + target_client = Cameo_BMC_14_client; + } + else + { + target_client = Cameo_CPLD_23_client; + } + + switch (attr->index) + { + case FAN1_FRONT_RPM: + fan_location = 0; + fan_offset = 0; + break; + case FAN2_FRONT_RPM: + fan_location = 0; + fan_offset = 1; + break; + case FAN3_FRONT_RPM: + fan_location = 0; + fan_offset = 2; + break; + case FAN4_FRONT_RPM: + fan_location = 0; + fan_offset = 3; + break; + case FAN5_FRONT_RPM: + fan_location = 0; + fan_offset = 4; + break; + case FAN1_REAR_RPM: + fan_location = 1; + fan_offset = 0; + break; + case FAN2_REAR_RPM: + fan_location = 1; + fan_offset = 1; + break; + case FAN3_REAR_RPM: + fan_location = 1; + fan_offset = 2; + break; + case FAN4_REAR_RPM: + fan_location = 1; + fan_offset = 3; + break; + case FAN5_REAR_RPM: + fan_location = 1; + fan_offset = 4; + break; + } + if(fan_location == 0) + { + // front fan of couple + // read high byte + status = i2c_smbus_read_byte_data(target_client, FAN_F_RPM_REG+(fan_offset*2)+1); + fan_speed = status; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + // read low byte + status = i2c_smbus_read_byte_data(target_client, FAN_F_RPM_REG+(fan_offset*2)); + fan_speed = ((fan_speed<<8) + status)*30; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + } + else + { + // rear fan of couple + // read high byte + status = i2c_smbus_read_byte_data(target_client, FAN_R_RPM_REG+(fan_offset*2)+1); + fan_speed = status; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + // read low byte + status = i2c_smbus_read_byte_data(target_client, FAN_R_RPM_REG+(fan_offset*2)); + fan_speed = ((fan_speed<<8) + status)*30; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + } + sprintf(buf, "%s%d\n", buf, fan_speed); + return sprintf(buf, "%s\n",buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.h new file mode 100644 index 0000000000..66ffc93393 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-fan.h @@ -0,0 +1,12 @@ +/* register offset define */ +#define FANCTRL_RPM_REG 0x1a +#define FANCTRL_MODE_REG 0x1b +#define FAN_STAT_REG 0x00 +#define FAN_POWER_REG 0x01 +#define FAN_PRESENT_REG 0x02 +#define BMC_FAN_STAT_REG 0x80 +#define BMC_FAN_POWER_REG 0x81 +#define BMC_FAN_PRESENT_REG 0x82 +#define FAN_F_RPM_REG 0xa0 +#define FAN_R_RPM_REG 0xb0 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.c new file mode 100644 index 0000000000..d9b62acc37 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.c @@ -0,0 +1,220 @@ +/* An hwmon driver for Cameo escc601-32Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-escc601-32q.h" +#include "x86-64-cameo-escc601-32q-common.h" +#include "x86-64-cameo-escc601-32q-led.h" + +/* i2c_client Declaration */ +extern struct i2c_client *Cameo_CPLD_30_client; //0x30 for SYS CPLD +/* end of i2c_client Declaration */ + +/* implement i2c_function */ +ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int res = 0x1; + int i; + int led_a_status = 0; + int led_g_status = 0; + int led_b_status = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG); + sprintf(buf, ""); + + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_a_status = ENABLE; + } + else + { + led_a_status = DISABLE; + } + } + res = res << 1; + if( i == (attr->index + 1) ) + { + if (status & res) + { + led_g_status = ENABLE; + } + else + { + led_g_status = DISABLE; + } + } + res = res << 1; + } + res = 0x1; + + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_BLINK_REG); + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_b_status = ENABLE; + } + else + { + led_b_status = DISABLE; + } + } + res = res << 1; + } + if(led_a_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s2\n", buf); + } + else if(led_a_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s1\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s4\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s3\n", buf); + } + else + { + sprintf(buf, "%s0\n", buf); + } + + return sprintf(buf, "%s", buf); +} + +ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int led_value = -EPERM; + int blk_value = -EPERM; + int result = -EPERM; + int offset = 0; + u16 i; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + led_value = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG); + blk_value = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_BLINK_REG); + if (attr->index != 0) + { + i = simple_strtol(buf, NULL, 10); + if(attr->index == 1) + { + offset = 0; + } + else + { + offset = 2*((attr->index)-1); + } + switch(i) + { + case SWITCH_LED_OFF: //i=0 + led_value &= ~(0x03 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_N: //i=1 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_B: //i=2 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_N: //i=3 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_B: //i=4 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + default: + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + return count; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG, led_value); + result |= i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_BLINK_REG, blk_value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t led_fiber_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == LED_FIBER) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_FIBER_REG) & BIT_0_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} +ssize_t led_fiber_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG); + if (attr->index == LED_FIBER) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | LED_FIBER_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_FIBER_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & LED_FIBER_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_FIBER_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.h new file mode 100644 index 0000000000..c07a246447 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-led.h @@ -0,0 +1,12 @@ +/* register offset define */ +#define LED_CTRL_REG 0xa2 +#define LED_BLINK_REG 0xa3 +#define LED_FIBER_REG 0xa0 +#define LED_FIBER_ENABLE 0x01 +#define LED_FIBER_DISABLE 0xfe +#define SWITCH_LED_OFF 0 +#define SWITCH_LED_A_N 1 +#define SWITCH_LED_A_B 2 +#define SWITCH_LED_G_N 3 +#define SWITCH_LED_G_B 4 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.c new file mode 100644 index 0000000000..87231e21f7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.c @@ -0,0 +1,652 @@ +/* An hwmon driver for Cameo escc601-32Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-escc601-32q.h" +#include "x86-64-cameo-escc601-32q-common.h" +#include "x86-64-cameo-escc601-32q-power.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_35_client; //0x35 for Power CPLD +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* convert function */ +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} +/* end of convert function */ + +/* implement i2c_function */ +ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_PSU_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, PSU_STAT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = TRUE; + switch (attr->index) + { + case 1: + if(status & BIT_2_MASK) + { + result = FALSE; + } + break; + case 2: + if(status & BIT_3_MASK) + { + result = FALSE; + } + break; + } + if(result != TRUE) + { + return sprintf(buf, "%s%d\n", buf, FALSE); + } + return sprintf(buf, "%s%d\n", buf, TRUE); +} +ssize_t psu_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_PSU_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, PSU_STAT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = FALSE; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = TRUE; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = TRUE; + } + break; + } + if(result != TRUE) + { + return sprintf(buf, "%s%d\n", buf, FALSE); + } + return sprintf(buf, "%s%d\n", buf, TRUE); +} +ssize_t psu_vin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_VIN_REG); + break; + case PSU2_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_VIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t psu_iin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_IIN_REG); + break; + case PSU2_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_IIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t psu_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0; + int multiplier = 1000; + u16 u16_vmode = 0; + u16 u16_vout = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_VOUT_REG); + break; + case PSU2_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_VOUT_REG); + break; + } + if(u16_vout == 0xffff || u16_vout == -1) + { + return sprintf(buf, "%s0\n", buf); + } + /* vout mode */ + multiplier = 1000; + exponent = two_complement_to_int(u16_vmode & 0x1f, 5, 0x1f); + /* vout */ + result = (exponent >= 0) ? ((u16_vout << exponent)*multiplier) : \ + (u16_vout*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_IOUT_REG); + break; + case PSU2_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_IOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_temp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_TEMP_1_REG); + break; + case PSU2_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_TEMP_1_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_fan_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_FAN_SPEED_REG); + break; + case PSU2_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_FAN_SPEED_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_pout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_POUT_REG); + break; + case PSU2_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_POUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_pin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_PIN_REG); + break; + case PSU2_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_PIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 u16_val = 0; + char model[I2C_SMBUS_BLOCK_MAX] = {0}; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_1_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + case PSU2_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_2_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + } + if(u16_val != I2C_SMBUS_BLOCK_MAX) + { + return sprintf(buf, "%sERROR\n", buf); + } + if (model[1] < 0x20 || model[1] > 0x7f) + { + return sprintf(buf, "%sERROR\n", buf); + } + sprintf(buf, "%s%s", buf, model); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_iout_max_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_MFR_IOUT_MAX_REG); + break; + case PSU2_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_MFR_IOUT_MAX_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_vmode_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 u16_vmode = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); + break; + case PSU2_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); + break; + } + if(u16_vmode == 0xffff || u16_vmode == -1) + { + return sprintf(buf, "%s0\n", buf); + } + /* vout mode */ + sprintf(buf, "%s%d\n", buf, u16_vmode); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC6E_P0_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P0_VOUT_REG); + break; + case DC6E_P1_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P1_VOUT_REG); + break; + case DC70_P0_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P0_VOUT_REG); + break; + case DC70_P1_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P1_VOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC6E_P0_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P0_IOUT_REG); + break; + case DC6E_P1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P1_IOUT_REG); + break; + case DC70_P0_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P0_IOUT_REG); + break; + case DC70_P1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P1_IOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_pout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC6E_P0_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P0_POUT_REG); + break; + case DC6E_P1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P1_POUT_REG); + break; + case DC70_P0_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P0_POUT_REG); + break; + case DC70_P1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P1_POUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.h new file mode 100644 index 0000000000..2290699ff9 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-power.h @@ -0,0 +1,38 @@ +/* register offset define */ +#define PSU_STAT_REG 0xa0 +#define BMC_PSU_STAT_REG 0xc0 +#define PSU_1_VIN_REG 0x50 +#define PSU_1_IIN_REG 0x51 +#define PSU_1_VOUT_REG 0x52 +#define PSU_1_IOUT_REG 0x53 +#define PSU_1_TEMP_1_REG 0x54 +#define PSU_1_FAN_SPEED_REG 0x55 +#define PSU_1_POUT_REG 0x56 +#define PSU_1_PIN_REG 0x57 +#define PSU_1_MFR_MODEL_REG 0x58 +#define PSU_1_MFR_IOUT_MAX_REG 0x59 +#define PSU_1_VMODE_REG 0x5a +#define PSU_2_VIN_REG 0x60 +#define PSU_2_IIN_REG 0x61 +#define PSU_2_VOUT_REG 0x62 +#define PSU_2_IOUT_REG 0x63 +#define PSU_2_TEMP_1_REG 0x64 +#define PSU_2_FAN_SPEED_REG 0x65 +#define PSU_2_POUT_REG 0x66 +#define PSU_2_PIN_REG 0x67 +#define PSU_2_MFR_MODEL_REG 0x68 +#define PSU_2_MFR_IOUT_MAX_REG 0x69 +#define PSU_2_VMODE_REG 0x6a +#define DC_CHIP_6E_P0_VOUT_REG 0x90 +#define DC_CHIP_6E_P0_IOUT_REG 0x91 +#define DC_CHIP_6E_P0_POUT_REG 0x92 +#define DC_CHIP_6E_P1_VOUT_REG 0x94 +#define DC_CHIP_6E_P1_IOUT_REG 0x95 +#define DC_CHIP_6E_P1_POUT_REG 0x96 +#define DC_CHIP_70_P0_VOUT_REG 0x98 +#define DC_CHIP_70_P0_IOUT_REG 0x99 +#define DC_CHIP_70_P0_POUT_REG 0x9a +#define DC_CHIP_70_P1_VOUT_REG 0x9c +#define DC_CHIP_70_P1_IOUT_REG 0x9d +#define DC_CHIP_70_P1_POUT_REG 0x9e +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.c new file mode 100644 index 0000000000..6fc4db76cc --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.c @@ -0,0 +1,584 @@ +/* An hwmon driver for Cameo escc601-32Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-escc601-32q.h" +#include "x86-64-cameo-escc601-32q-common.h" +#include "x86-64-cameo-escc601-32q-qsfp.h" + +/* i2c_client Declaration */ +extern struct i2c_client *Cameo_CPLD_31_client; //0x31 for Port 01-16 +extern struct i2c_client *Cameo_CPLD_32_client; //0x32 for Port 17-32 +/* end of i2c_client Declaration */ + +/* extern i2c_function */ +/* end of extern i2c_function */ + +/* implement i2c_function */ +ssize_t qsfp_low_power_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == QSFP_LOW_POWER_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_REAR_LOW_POWER_REG); //25-32 + result = status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_FRONT_LOW_POWER_REG); //17-24 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, QSFP_REAR_LOW_POWER_REG); //9-16 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, QSFP_FRONT_LOW_POWER_REG); //1-8 + result = (result << 8) | status; + sprintf(buf, "%s0x%x\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_low_power_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int value = 0x0; + int result = 0; + int input = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + if (attr->index == QSFP_LOW_POWER_ALL) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = 0xff; + } + else if(input == DISABLE) + { + value = 0x00; + } + else + { + printk(KERN_ALERT "qsfp_low_power_all_set wrong value\n"); + return count; + } + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, QSFP_FRONT_LOW_POWER_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, QSFP_REAR_LOW_POWER_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, QSFP_FRONT_LOW_POWER_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, QSFP_REAR_LOW_POWER_REG, value); + + if(result != 0) + { + printk(KERN_ALERT "qsfp_low_power_all_set FAILED\n"); + return count; + } + } + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + return count; +} + +ssize_t qsfp_low_power_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 16) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, qsfp_low_power_regs[port_index][0]); + } + else if (port_index >= 17 && port_index <= 32) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_low_power_regs[port_index][0]); + } + + if (status & qsfp_low_power_regs[port_index][1]) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_low_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + port_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (port_index >= 1 && port_index <= 16) + { + target_client = Cameo_CPLD_31_client; + + } + else if (port_index >= 17 && port_index <= 32) + { + target_client = Cameo_CPLD_32_client; + } + + status = i2c_smbus_read_byte_data(target_client, qsfp_low_power_regs[port_index][0]); + if( input == ENABLE) + { + status |= qsfp_low_power_regs[port_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_low_power_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_low_power_set ON FAILED!\n"); + } + } + else if( input == DISABLE) + { + status &= ~(qsfp_low_power_regs[port_index][1]); + result = i2c_smbus_write_byte_data(target_client, qsfp_low_power_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_low_power_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_low_power_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} + +ssize_t qsfp_reset_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int value = 0x0; + int result = 0; + int input = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + if (attr->index == QSFP_RESET_ALL) + { + input = simple_strtol(buf, NULL, 10); + if (input == QSFP_RESET) + { + value = 0x00; + } + else + { + printk(KERN_ALERT "qsfp_reset_all_set wrong value\n"); + return count; + } + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, QSFP_FRONT_RESET_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, QSFP_REAR_RESET_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, QSFP_FRONT_RESET_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, QSFP_REAR_RESET_REG, value); + + if(result != 0) + { + printk(KERN_ALERT "qsfp_reset_all_set FAILED\n"); + return count; + } + } + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + return count; +} + +ssize_t qsfp_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + port_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (port_index >= 1 && port_index <= 16) + { + target_client = Cameo_CPLD_31_client; + + } + else if (port_index >= 17 && port_index <= 32) + { + target_client = Cameo_CPLD_32_client; + } + + status = i2c_smbus_read_byte_data(target_client, qsfp_reset_regs[port_index][0]); + if( input == QSFP_RESET) + { + status |= qsfp_reset_regs[port_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_reset_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_reset_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_reset_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} + +ssize_t qsfp_present_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == QSFP_PRESENT_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_REAR_PRESENT_REG); //25-32 + result = status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_FRONT_PRESENT_REG); //17-24 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, QSFP_REAR_PRESENT_REG); //9-16 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, QSFP_FRONT_PRESENT_REG); //1-8 + result = (result << 8) | status; + result = ~(result); + sprintf(buf, "%s0x%x\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 16) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, qsfp_present_regs[port_index][0]); + } + else if (port_index >= 17 && port_index <= 32) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_present_regs[port_index][0]); + } + + if (status & qsfp_present_regs[port_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} +ssize_t qsfp_int_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == QSFP_INT_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_REAR_INT_REG); //25-32 + result = status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_FRONT_INT_REG); //17-24 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, QSFP_REAR_INT_REG); //9-16 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, QSFP_FRONT_INT_REG); //1-8 + result = (result << 8) | status; + sprintf(buf, "%s0x%x\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t qsfp_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 16) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, qsfp_int_regs[port_index][0]); + } + else if (port_index >= 17 && port_index <= 32) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_int_regs[port_index][0]); + } + + if (status & qsfp_int_regs[port_index][1]) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_quter_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + if (quter_index >= 1 && quter_index <= 2) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, qsfp_quter_int_regs[quter_index][0]); + } + else if (quter_index >= 3 && quter_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_quter_int_regs[quter_index][0]); + } + + if (status & qsfp_quter_int_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_quter_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + if (quter_index >= 1 && quter_index <= 2) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, qsfp_quter_int_mask_regs[quter_index][0]); + } + else if (quter_index >= 3 && quter_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_quter_int_mask_regs[quter_index][0]); + } + + if (status & qsfp_quter_int_mask_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_quter_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + quter_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (quter_index >= 1 && quter_index <= 2) + { + target_client = Cameo_CPLD_31_client; + + } + else if (quter_index >= 3 && quter_index <= 4) + { + target_client = Cameo_CPLD_32_client; + } + + status = i2c_smbus_read_byte_data(target_client, qsfp_quter_int_mask_regs[quter_index][0]); + if( input == DISABLE) + { + status |= qsfp_quter_int_mask_regs[quter_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_quter_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_quter_int_mask_set ON FAILED!\n"); + } + } + else if( input == ENABLE) + { + status &= ~(qsfp_quter_int_mask_regs[quter_index][1]); + result = i2c_smbus_write_byte_data(target_client, qsfp_quter_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_quter_int_mask_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_quter_int_mask_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} + +ssize_t qsfp_modprs_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + if (quter_index >= 1 && quter_index <= 2) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, qsfp_modprs_int_regs[quter_index][0]); + } + else if (quter_index >= 3 && quter_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_modprs_int_regs[quter_index][0]); + } + + if (status & qsfp_modprs_int_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_modprs_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + if (quter_index >= 1 && quter_index <= 2) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, qsfp_modprs_int_mask_regs[quter_index][0]); + } + else if (quter_index >= 3 && quter_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_modprs_int_mask_regs[quter_index][0]); + } + + if (status & qsfp_modprs_int_mask_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_modprs_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + quter_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (quter_index >= 1 && quter_index <= 2) + { + target_client = Cameo_CPLD_31_client; + + } + else if (quter_index >= 3 && quter_index <= 4) + { + target_client = Cameo_CPLD_32_client; + } + + status = i2c_smbus_read_byte_data(target_client, qsfp_modprs_int_mask_regs[quter_index][0]); + if( input == DISABLE) + { + status |= qsfp_modprs_int_mask_regs[quter_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_modprs_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_modprs_int_mask_set ON FAILED!\n"); + } + } + else if( input == ENABLE) + { + status &= ~(qsfp_modprs_int_mask_regs[quter_index][1]); + result = i2c_smbus_write_byte_data(target_client, qsfp_modprs_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_modprs_int_mask_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_modprs_int_mask_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.h new file mode 100644 index 0000000000..a1deb8f3d7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-qsfp.h @@ -0,0 +1,187 @@ +/* register offset define */ +#define QSFP_FRONT_LOW_POWER_REG 0x60 +#define QSFP_REAR_LOW_POWER_REG 0x61 +#define QSFP_FRONT_RESET_REG 0x70 +#define QSFP_REAR_RESET_REG 0x71 +#define QSFP_FRONT_PRESENT_REG 0x80 +#define QSFP_REAR_PRESENT_REG 0x81 +#define QSFP_FRONT_INT_REG 0x90 +#define QSFP_REAR_INT_REG 0x91 +#define QSFP_RESET 1 + +unsigned char qsfp_low_power_regs[33][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x60, 0x01}, + {0x60, 0x02}, + {0x60, 0x04}, + {0x60, 0x08}, + {0x60, 0x10}, + {0x60, 0x20}, + {0x60, 0x40}, + {0x60, 0x80}, + {0x61, 0x01}, + {0x61, 0x02}, + {0x61, 0x04}, + {0x61, 0x08}, + {0x61, 0x10}, + {0x61, 0x20}, + {0x61, 0x40}, + {0x61, 0x80}, + {0x60, 0x01}, + {0x60, 0x02}, + {0x60, 0x04}, + {0x60, 0x08}, + {0x60, 0x10}, + {0x60, 0x20}, + {0x60, 0x40}, + {0x60, 0x80}, + {0x61, 0x01}, + {0x61, 0x02}, + {0x61, 0x04}, + {0x61, 0x08}, + {0x61, 0x10}, + {0x61, 0x20}, + {0x61, 0x40}, + {0x61, 0x80} +}; + +unsigned char qsfp_reset_regs[33][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x70, 0x01}, + {0x70, 0x02}, + {0x70, 0x04}, + {0x70, 0x08}, + {0x70, 0x10}, + {0x70, 0x20}, + {0x70, 0x40}, + {0x70, 0x80}, + {0x71, 0x01}, + {0x71, 0x02}, + {0x71, 0x04}, + {0x71, 0x08}, + {0x71, 0x10}, + {0x71, 0x20}, + {0x71, 0x40}, + {0x71, 0x80}, + {0x70, 0x01}, + {0x70, 0x02}, + {0x70, 0x04}, + {0x70, 0x08}, + {0x70, 0x10}, + {0x70, 0x20}, + {0x70, 0x40}, + {0x70, 0x80}, + {0x71, 0x01}, + {0x71, 0x02}, + {0x71, 0x04}, + {0x71, 0x08}, + {0x71, 0x10}, + {0x71, 0x20}, + {0x71, 0x40}, + {0x71, 0x80} +}; + +unsigned char qsfp_present_regs[33][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x80, 0x01}, + {0x80, 0x02}, + {0x80, 0x04}, + {0x80, 0x08}, + {0x80, 0x10}, + {0x80, 0x20}, + {0x80, 0x40}, + {0x80, 0x80}, + {0x81, 0x01}, + {0x81, 0x02}, + {0x81, 0x04}, + {0x81, 0x08}, + {0x81, 0x10}, + {0x81, 0x20}, + {0x81, 0x40}, + {0x81, 0x80}, + {0x80, 0x01}, + {0x80, 0x02}, + {0x80, 0x04}, + {0x80, 0x08}, + {0x80, 0x10}, + {0x80, 0x20}, + {0x80, 0x40}, + {0x80, 0x80}, + {0x81, 0x01}, + {0x81, 0x02}, + {0x81, 0x04}, + {0x81, 0x08}, + {0x81, 0x10}, + {0x81, 0x20}, + {0x81, 0x40}, + {0x81, 0x80} +}; + +unsigned char qsfp_int_regs[33][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x90, 0x01}, + {0x90, 0x02}, + {0x90, 0x04}, + {0x90, 0x08}, + {0x90, 0x10}, + {0x90, 0x20}, + {0x90, 0x40}, + {0x90, 0x80}, + {0x91, 0x01}, + {0x91, 0x02}, + {0x91, 0x04}, + {0x91, 0x08}, + {0x91, 0x10}, + {0x91, 0x20}, + {0x91, 0x40}, + {0x91, 0x80}, + {0x90, 0x01}, + {0x90, 0x02}, + {0x90, 0x04}, + {0x90, 0x08}, + {0x90, 0x10}, + {0x90, 0x20}, + {0x90, 0x40}, + {0x90, 0x80}, + {0x91, 0x01}, + {0x91, 0x02}, + {0x91, 0x04}, + {0x91, 0x08}, + {0x91, 0x10}, + {0x91, 0x20}, + {0x91, 0x40}, + {0x91, 0x80} +}; + +unsigned char qsfp_quter_int_regs[5][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd0, 0x04}, + {0xd0, 0x08}, + {0xd0, 0x04}, + {0xd0, 0x08} +}; + +unsigned char qsfp_quter_int_mask_regs[5][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd1, 0x04}, + {0xd1, 0x08}, + {0xd1, 0x04}, + {0xd1, 0x08} +}; + +unsigned char qsfp_modprs_int_regs[5][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd0, 0x01}, + {0xd0, 0x02}, + {0xd0, 0x01}, + {0xd0, 0x02} +}; + +unsigned char qsfp_modprs_int_mask_regs[5][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd1, 0x01}, + {0xd1, 0x02}, + {0xd1, 0x01}, + {0xd1, 0x02} +}; +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.c new file mode 100644 index 0000000000..4c6668fcd0 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.c @@ -0,0 +1,789 @@ +/* An hwmon driver for Cameo escc601-32Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-escc601-32q.h" +#include "x86-64-cameo-escc601-32q-common.h" +#include "x86-64-cameo-escc601-32q-sys.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_30_client; //0x30 for SYS CPLD +extern struct i2c_client *Cameo_CPLD_31_client; //0x31 for Port 01-16 +extern struct i2c_client *Cameo_CPLD_32_client; //0x32 for Port 17-32 +extern struct i2c_client *Cameo_CPLD_23_client; //0x23 for Fan CPLD +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t cpld_hw_ver_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case 23: + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, 0xff); + } + else + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, CPLD_VER_REG); + } + break; + case 30: + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, CPLD_VER_REG); + break; + case 31: + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, CPLD_VER_REG); + break; + case 32: + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, CPLD_VER_REG); + break; + } + if(status < 0) + { + mutex_unlock(&data->update_lock); + return status; + } + else + { + mutex_unlock(&data->update_lock); + sprintf(buf, "%s0x%x\n", buf, status); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t wdt_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == WDT_EN) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, WDT_EN_REG) & BIT_4_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t wdt_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, WDT_EN_REG); + if (attr->index == WDT_EN) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | WDT_EN_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, WDT_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: wdt_enable_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & WDT_EN_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, WDT_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: wdt_enable_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "wdt_enable_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t eeprom_wp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == EEPROM_WP) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG) & BIT_2_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t eeprom_wp_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG); + if (attr->index == EEPROM_WP) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | EEPROM_WP_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: eeprom_wp_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & EEPROM_WP_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: eeprom_wp_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "eeprom_wp_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t usb_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == USB_EN) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG) & BIT_1_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t usb_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG); + if (attr->index == USB_EN) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | USB_EN_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, USB_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: usb_enable_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & USB_EN_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, USB_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: usb_enable_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "usb_enable_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t reset_mac_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MAC_RESET_REG); + if (attr->index == RESET) + { + input = simple_strtol(buf, NULL, 10); + if (input == MAC_RESET) + { + value = MAC_RESET; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, MAC_RESET_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: reset_mac_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "reset_mac_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t shutdown_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SHUTDOWN_REG); + if (attr->index == SHUTDOWN_SET) + { + input = simple_strtol(buf, NULL, 10); + if (input == SHUTDOWN) + { + value = status | SHUTDOWN; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, SHUTDOWN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: shutdown_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "shutdown_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t bmc_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == BMC_PRESENT) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, BMC_EN_REG) & BIT_0_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case TEMP_R_B_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_L_B_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_L_T_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_R_T_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case TEMP_R_B_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_L_B_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_L_T_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_R_T_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + switch (attr->index) + { + case TEMP_R_B_INT_MASK: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + case TEMP_L_B_INT_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + case TEMP_L_T_INT_MASK: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + case TEMP_R_T_INT_MASK: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t sys_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case CPLD_FP_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_RP_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_FAN_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_PSU_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case THERMAL_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_6_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case USB_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_7_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sys_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case CPLD_FP_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_RP_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_FAN_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_PSU_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case THERMAL_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_6_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case USB_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_7_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sys_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + switch (attr->index) + { + case CPLD_FP_INT_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case CPLD_RP_INT_MASK: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case CPLD_FAN_INT_MASK: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case CPLD_PSU_INT_MASK: + if (input == ENABLE) + { + value = status | 0x10; + } + else if (input == DISABLE) + { + value = status & 0xef; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case THERMAL_INT_MASK: + if (input == ENABLE) + { + value = status | 0x20; + } + else if (input == DISABLE) + { + value = status & 0xdf; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case USB_INT_MASK: + if (input == ENABLE) + { + value = status | 0x40; + } + else if (input == DISABLE) + { + value = status & 0xbf; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.h new file mode 100644 index 0000000000..400aeaf3d7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-sys.h @@ -0,0 +1,23 @@ +/* register offset define */ +#define CPLD_VER_REG 0x20 +#define WDT_EN_REG 0xa0 +#define WDT_EN_ENABLE 0x10 +#define WDT_EN_DISABLE 0xef +#define EEPROM_WP_REG 0xa0 +#define EEPROM_WP_ENABLE 0x04 +#define EEPROM_WP_DISABLE 0xfB +#define USB_EN_REG 0xa0 +#define USB_EN_ENABLE 0x02 +#define USB_EN_DISABLE 0xfD +#define MAC_RESET_REG 0xa1 +#define MAC_RESET 0x00 +#define SHUTDOWN_REG 0xa1 +#define SHUTDOWN 0x10 +#define BMC_EN_REG 0xa4 +#define BMC_EN_ENABLE 0x01 +#define BMC_EN_DISABLE 0x00 +#define THERMAL_INT_REG 0xc0 +#define THERMAL_INT_MASK_REG 0xc1 +#define SYS_INT_REG 0xd0 +#define SYS_INT_MASK_REG 0xd1 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.c new file mode 100644 index 0000000000..cb490ace02 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.c @@ -0,0 +1,271 @@ +/* An hwmon driver for Cameo escc601-32Q Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-escc601-32q.h" +#include "x86-64-cameo-escc601-32q-common.h" +#include "x86-64-cameo-escc601-32q-thermal.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_R_B_F: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_F_REG); + break; + case TEMP_R_B_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_B_REG); + break; + case TEMP_L_B_F: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_F_REG); + break; + case TEMP_L_B_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_B_REG); + break; + case TEMP_R_T_F: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_F_REG); + break; + case TEMP_R_T_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_B_REG); + break; + case TEMP_L_T_F: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_F_REG); + break; + case TEMP_L_T_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_B_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_max_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_R_B_F_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_F_MAX_REG); + break; + case TEMP_L_B_F_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_F_MAX_REG); + break; + case TEMP_R_T_F_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_F_MAX_REG); + break; + case TEMP_L_T_F_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_F_MAX_REG); + break; + case TEMP_R_B_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_B_MAX_REG); + break; + case TEMP_L_B_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_B_MAX_REG); + break; + case TEMP_R_T_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_B_MAX_REG); + break; + case TEMP_L_T_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_B_MAX_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_min_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_R_B_F_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_F_MIN_REG); + break; + case TEMP_L_B_F_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_F_MIN_REG); + break; + case TEMP_R_T_F_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_F_MIN_REG); + break; + case TEMP_L_T_F_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_F_MIN_REG); + break; + case TEMP_R_B_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_B_MIN_REG); + break; + case TEMP_L_B_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_B_MIN_REG); + break; + case TEMP_R_T_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_B_MIN_REG); + break; + case TEMP_L_T_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_B_MIN_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_crit_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_R_B_F_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_F_CRIT_REG); + break; + case TEMP_L_B_F_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_F_CRIT_REG); + break; + case TEMP_R_T_F_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_F_CRIT_REG); + break; + case TEMP_L_T_F_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_F_CRIT_REG); + break; + case TEMP_R_B_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_B_CRIT_REG); + break; + case TEMP_L_B_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_B_CRIT_REG); + break; + case TEMP_R_T_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_B_CRIT_REG); + break; + case TEMP_L_T_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_B_CRIT_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_lcrit_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_R_B_F_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_F_LCRIT_REG); + break; + case TEMP_L_B_F_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_F_LCRIT_REG); + break; + case TEMP_R_T_F_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_F_LCRIT_REG); + break; + case TEMP_L_T_F_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_F_LCRIT_REG); + break; + case TEMP_R_B_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_B_B_LCRIT_REG); + break; + case TEMP_L_B_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_B_B_LCRIT_REG); + break; + case TEMP_R_T_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_R_T_B_LCRIT_REG); + break; + case TEMP_L_T_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_L_T_B_LCRIT_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.h new file mode 100644 index 0000000000..54b95a3869 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q-thermal.h @@ -0,0 +1,45 @@ +/* register offset define */ +#define TEMP_R_B_F_REG 0x10 +#define TEMP_R_B_B_REG 0x11 +#define TEMP_R_B_F_MAX_REG 0x12 +#define TEMP_R_B_F_MIN_REG 0x13 +#define TEMP_R_B_F_CRIT_REG 0x14 +#define TEMP_R_B_F_LCRIT_REG 0x15 +#define TEMP_R_B_B_MAX_REG 0x16 +#define TEMP_R_B_B_MIN_REG 0x17 +#define TEMP_R_B_B_CRIT_REG 0x18 +#define TEMP_R_B_B_LCRIT_REG 0x19 + +#define TEMP_L_B_F_REG 0x20 +#define TEMP_L_B_B_REG 0x21 +#define TEMP_L_B_F_MAX_REG 0x22 +#define TEMP_L_B_F_MIN_REG 0x23 +#define TEMP_L_B_F_CRIT_REG 0x24 +#define TEMP_L_B_F_LCRIT_REG 0x25 +#define TEMP_L_B_B_MAX_REG 0x26 +#define TEMP_L_B_B_MIN_REG 0x27 +#define TEMP_L_B_B_CRIT_REG 0x28 +#define TEMP_L_B_B_LCRIT_REG 0x29 + +#define TEMP_R_T_F_REG 0x30 +#define TEMP_R_T_B_REG 0x31 +#define TEMP_R_T_F_MAX_REG 0x32 +#define TEMP_R_T_F_MIN_REG 0x33 +#define TEMP_R_T_F_CRIT_REG 0x34 +#define TEMP_R_T_F_LCRIT_REG 0x35 +#define TEMP_R_T_B_MAX_REG 0x36 +#define TEMP_R_T_B_MIN_REG 0x37 +#define TEMP_R_T_B_CRIT_REG 0x38 +#define TEMP_R_T_B_LCRIT_REG 0x39 + +#define TEMP_L_T_F_REG 0x40 +#define TEMP_L_T_B_REG 0x41 +#define TEMP_L_T_F_MAX_REG 0x42 +#define TEMP_L_T_F_MIN_REG 0x43 +#define TEMP_L_T_F_CRIT_REG 0x44 +#define TEMP_L_T_F_LCRIT_REG 0x45 +#define TEMP_L_T_B_MAX_REG 0x46 +#define TEMP_L_T_B_MIN_REG 0x47 +#define TEMP_L_T_B_CRIT_REG 0x48 +#define TEMP_L_T_B_LCRIT_REG 0x49 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q.h b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q.h new file mode 100644 index 0000000000..e6a0c9ee3b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/x86-64-cameo-escc601-32q.h @@ -0,0 +1,1044 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "1.0.3" + +struct i2c_adap { + int nr; + char *name; + const char *funcs; + const char *algo; +}; + +struct i2c_adap *gather_i2c_busses(void); +void free_adapters(struct i2c_adap *adapters); + +/* compiler conditional */ +/* end of compiler conditional */ + +/* Function Declaration */ +/* i2c-0 */ +ssize_t cpld_hw_ver_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t wdt_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t wdt_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t eeprom_wp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t eeprom_wp_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t usb_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t usb_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t reset_mac_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t shutdown_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t bmc_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t led_fiber_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_fiber_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t themal_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sys_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sys_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sys_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_max_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_min_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_crit_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_lcrit_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_ctrl_mode_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_ctrl_rpm_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_rpm_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_temp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_fan_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_pout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_pin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iout_max_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vmode_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_pout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_low_power_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_low_power_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_low_power_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_low_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_reset_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_present_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_int_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_quter_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_quter_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_quter_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_modprs_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_modprs_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_modprs_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +/* end of Function Declaration */ + +/* struct i2c_data */ +struct Cameo_i2c_data +{ + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; + u8 status; +}; + +/* struct i2c_sysfs_attributes */ +enum Cameo_i2c_sysfs_attributes +{ + CPLD_23_VER, + CPLD_30_VER, + CPLD_31_VER, + CPLD_32_VER, + WDT_EN, + EEPROM_WP, + USB_EN, + SHUTDOWN_SET, + RESET, + BMC_PRESENT, + LED_1, + LED_2, + LED_FLOW, + LED_SYS, + LED_FIBER, + TEMP_R_B_INT, + TEMP_L_B_INT, + TEMP_R_T_INT, + TEMP_L_T_INT, + TEMP_R_B_INT_MASK, + TEMP_L_B_INT_MASK, + TEMP_R_T_INT_MASK, + TEMP_L_T_INT_MASK, + CPLD_FP_INT, + CPLD_RP_INT, + CPLD_FAN_INT, + CPLD_PSU_INT, + THERMAL_INT, + USB_INT, + CPLD_FP_INT_MASK, + CPLD_RP_INT_MASK, + CPLD_FAN_INT_MASK, + CPLD_PSU_INT_MASK, + THERMAL_INT_MASK, + USB_INT_MASK, + TEMP_R_B_F, + TEMP_R_B_B, + TEMP_L_B_F, + TEMP_L_B_B, + TEMP_R_T_F, + TEMP_R_T_B, + TEMP_L_T_F, + TEMP_L_T_B, + TEMP_R_B_F_MAX, + TEMP_L_B_F_MAX, + TEMP_R_T_F_MAX, + TEMP_L_T_F_MAX, + TEMP_R_B_B_MAX, + TEMP_L_B_B_MAX, + TEMP_R_T_B_MAX, + TEMP_L_T_B_MAX, + TEMP_R_B_F_MIN, + TEMP_L_B_F_MIN, + TEMP_R_T_F_MIN, + TEMP_L_T_F_MIN, + TEMP_R_B_B_MIN, + TEMP_L_B_B_MIN, + TEMP_R_T_B_MIN, + TEMP_L_T_B_MIN, + TEMP_R_B_F_CRIT, + TEMP_L_B_F_CRIT, + TEMP_R_T_F_CRIT, + TEMP_L_T_F_CRIT, + TEMP_R_B_B_CRIT, + TEMP_L_B_B_CRIT, + TEMP_R_T_B_CRIT, + TEMP_L_T_B_CRIT, + TEMP_R_B_F_LCRIT, + TEMP_L_B_F_LCRIT, + TEMP_R_T_F_LCRIT, + TEMP_L_T_F_LCRIT, + TEMP_R_B_B_LCRIT, + TEMP_L_B_B_LCRIT, + TEMP_R_T_B_LCRIT, + TEMP_L_T_B_LCRIT, + FANCTRL_RPM, + FANCTRL_MODE, + FAN1_STAT, + FAN2_STAT, + FAN3_STAT, + FAN4_STAT, + FAN5_STAT, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN1_POWER, + FAN2_POWER, + FAN3_POWER, + FAN4_POWER, + FAN5_POWER, + FAN1_FRONT_RPM, + FAN2_FRONT_RPM, + FAN3_FRONT_RPM, + FAN4_FRONT_RPM, + FAN5_FRONT_RPM, + FAN1_REAR_RPM, + FAN2_REAR_RPM, + FAN3_REAR_RPM, + FAN4_REAR_RPM, + FAN5_REAR_RPM, + PSU1_GOOD, + PSU2_GOOD, + PSU1_PRNT, + PSU2_PRNT, + PSU1_VIN, + PSU1_IIN, + PSU1_VOUT, + PSU1_IOUT, + PSU1_TEMP, + PSU1_FAN_SPEED, + PSU1_POUT, + PSU1_PIN, + PSU1_MFR_MODEL, + PSU1_MFR_IOUT_MAX, + PSU1_VMODE, + PSU2_VIN, + PSU2_IIN, + PSU2_VOUT, + PSU2_IOUT, + PSU2_TEMP, + PSU2_FAN_SPEED, + PSU2_POUT, + PSU2_PIN, + PSU2_MFR_MODEL, + PSU2_MFR_IOUT_MAX, + PSU2_VMODE, + DC6E_P0_VOUT, + DC6E_P0_IOUT, + DC6E_P0_POUT, + DC6E_P1_VOUT, + DC6E_P1_IOUT, + DC6E_P1_POUT, + DC70_P0_VOUT, + DC70_P0_IOUT, + DC70_P0_POUT, + DC70_P1_VOUT, + DC70_P1_IOUT, + DC70_P1_POUT, + QSFP_LOW_POWER_ALL, + QSFP1_LOW_POWER, + QSFP2_LOW_POWER, + QSFP3_LOW_POWER, + QSFP4_LOW_POWER, + QSFP5_LOW_POWER, + QSFP6_LOW_POWER, + QSFP7_LOW_POWER, + QSFP8_LOW_POWER, + QSFP9_LOW_POWER, + QSFP10_LOW_POWER, + QSFP11_LOW_POWER, + QSFP12_LOW_POWER, + QSFP13_LOW_POWER, + QSFP14_LOW_POWER, + QSFP15_LOW_POWER, + QSFP16_LOW_POWER, + QSFP17_LOW_POWER, + QSFP18_LOW_POWER, + QSFP19_LOW_POWER, + QSFP20_LOW_POWER, + QSFP21_LOW_POWER, + QSFP22_LOW_POWER, + QSFP23_LOW_POWER, + QSFP24_LOW_POWER, + QSFP25_LOW_POWER, + QSFP26_LOW_POWER, + QSFP27_LOW_POWER, + QSFP28_LOW_POWER, + QSFP29_LOW_POWER, + QSFP30_LOW_POWER, + QSFP31_LOW_POWER, + QSFP32_LOW_POWER, + QSFP_RESET_ALL, + QSFP1_RESET, + QSFP2_RESET, + QSFP3_RESET, + QSFP4_RESET, + QSFP5_RESET, + QSFP6_RESET, + QSFP7_RESET, + QSFP8_RESET, + QSFP9_RESET, + QSFP10_RESET, + QSFP11_RESET, + QSFP12_RESET, + QSFP13_RESET, + QSFP14_RESET, + QSFP15_RESET, + QSFP16_RESET, + QSFP17_RESET, + QSFP18_RESET, + QSFP19_RESET, + QSFP20_RESET, + QSFP21_RESET, + QSFP22_RESET, + QSFP23_RESET, + QSFP24_RESET, + QSFP25_RESET, + QSFP26_RESET, + QSFP27_RESET, + QSFP28_RESET, + QSFP29_RESET, + QSFP30_RESET, + QSFP31_RESET, + QSFP32_RESET, + QSFP_PRESENT_ALL, + QSFP1_PRESENT, + QSFP2_PRESENT, + QSFP3_PRESENT, + QSFP4_PRESENT, + QSFP5_PRESENT, + QSFP6_PRESENT, + QSFP7_PRESENT, + QSFP8_PRESENT, + QSFP9_PRESENT, + QSFP10_PRESENT, + QSFP11_PRESENT, + QSFP12_PRESENT, + QSFP13_PRESENT, + QSFP14_PRESENT, + QSFP15_PRESENT, + QSFP16_PRESENT, + QSFP17_PRESENT, + QSFP18_PRESENT, + QSFP19_PRESENT, + QSFP20_PRESENT, + QSFP21_PRESENT, + QSFP22_PRESENT, + QSFP23_PRESENT, + QSFP24_PRESENT, + QSFP25_PRESENT, + QSFP26_PRESENT, + QSFP27_PRESENT, + QSFP28_PRESENT, + QSFP29_PRESENT, + QSFP30_PRESENT, + QSFP31_PRESENT, + QSFP32_PRESENT, + QSFP_INT_ALL, + QSFP1_INT, + QSFP2_INT, + QSFP3_INT, + QSFP4_INT, + QSFP5_INT, + QSFP6_INT, + QSFP7_INT, + QSFP8_INT, + QSFP9_INT, + QSFP10_INT, + QSFP11_INT, + QSFP12_INT, + QSFP13_INT, + QSFP14_INT, + QSFP15_INT, + QSFP16_INT, + QSFP17_INT, + QSFP18_INT, + QSFP19_INT, + QSFP20_INT, + QSFP21_INT, + QSFP22_INT, + QSFP23_INT, + QSFP24_INT, + QSFP25_INT, + QSFP26_INT, + QSFP27_INT, + QSFP28_INT, + QSFP29_INT, + QSFP30_INT, + QSFP31_INT, + QSFP32_INT, + QSFP1_4_INT, + QSFP2_4_INT, + QSFP3_4_INT, + QSFP4_4_INT, + QSFP1_4_MODPRS, + QSFP2_4_MODPRS, + QSFP3_4_MODPRS, + QSFP4_4_MODPRS, + QSFP1_4_INT_MASK, + QSFP2_4_INT_MASK, + QSFP3_4_INT_MASK, + QSFP4_4_INT_MASK, + QSFP1_4_MODPRS_MASK, + QSFP2_4_MODPRS_MASK, + QSFP3_4_MODPRS_MASK, + QSFP4_4_MODPRS_MASK +}; +/* end of struct i2c_sysfs_attributes */ + +/* sysfs attributes for SENSOR_DEVICE_ATTR */ +static SENSOR_DEVICE_ATTR(cpld_23_ver , S_IRUGO , cpld_hw_ver_get , NULL , 23); +static SENSOR_DEVICE_ATTR(cpld_30_ver , S_IRUGO , cpld_hw_ver_get , NULL , 30); +static SENSOR_DEVICE_ATTR(cpld_31_ver , S_IRUGO , cpld_hw_ver_get , NULL , 31); +static SENSOR_DEVICE_ATTR(cpld_32_ver , S_IRUGO , cpld_hw_ver_get , NULL , 32); +static SENSOR_DEVICE_ATTR(wdt_en , S_IRUGO | S_IWUSR , wdt_enable_get , wdt_enable_set , WDT_EN); +static SENSOR_DEVICE_ATTR(eeprom_wp , S_IRUGO | S_IWUSR , eeprom_wp_get , eeprom_wp_set , EEPROM_WP); +static SENSOR_DEVICE_ATTR(usb_en , S_IRUGO | S_IWUSR , usb_enable_get , usb_enable_set , USB_EN); +static SENSOR_DEVICE_ATTR(shutdown_set , S_IRUGO | S_IWUSR , NULL , shutdown_set , SHUTDOWN_SET); +static SENSOR_DEVICE_ATTR(reset , S_IRUGO | S_IWUSR , NULL , reset_mac_set , RESET); +static SENSOR_DEVICE_ATTR(bmc_present , S_IRUGO , bmc_enable_get , NULL , BMC_PRESENT); +static SENSOR_DEVICE_ATTR(led_1 , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 4); +static SENSOR_DEVICE_ATTR(led_2 , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 3); +static SENSOR_DEVICE_ATTR(led_flow , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 2); +static SENSOR_DEVICE_ATTR(led_sys , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 1); +static SENSOR_DEVICE_ATTR(led_fiber , S_IRUGO | S_IWUSR , led_fiber_get , led_fiber_set , LED_FIBER); +static SENSOR_DEVICE_ATTR(temp_r_b_int , S_IRUGO , themal_int_get , NULL , TEMP_R_B_INT); +static SENSOR_DEVICE_ATTR(temp_l_b_int , S_IRUGO , themal_int_get , NULL , TEMP_L_B_INT); +static SENSOR_DEVICE_ATTR(temp_r_t_int , S_IRUGO , themal_int_get , NULL , TEMP_R_T_INT); +static SENSOR_DEVICE_ATTR(temp_l_t_int , S_IRUGO , themal_int_get , NULL , TEMP_L_T_INT); +static SENSOR_DEVICE_ATTR(temp_r_b_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_R_B_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_l_b_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_L_B_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_r_t_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_R_T_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_l_t_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_L_T_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_fp_int , S_IRUGO , sys_int_get , NULL , CPLD_FP_INT); +static SENSOR_DEVICE_ATTR(cpld_rp_int , S_IRUGO , sys_int_get , NULL , CPLD_RP_INT); +static SENSOR_DEVICE_ATTR(cpld_fan_int , S_IRUGO , sys_int_get , NULL , CPLD_FAN_INT); +static SENSOR_DEVICE_ATTR(cpld_psu_int , S_IRUGO , sys_int_get , NULL , CPLD_PSU_INT); +static SENSOR_DEVICE_ATTR(thermal_int , S_IRUGO , sys_int_get , NULL , THERMAL_INT); +static SENSOR_DEVICE_ATTR(usb_int , S_IRUGO , sys_int_get , NULL , USB_INT); +static SENSOR_DEVICE_ATTR(cpld_fp_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_FP_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_rp_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_RP_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_fan_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_FAN_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_psu_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_PSU_INT_MASK); +static SENSOR_DEVICE_ATTR(thermal_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , THERMAL_INT_MASK); +static SENSOR_DEVICE_ATTR(usb_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , USB_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_r_b_f , S_IRUGO , themal_temp_get , NULL , TEMP_R_B_F); +static SENSOR_DEVICE_ATTR(temp_r_b_b , S_IRUGO , themal_temp_get , NULL , TEMP_R_B_B); +static SENSOR_DEVICE_ATTR(temp_l_b_f , S_IRUGO , themal_temp_get , NULL , TEMP_L_B_F); +static SENSOR_DEVICE_ATTR(temp_l_b_b , S_IRUGO , themal_temp_get , NULL , TEMP_L_B_B); +static SENSOR_DEVICE_ATTR(temp_r_t_f , S_IRUGO , themal_temp_get , NULL , TEMP_R_T_F); +static SENSOR_DEVICE_ATTR(temp_r_t_b , S_IRUGO , themal_temp_get , NULL , TEMP_R_T_B); +static SENSOR_DEVICE_ATTR(temp_l_t_f , S_IRUGO , themal_temp_get , NULL , TEMP_L_T_F); +static SENSOR_DEVICE_ATTR(temp_l_t_b , S_IRUGO , themal_temp_get , NULL , TEMP_L_T_B); +static SENSOR_DEVICE_ATTR(temp_r_b_f_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_R_B_F_MAX); +static SENSOR_DEVICE_ATTR(temp_l_b_f_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_L_B_F_MAX); +static SENSOR_DEVICE_ATTR(temp_r_t_f_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_R_T_F_MAX); +static SENSOR_DEVICE_ATTR(temp_l_t_f_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_L_T_F_MAX); +static SENSOR_DEVICE_ATTR(temp_r_b_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_R_B_B_MAX); +static SENSOR_DEVICE_ATTR(temp_l_b_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_L_B_B_MAX); +static SENSOR_DEVICE_ATTR(temp_r_t_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_R_T_B_MAX); +static SENSOR_DEVICE_ATTR(temp_l_t_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_L_T_B_MAX); +static SENSOR_DEVICE_ATTR(temp_r_b_f_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_R_B_F_MIN); +static SENSOR_DEVICE_ATTR(temp_l_b_f_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_L_B_F_MIN); +static SENSOR_DEVICE_ATTR(temp_r_t_f_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_R_T_F_MIN); +static SENSOR_DEVICE_ATTR(temp_l_t_f_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_L_T_F_MIN); +static SENSOR_DEVICE_ATTR(temp_r_b_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_R_B_B_MIN); +static SENSOR_DEVICE_ATTR(temp_l_b_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_L_B_B_MIN); +static SENSOR_DEVICE_ATTR(temp_r_t_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_R_T_B_MIN); +static SENSOR_DEVICE_ATTR(temp_l_t_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_L_T_B_MIN); +static SENSOR_DEVICE_ATTR(temp_r_b_f_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_R_B_F_CRIT); +static SENSOR_DEVICE_ATTR(temp_l_b_f_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_L_B_F_CRIT); +static SENSOR_DEVICE_ATTR(temp_r_t_f_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_R_T_F_CRIT); +static SENSOR_DEVICE_ATTR(temp_l_t_f_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_L_T_F_CRIT); +static SENSOR_DEVICE_ATTR(temp_r_b_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_R_B_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_l_b_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_L_B_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_r_t_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_R_T_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_l_t_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_L_T_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_r_b_f_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_R_B_F_LCRIT); +static SENSOR_DEVICE_ATTR(temp_l_b_f_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_L_B_F_LCRIT); +static SENSOR_DEVICE_ATTR(temp_r_t_f_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_R_T_F_LCRIT); +static SENSOR_DEVICE_ATTR(temp_l_t_f_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_L_T_F_LCRIT); +static SENSOR_DEVICE_ATTR(temp_r_b_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_R_B_B_LCRIT); +static SENSOR_DEVICE_ATTR(temp_l_b_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_L_B_B_LCRIT); +static SENSOR_DEVICE_ATTR(temp_r_t_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_R_T_B_LCRIT); +static SENSOR_DEVICE_ATTR(temp_l_t_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_L_T_B_LCRIT); +static SENSOR_DEVICE_ATTR(fanctrl_rpm , S_IRUGO , fan_ctrl_rpm_get , NULL , FANCTRL_RPM); +static SENSOR_DEVICE_ATTR(fanctrl_mode , S_IRUGO , fan_ctrl_mode_get , NULL , FANCTRL_MODE); +static SENSOR_DEVICE_ATTR(fan1_stat , S_IRUGO , fan_status_get , NULL , 1); +static SENSOR_DEVICE_ATTR(fan2_stat , S_IRUGO , fan_status_get , NULL , 2); +static SENSOR_DEVICE_ATTR(fan3_stat , S_IRUGO , fan_status_get , NULL , 3); +static SENSOR_DEVICE_ATTR(fan4_stat , S_IRUGO , fan_status_get , NULL , 4); +static SENSOR_DEVICE_ATTR(fan5_stat , S_IRUGO , fan_status_get , NULL , 5); +static SENSOR_DEVICE_ATTR(fan1_present , S_IRUGO , fan_present_get , NULL , 1); +static SENSOR_DEVICE_ATTR(fan2_present , S_IRUGO , fan_present_get , NULL , 2); +static SENSOR_DEVICE_ATTR(fan3_present , S_IRUGO , fan_present_get , NULL , 3); +static SENSOR_DEVICE_ATTR(fan4_present , S_IRUGO , fan_present_get , NULL , 4); +static SENSOR_DEVICE_ATTR(fan5_present , S_IRUGO , fan_present_get , NULL , 5); +static SENSOR_DEVICE_ATTR(fan1_power , S_IRUGO , fan_power_get , NULL , 1); +static SENSOR_DEVICE_ATTR(fan2_power , S_IRUGO , fan_power_get , NULL , 2); +static SENSOR_DEVICE_ATTR(fan3_power , S_IRUGO , fan_power_get , NULL , 3); +static SENSOR_DEVICE_ATTR(fan4_power , S_IRUGO , fan_power_get , NULL , 4); +static SENSOR_DEVICE_ATTR(fan5_power , S_IRUGO , fan_power_get , NULL , 5); +static SENSOR_DEVICE_ATTR(fan1_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN1_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan2_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN2_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan3_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN3_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan4_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN4_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan5_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN5_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan1_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN1_REAR_RPM); +static SENSOR_DEVICE_ATTR(fan2_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN2_REAR_RPM); +static SENSOR_DEVICE_ATTR(fan3_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN3_REAR_RPM); +static SENSOR_DEVICE_ATTR(fan4_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN4_REAR_RPM); +static SENSOR_DEVICE_ATTR(fan5_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN5_REAR_RPM); +static SENSOR_DEVICE_ATTR(psu1_good , S_IRUGO , psu_status_get , NULL , 1); +static SENSOR_DEVICE_ATTR(psu2_good , S_IRUGO , psu_status_get , NULL , 2); +static SENSOR_DEVICE_ATTR(psu1_prnt , S_IRUGO , psu_present_get , NULL , 1); +static SENSOR_DEVICE_ATTR(psu2_prnt , S_IRUGO , psu_present_get , NULL , 2); +static SENSOR_DEVICE_ATTR(psu1_vin , S_IRUGO , psu_vin_get , NULL , PSU1_VIN); +static SENSOR_DEVICE_ATTR(psu1_iin , S_IRUGO , psu_iin_get , NULL , PSU1_IIN); +static SENSOR_DEVICE_ATTR(psu1_vout , S_IRUGO , psu_vout_get , NULL , PSU1_VOUT); +static SENSOR_DEVICE_ATTR(psu1_iout , S_IRUGO , psu_iout_get , NULL , PSU1_IOUT); +static SENSOR_DEVICE_ATTR(psu1_temp , S_IRUGO , psu_temp_get , NULL , PSU1_TEMP); +static SENSOR_DEVICE_ATTR(psu1_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU1_FAN_SPEED); +static SENSOR_DEVICE_ATTR(psu1_pout , S_IRUGO , psu_pout_get , NULL , PSU1_POUT); +static SENSOR_DEVICE_ATTR(psu1_pin , S_IRUGO , psu_pin_get , NULL , PSU1_PIN); +static SENSOR_DEVICE_ATTR(psu1_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU1_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu1_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU1_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu1_vmode , S_IRUGO , psu_vmode_get , NULL , PSU1_VMODE); +static SENSOR_DEVICE_ATTR(psu2_vin , S_IRUGO , psu_vin_get , NULL , PSU2_VIN); +static SENSOR_DEVICE_ATTR(psu2_iin , S_IRUGO , psu_iin_get , NULL , PSU2_IIN); +static SENSOR_DEVICE_ATTR(psu2_vout , S_IRUGO , psu_vout_get , NULL , PSU2_VOUT); +static SENSOR_DEVICE_ATTR(psu2_iout , S_IRUGO , psu_iout_get , NULL , PSU2_IOUT); +static SENSOR_DEVICE_ATTR(psu2_temp , S_IRUGO , psu_temp_get , NULL , PSU2_TEMP); +static SENSOR_DEVICE_ATTR(psu2_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU2_FAN_SPEED); +static SENSOR_DEVICE_ATTR(psu2_pout , S_IRUGO , psu_pout_get , NULL , PSU2_POUT); +static SENSOR_DEVICE_ATTR(psu2_pin , S_IRUGO , psu_pin_get , NULL , PSU2_PIN); +static SENSOR_DEVICE_ATTR(psu2_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU2_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu2_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU2_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu2_vmode , S_IRUGO , psu_vmode_get , NULL , PSU2_VMODE); +static SENSOR_DEVICE_ATTR(dc6e_p0_vout , S_IRUGO , dc_vout_get , NULL , DC6E_P0_VOUT); +static SENSOR_DEVICE_ATTR(dc6e_p0_iout , S_IRUGO , dc_iout_get , NULL , DC6E_P0_IOUT); +static SENSOR_DEVICE_ATTR(dc6e_p0_pout , S_IRUGO , dc_pout_get , NULL , DC6E_P0_POUT); +static SENSOR_DEVICE_ATTR(dc6e_p1_vout , S_IRUGO , dc_vout_get , NULL , DC6E_P1_VOUT); +static SENSOR_DEVICE_ATTR(dc6e_p1_iout , S_IRUGO , dc_iout_get , NULL , DC6E_P1_IOUT); +static SENSOR_DEVICE_ATTR(dc6e_p1_pout , S_IRUGO , dc_pout_get , NULL , DC6E_P1_POUT); +static SENSOR_DEVICE_ATTR(dc70_p0_vout , S_IRUGO , dc_vout_get , NULL , DC70_P0_VOUT); +static SENSOR_DEVICE_ATTR(dc70_p0_iout , S_IRUGO , dc_iout_get , NULL , DC70_P0_IOUT); +static SENSOR_DEVICE_ATTR(dc70_p0_pout , S_IRUGO , dc_pout_get , NULL , DC70_P0_POUT); +static SENSOR_DEVICE_ATTR(dc70_p1_vout , S_IRUGO , dc_vout_get , NULL , DC70_P1_VOUT); +static SENSOR_DEVICE_ATTR(dc70_p1_iout , S_IRUGO , dc_iout_get , NULL , DC70_P1_IOUT); +static SENSOR_DEVICE_ATTR(dc70_p1_pout , S_IRUGO , dc_pout_get , NULL , DC70_P1_POUT); +static SENSOR_DEVICE_ATTR(qsfp_low_power_all , S_IRUGO | S_IWUSR , qsfp_low_power_all_get , qsfp_low_power_all_set , QSFP_LOW_POWER_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 1); +static SENSOR_DEVICE_ATTR(qsfp2_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 2); +static SENSOR_DEVICE_ATTR(qsfp3_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 3); +static SENSOR_DEVICE_ATTR(qsfp4_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 4); +static SENSOR_DEVICE_ATTR(qsfp5_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 5); +static SENSOR_DEVICE_ATTR(qsfp6_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 6); +static SENSOR_DEVICE_ATTR(qsfp7_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 7); +static SENSOR_DEVICE_ATTR(qsfp8_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 8); +static SENSOR_DEVICE_ATTR(qsfp9_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 9); +static SENSOR_DEVICE_ATTR(qsfp10_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 10); +static SENSOR_DEVICE_ATTR(qsfp11_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 11); +static SENSOR_DEVICE_ATTR(qsfp12_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 12); +static SENSOR_DEVICE_ATTR(qsfp13_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 13); +static SENSOR_DEVICE_ATTR(qsfp14_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 14); +static SENSOR_DEVICE_ATTR(qsfp15_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 15); +static SENSOR_DEVICE_ATTR(qsfp16_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 16); +static SENSOR_DEVICE_ATTR(qsfp17_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 17); +static SENSOR_DEVICE_ATTR(qsfp18_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 18); +static SENSOR_DEVICE_ATTR(qsfp19_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 19); +static SENSOR_DEVICE_ATTR(qsfp20_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 20); +static SENSOR_DEVICE_ATTR(qsfp21_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 21); +static SENSOR_DEVICE_ATTR(qsfp22_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 22); +static SENSOR_DEVICE_ATTR(qsfp23_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 23); +static SENSOR_DEVICE_ATTR(qsfp24_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 24); +static SENSOR_DEVICE_ATTR(qsfp25_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 25); +static SENSOR_DEVICE_ATTR(qsfp26_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 26); +static SENSOR_DEVICE_ATTR(qsfp27_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 27); +static SENSOR_DEVICE_ATTR(qsfp28_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 28); +static SENSOR_DEVICE_ATTR(qsfp29_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 29); +static SENSOR_DEVICE_ATTR(qsfp30_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 30); +static SENSOR_DEVICE_ATTR(qsfp31_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 31); +static SENSOR_DEVICE_ATTR(qsfp32_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 32); +static SENSOR_DEVICE_ATTR(qsfp_reset_all , S_IRUGO | S_IWUSR , NULL , qsfp_reset_all_set , QSFP_RESET_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 1); +static SENSOR_DEVICE_ATTR(qsfp2_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 2); +static SENSOR_DEVICE_ATTR(qsfp3_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 3); +static SENSOR_DEVICE_ATTR(qsfp4_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 4); +static SENSOR_DEVICE_ATTR(qsfp5_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 5); +static SENSOR_DEVICE_ATTR(qsfp6_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 6); +static SENSOR_DEVICE_ATTR(qsfp7_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 7); +static SENSOR_DEVICE_ATTR(qsfp8_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 8); +static SENSOR_DEVICE_ATTR(qsfp9_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 9); +static SENSOR_DEVICE_ATTR(qsfp10_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 10); +static SENSOR_DEVICE_ATTR(qsfp11_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 11); +static SENSOR_DEVICE_ATTR(qsfp12_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 12); +static SENSOR_DEVICE_ATTR(qsfp13_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 13); +static SENSOR_DEVICE_ATTR(qsfp14_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 14); +static SENSOR_DEVICE_ATTR(qsfp15_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 15); +static SENSOR_DEVICE_ATTR(qsfp16_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 16); +static SENSOR_DEVICE_ATTR(qsfp17_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 17); +static SENSOR_DEVICE_ATTR(qsfp18_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 18); +static SENSOR_DEVICE_ATTR(qsfp19_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 19); +static SENSOR_DEVICE_ATTR(qsfp20_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 20); +static SENSOR_DEVICE_ATTR(qsfp21_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 21); +static SENSOR_DEVICE_ATTR(qsfp22_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 22); +static SENSOR_DEVICE_ATTR(qsfp23_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 23); +static SENSOR_DEVICE_ATTR(qsfp24_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 24); +static SENSOR_DEVICE_ATTR(qsfp25_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 25); +static SENSOR_DEVICE_ATTR(qsfp26_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 26); +static SENSOR_DEVICE_ATTR(qsfp27_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 27); +static SENSOR_DEVICE_ATTR(qsfp28_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 28); +static SENSOR_DEVICE_ATTR(qsfp29_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 29); +static SENSOR_DEVICE_ATTR(qsfp30_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 30); +static SENSOR_DEVICE_ATTR(qsfp31_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 31); +static SENSOR_DEVICE_ATTR(qsfp32_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 32); +static SENSOR_DEVICE_ATTR(qsfp_present_all , S_IRUGO , qsfp_present_all_get , NULL , QSFP_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_present , S_IRUGO , qsfp_present_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp2_present , S_IRUGO , qsfp_present_get , NULL , 2); +static SENSOR_DEVICE_ATTR(qsfp3_present , S_IRUGO , qsfp_present_get , NULL , 3); +static SENSOR_DEVICE_ATTR(qsfp4_present , S_IRUGO , qsfp_present_get , NULL , 4); +static SENSOR_DEVICE_ATTR(qsfp5_present , S_IRUGO , qsfp_present_get , NULL , 5); +static SENSOR_DEVICE_ATTR(qsfp6_present , S_IRUGO , qsfp_present_get , NULL , 6); +static SENSOR_DEVICE_ATTR(qsfp7_present , S_IRUGO , qsfp_present_get , NULL , 7); +static SENSOR_DEVICE_ATTR(qsfp8_present , S_IRUGO , qsfp_present_get , NULL , 8); +static SENSOR_DEVICE_ATTR(qsfp9_present , S_IRUGO , qsfp_present_get , NULL , 9); +static SENSOR_DEVICE_ATTR(qsfp10_present , S_IRUGO , qsfp_present_get , NULL , 10); +static SENSOR_DEVICE_ATTR(qsfp11_present , S_IRUGO , qsfp_present_get , NULL , 11); +static SENSOR_DEVICE_ATTR(qsfp12_present , S_IRUGO , qsfp_present_get , NULL , 12); +static SENSOR_DEVICE_ATTR(qsfp13_present , S_IRUGO , qsfp_present_get , NULL , 13); +static SENSOR_DEVICE_ATTR(qsfp14_present , S_IRUGO , qsfp_present_get , NULL , 14); +static SENSOR_DEVICE_ATTR(qsfp15_present , S_IRUGO , qsfp_present_get , NULL , 15); +static SENSOR_DEVICE_ATTR(qsfp16_present , S_IRUGO , qsfp_present_get , NULL , 16); +static SENSOR_DEVICE_ATTR(qsfp17_present , S_IRUGO , qsfp_present_get , NULL , 17); +static SENSOR_DEVICE_ATTR(qsfp18_present , S_IRUGO , qsfp_present_get , NULL , 18); +static SENSOR_DEVICE_ATTR(qsfp19_present , S_IRUGO , qsfp_present_get , NULL , 19); +static SENSOR_DEVICE_ATTR(qsfp20_present , S_IRUGO , qsfp_present_get , NULL , 20); +static SENSOR_DEVICE_ATTR(qsfp21_present , S_IRUGO , qsfp_present_get , NULL , 21); +static SENSOR_DEVICE_ATTR(qsfp22_present , S_IRUGO , qsfp_present_get , NULL , 22); +static SENSOR_DEVICE_ATTR(qsfp23_present , S_IRUGO , qsfp_present_get , NULL , 23); +static SENSOR_DEVICE_ATTR(qsfp24_present , S_IRUGO , qsfp_present_get , NULL , 24); +static SENSOR_DEVICE_ATTR(qsfp25_present , S_IRUGO , qsfp_present_get , NULL , 25); +static SENSOR_DEVICE_ATTR(qsfp26_present , S_IRUGO , qsfp_present_get , NULL , 26); +static SENSOR_DEVICE_ATTR(qsfp27_present , S_IRUGO , qsfp_present_get , NULL , 27); +static SENSOR_DEVICE_ATTR(qsfp28_present , S_IRUGO , qsfp_present_get , NULL , 28); +static SENSOR_DEVICE_ATTR(qsfp29_present , S_IRUGO , qsfp_present_get , NULL , 29); +static SENSOR_DEVICE_ATTR(qsfp30_present , S_IRUGO , qsfp_present_get , NULL , 30); +static SENSOR_DEVICE_ATTR(qsfp31_present , S_IRUGO , qsfp_present_get , NULL , 31); +static SENSOR_DEVICE_ATTR(qsfp32_present , S_IRUGO , qsfp_present_get , NULL , 32); +static SENSOR_DEVICE_ATTR(qsfp_int_all , S_IRUGO , qsfp_int_all_get , NULL , QSFP_INT_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_int , S_IRUGO , qsfp_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp2_int , S_IRUGO , qsfp_int_get , NULL , 2); +static SENSOR_DEVICE_ATTR(qsfp3_int , S_IRUGO , qsfp_int_get , NULL , 3); +static SENSOR_DEVICE_ATTR(qsfp4_int , S_IRUGO , qsfp_int_get , NULL , 4); +static SENSOR_DEVICE_ATTR(qsfp5_int , S_IRUGO , qsfp_int_get , NULL , 5); +static SENSOR_DEVICE_ATTR(qsfp6_int , S_IRUGO , qsfp_int_get , NULL , 6); +static SENSOR_DEVICE_ATTR(qsfp7_int , S_IRUGO , qsfp_int_get , NULL , 7); +static SENSOR_DEVICE_ATTR(qsfp8_int , S_IRUGO , qsfp_int_get , NULL , 8); +static SENSOR_DEVICE_ATTR(qsfp9_int , S_IRUGO , qsfp_int_get , NULL , 9); +static SENSOR_DEVICE_ATTR(qsfp10_int , S_IRUGO , qsfp_int_get , NULL , 10); +static SENSOR_DEVICE_ATTR(qsfp11_int , S_IRUGO , qsfp_int_get , NULL , 11); +static SENSOR_DEVICE_ATTR(qsfp12_int , S_IRUGO , qsfp_int_get , NULL , 12); +static SENSOR_DEVICE_ATTR(qsfp13_int , S_IRUGO , qsfp_int_get , NULL , 13); +static SENSOR_DEVICE_ATTR(qsfp14_int , S_IRUGO , qsfp_int_get , NULL , 14); +static SENSOR_DEVICE_ATTR(qsfp15_int , S_IRUGO , qsfp_int_get , NULL , 15); +static SENSOR_DEVICE_ATTR(qsfp16_int , S_IRUGO , qsfp_int_get , NULL , 16); +static SENSOR_DEVICE_ATTR(qsfp17_int , S_IRUGO , qsfp_int_get , NULL , 17); +static SENSOR_DEVICE_ATTR(qsfp18_int , S_IRUGO , qsfp_int_get , NULL , 18); +static SENSOR_DEVICE_ATTR(qsfp19_int , S_IRUGO , qsfp_int_get , NULL , 19); +static SENSOR_DEVICE_ATTR(qsfp20_int , S_IRUGO , qsfp_int_get , NULL , 20); +static SENSOR_DEVICE_ATTR(qsfp21_int , S_IRUGO , qsfp_int_get , NULL , 21); +static SENSOR_DEVICE_ATTR(qsfp22_int , S_IRUGO , qsfp_int_get , NULL , 22); +static SENSOR_DEVICE_ATTR(qsfp23_int , S_IRUGO , qsfp_int_get , NULL , 23); +static SENSOR_DEVICE_ATTR(qsfp24_int , S_IRUGO , qsfp_int_get , NULL , 24); +static SENSOR_DEVICE_ATTR(qsfp25_int , S_IRUGO , qsfp_int_get , NULL , 25); +static SENSOR_DEVICE_ATTR(qsfp26_int , S_IRUGO , qsfp_int_get , NULL , 26); +static SENSOR_DEVICE_ATTR(qsfp27_int , S_IRUGO , qsfp_int_get , NULL , 27); +static SENSOR_DEVICE_ATTR(qsfp28_int , S_IRUGO , qsfp_int_get , NULL , 28); +static SENSOR_DEVICE_ATTR(qsfp29_int , S_IRUGO , qsfp_int_get , NULL , 29); +static SENSOR_DEVICE_ATTR(qsfp30_int , S_IRUGO , qsfp_int_get , NULL , 30); +static SENSOR_DEVICE_ATTR(qsfp31_int , S_IRUGO , qsfp_int_get , NULL , 31); +static SENSOR_DEVICE_ATTR(qsfp32_int , S_IRUGO , qsfp_int_get , NULL , 32); +static SENSOR_DEVICE_ATTR(qsfp1_4_int , S_IRUGO , qsfp_quter_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp2_4_int , S_IRUGO , qsfp_quter_int_get , NULL , 2); +static SENSOR_DEVICE_ATTR(qsfp3_4_int , S_IRUGO , qsfp_quter_int_get , NULL , 3); +static SENSOR_DEVICE_ATTR(qsfp4_4_int , S_IRUGO , qsfp_quter_int_get , NULL , 4); +static SENSOR_DEVICE_ATTR(qsfp1_4_modprs , S_IRUGO , qsfp_modprs_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp2_4_modprs , S_IRUGO , qsfp_modprs_int_get , NULL , 2); +static SENSOR_DEVICE_ATTR(qsfp3_4_modprs , S_IRUGO , qsfp_modprs_int_get , NULL , 3); +static SENSOR_DEVICE_ATTR(qsfp4_4_modprs , S_IRUGO , qsfp_modprs_int_get , NULL , 4); +static SENSOR_DEVICE_ATTR(qsfp1_4_int_mask , S_IRUGO | S_IWUSR , qsfp_quter_int_mask_get , qsfp_quter_int_mask_set , 1); +static SENSOR_DEVICE_ATTR(qsfp2_4_int_mask , S_IRUGO | S_IWUSR , qsfp_quter_int_mask_get , qsfp_quter_int_mask_set , 2); +static SENSOR_DEVICE_ATTR(qsfp3_4_int_mask , S_IRUGO | S_IWUSR , qsfp_quter_int_mask_get , qsfp_quter_int_mask_set , 3); +static SENSOR_DEVICE_ATTR(qsfp4_4_int_mask , S_IRUGO | S_IWUSR , qsfp_quter_int_mask_get , qsfp_quter_int_mask_set , 4); +static SENSOR_DEVICE_ATTR(qsfp1_4_modprs_mask , S_IRUGO | S_IWUSR , qsfp_modprs_int_mask_get , qsfp_modprs_int_mask_set , 1); +static SENSOR_DEVICE_ATTR(qsfp2_4_modprs_mask , S_IRUGO | S_IWUSR , qsfp_modprs_int_mask_get , qsfp_modprs_int_mask_set , 2); +static SENSOR_DEVICE_ATTR(qsfp3_4_modprs_mask , S_IRUGO | S_IWUSR , qsfp_modprs_int_mask_get , qsfp_modprs_int_mask_set , 3); +static SENSOR_DEVICE_ATTR(qsfp4_4_modprs_mask , S_IRUGO | S_IWUSR , qsfp_modprs_int_mask_get , qsfp_modprs_int_mask_set , 4); +/* end of sysfs attributes for SENSOR_DEVICE_ATTR */ + +/* sysfs attributes for hwmon */ +/* i2c-0 */ +static struct attribute *ESCC601_SYS_attributes[] = +{ + &sensor_dev_attr_cpld_23_ver.dev_attr.attr, + &sensor_dev_attr_cpld_30_ver.dev_attr.attr, + &sensor_dev_attr_cpld_31_ver.dev_attr.attr, + &sensor_dev_attr_cpld_32_ver.dev_attr.attr, + &sensor_dev_attr_wdt_en.dev_attr.attr, + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_usb_en.dev_attr.attr, + &sensor_dev_attr_shutdown_set.dev_attr.attr, + &sensor_dev_attr_reset.dev_attr.attr, + &sensor_dev_attr_bmc_present.dev_attr.attr, + &sensor_dev_attr_cpld_fp_int.dev_attr.attr, + &sensor_dev_attr_cpld_rp_int.dev_attr.attr, + &sensor_dev_attr_cpld_fan_int.dev_attr.attr, + &sensor_dev_attr_cpld_psu_int.dev_attr.attr, + &sensor_dev_attr_thermal_int.dev_attr.attr, + &sensor_dev_attr_usb_int.dev_attr.attr, + &sensor_dev_attr_cpld_fp_int_mask.dev_attr.attr, + &sensor_dev_attr_cpld_rp_int_mask.dev_attr.attr, + &sensor_dev_attr_cpld_fan_int_mask.dev_attr.attr, + &sensor_dev_attr_cpld_psu_int_mask.dev_attr.attr, + &sensor_dev_attr_thermal_int_mask.dev_attr.attr, + &sensor_dev_attr_usb_int_mask.dev_attr.attr, + NULL +}; +static struct attribute *ESCC601_LED_attributes[] = +{ + &sensor_dev_attr_led_1.dev_attr.attr, + &sensor_dev_attr_led_2.dev_attr.attr, + &sensor_dev_attr_led_flow.dev_attr.attr, + &sensor_dev_attr_led_sys.dev_attr.attr, + &sensor_dev_attr_led_fiber.dev_attr.attr, + NULL +}; +static struct attribute *ESCC601_THERMAL_attributes[] = +{ + &sensor_dev_attr_temp_r_b_f.dev_attr.attr, + &sensor_dev_attr_temp_r_b_b.dev_attr.attr, + &sensor_dev_attr_temp_l_b_f.dev_attr.attr, + &sensor_dev_attr_temp_l_b_b.dev_attr.attr, + &sensor_dev_attr_temp_r_t_f.dev_attr.attr, + &sensor_dev_attr_temp_r_t_b.dev_attr.attr, + &sensor_dev_attr_temp_l_t_f.dev_attr.attr, + &sensor_dev_attr_temp_l_t_b.dev_attr.attr, + &sensor_dev_attr_temp_r_b_int.dev_attr.attr, + &sensor_dev_attr_temp_l_b_int.dev_attr.attr, + &sensor_dev_attr_temp_r_t_int.dev_attr.attr, + &sensor_dev_attr_temp_l_t_int.dev_attr.attr, + &sensor_dev_attr_temp_r_b_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_l_b_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_r_t_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_l_t_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_r_b_f_max.dev_attr.attr, + &sensor_dev_attr_temp_r_b_f_min.dev_attr.attr, + &sensor_dev_attr_temp_r_b_f_crit.dev_attr.attr, + &sensor_dev_attr_temp_r_b_f_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_r_b_b_max.dev_attr.attr, + &sensor_dev_attr_temp_r_b_b_min.dev_attr.attr, + &sensor_dev_attr_temp_r_b_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_r_b_b_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_l_b_f_max.dev_attr.attr, + &sensor_dev_attr_temp_l_b_f_min.dev_attr.attr, + &sensor_dev_attr_temp_l_b_f_crit.dev_attr.attr, + &sensor_dev_attr_temp_l_b_f_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_l_b_b_max.dev_attr.attr, + &sensor_dev_attr_temp_l_b_b_min.dev_attr.attr, + &sensor_dev_attr_temp_l_b_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_l_b_b_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_r_t_f_max.dev_attr.attr, + &sensor_dev_attr_temp_r_t_f_min.dev_attr.attr, + &sensor_dev_attr_temp_r_t_f_crit.dev_attr.attr, + &sensor_dev_attr_temp_r_t_f_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_r_t_b_max.dev_attr.attr, + &sensor_dev_attr_temp_r_t_b_min.dev_attr.attr, + &sensor_dev_attr_temp_r_t_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_r_t_b_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_l_t_f_max.dev_attr.attr, + &sensor_dev_attr_temp_l_t_f_min.dev_attr.attr, + &sensor_dev_attr_temp_l_t_f_crit.dev_attr.attr, + &sensor_dev_attr_temp_l_t_f_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_l_t_b_max.dev_attr.attr, + &sensor_dev_attr_temp_l_t_b_min.dev_attr.attr, + &sensor_dev_attr_temp_l_t_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_l_t_b_lcrit.dev_attr.attr, + NULL +}; +static struct attribute *ESCC601_FAN_attributes[] = +{ + &sensor_dev_attr_fanctrl_rpm.dev_attr.attr, + &sensor_dev_attr_fanctrl_mode.dev_attr.attr, + &sensor_dev_attr_fan1_stat.dev_attr.attr, + &sensor_dev_attr_fan2_stat.dev_attr.attr, + &sensor_dev_attr_fan3_stat.dev_attr.attr, + &sensor_dev_attr_fan4_stat.dev_attr.attr, + &sensor_dev_attr_fan5_stat.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan5_present.dev_attr.attr, + &sensor_dev_attr_fan1_power.dev_attr.attr, + &sensor_dev_attr_fan2_power.dev_attr.attr, + &sensor_dev_attr_fan3_power.dev_attr.attr, + &sensor_dev_attr_fan4_power.dev_attr.attr, + &sensor_dev_attr_fan5_power.dev_attr.attr, + &sensor_dev_attr_fan1_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_rear_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rear_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rear_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rear_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_rear_rpm.dev_attr.attr, + NULL +}; +static struct attribute *ESCC601_POWER_attributes[] = +{ + &sensor_dev_attr_psu1_good.dev_attr.attr, + &sensor_dev_attr_psu2_good.dev_attr.attr, + &sensor_dev_attr_psu1_prnt.dev_attr.attr, + &sensor_dev_attr_psu2_prnt.dev_attr.attr, + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu1_temp.dev_attr.attr, + &sensor_dev_attr_psu1_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu1_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu1_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu1_vmode.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu2_temp.dev_attr.attr, + &sensor_dev_attr_psu2_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu2_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu2_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu2_vmode.dev_attr.attr, + &sensor_dev_attr_dc6e_p0_vout.dev_attr.attr, + &sensor_dev_attr_dc6e_p0_iout.dev_attr.attr, + &sensor_dev_attr_dc6e_p0_pout.dev_attr.attr, + &sensor_dev_attr_dc6e_p1_vout.dev_attr.attr, + &sensor_dev_attr_dc6e_p1_iout.dev_attr.attr, + &sensor_dev_attr_dc6e_p1_pout.dev_attr.attr, + &sensor_dev_attr_dc70_p0_vout.dev_attr.attr, + &sensor_dev_attr_dc70_p0_iout.dev_attr.attr, + &sensor_dev_attr_dc70_p0_pout.dev_attr.attr, + &sensor_dev_attr_dc70_p1_vout.dev_attr.attr, + &sensor_dev_attr_dc70_p1_iout.dev_attr.attr, + &sensor_dev_attr_dc70_p1_pout.dev_attr.attr, + NULL +}; +static struct attribute *ESCC601_QSFP_attributes[] = +{ + &sensor_dev_attr_qsfp_low_power_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp2_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp3_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp4_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp5_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp6_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp7_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp8_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp9_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp10_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp11_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp12_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp13_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp14_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp15_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp16_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp17_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp18_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp19_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp20_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp21_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp22_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp23_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp24_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp25_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp26_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp27_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp28_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp29_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp30_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp31_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp32_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp_reset_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_reset.dev_attr.attr, + &sensor_dev_attr_qsfp2_reset.dev_attr.attr, + &sensor_dev_attr_qsfp3_reset.dev_attr.attr, + &sensor_dev_attr_qsfp4_reset.dev_attr.attr, + &sensor_dev_attr_qsfp5_reset.dev_attr.attr, + &sensor_dev_attr_qsfp6_reset.dev_attr.attr, + &sensor_dev_attr_qsfp7_reset.dev_attr.attr, + &sensor_dev_attr_qsfp8_reset.dev_attr.attr, + &sensor_dev_attr_qsfp9_reset.dev_attr.attr, + &sensor_dev_attr_qsfp10_reset.dev_attr.attr, + &sensor_dev_attr_qsfp11_reset.dev_attr.attr, + &sensor_dev_attr_qsfp12_reset.dev_attr.attr, + &sensor_dev_attr_qsfp13_reset.dev_attr.attr, + &sensor_dev_attr_qsfp14_reset.dev_attr.attr, + &sensor_dev_attr_qsfp15_reset.dev_attr.attr, + &sensor_dev_attr_qsfp16_reset.dev_attr.attr, + &sensor_dev_attr_qsfp17_reset.dev_attr.attr, + &sensor_dev_attr_qsfp18_reset.dev_attr.attr, + &sensor_dev_attr_qsfp19_reset.dev_attr.attr, + &sensor_dev_attr_qsfp20_reset.dev_attr.attr, + &sensor_dev_attr_qsfp21_reset.dev_attr.attr, + &sensor_dev_attr_qsfp22_reset.dev_attr.attr, + &sensor_dev_attr_qsfp23_reset.dev_attr.attr, + &sensor_dev_attr_qsfp24_reset.dev_attr.attr, + &sensor_dev_attr_qsfp25_reset.dev_attr.attr, + &sensor_dev_attr_qsfp26_reset.dev_attr.attr, + &sensor_dev_attr_qsfp27_reset.dev_attr.attr, + &sensor_dev_attr_qsfp28_reset.dev_attr.attr, + &sensor_dev_attr_qsfp29_reset.dev_attr.attr, + &sensor_dev_attr_qsfp30_reset.dev_attr.attr, + &sensor_dev_attr_qsfp31_reset.dev_attr.attr, + &sensor_dev_attr_qsfp32_reset.dev_attr.attr, + &sensor_dev_attr_qsfp_present_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_present.dev_attr.attr, + &sensor_dev_attr_qsfp2_present.dev_attr.attr, + &sensor_dev_attr_qsfp3_present.dev_attr.attr, + &sensor_dev_attr_qsfp4_present.dev_attr.attr, + &sensor_dev_attr_qsfp5_present.dev_attr.attr, + &sensor_dev_attr_qsfp6_present.dev_attr.attr, + &sensor_dev_attr_qsfp7_present.dev_attr.attr, + &sensor_dev_attr_qsfp8_present.dev_attr.attr, + &sensor_dev_attr_qsfp9_present.dev_attr.attr, + &sensor_dev_attr_qsfp10_present.dev_attr.attr, + &sensor_dev_attr_qsfp11_present.dev_attr.attr, + &sensor_dev_attr_qsfp12_present.dev_attr.attr, + &sensor_dev_attr_qsfp13_present.dev_attr.attr, + &sensor_dev_attr_qsfp14_present.dev_attr.attr, + &sensor_dev_attr_qsfp15_present.dev_attr.attr, + &sensor_dev_attr_qsfp16_present.dev_attr.attr, + &sensor_dev_attr_qsfp17_present.dev_attr.attr, + &sensor_dev_attr_qsfp18_present.dev_attr.attr, + &sensor_dev_attr_qsfp19_present.dev_attr.attr, + &sensor_dev_attr_qsfp20_present.dev_attr.attr, + &sensor_dev_attr_qsfp21_present.dev_attr.attr, + &sensor_dev_attr_qsfp22_present.dev_attr.attr, + &sensor_dev_attr_qsfp23_present.dev_attr.attr, + &sensor_dev_attr_qsfp24_present.dev_attr.attr, + &sensor_dev_attr_qsfp25_present.dev_attr.attr, + &sensor_dev_attr_qsfp26_present.dev_attr.attr, + &sensor_dev_attr_qsfp27_present.dev_attr.attr, + &sensor_dev_attr_qsfp28_present.dev_attr.attr, + &sensor_dev_attr_qsfp29_present.dev_attr.attr, + &sensor_dev_attr_qsfp30_present.dev_attr.attr, + &sensor_dev_attr_qsfp31_present.dev_attr.attr, + &sensor_dev_attr_qsfp32_present.dev_attr.attr, + &sensor_dev_attr_qsfp_int_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_int.dev_attr.attr, + &sensor_dev_attr_qsfp2_int.dev_attr.attr, + &sensor_dev_attr_qsfp3_int.dev_attr.attr, + &sensor_dev_attr_qsfp4_int.dev_attr.attr, + &sensor_dev_attr_qsfp5_int.dev_attr.attr, + &sensor_dev_attr_qsfp6_int.dev_attr.attr, + &sensor_dev_attr_qsfp7_int.dev_attr.attr, + &sensor_dev_attr_qsfp8_int.dev_attr.attr, + &sensor_dev_attr_qsfp9_int.dev_attr.attr, + &sensor_dev_attr_qsfp10_int.dev_attr.attr, + &sensor_dev_attr_qsfp11_int.dev_attr.attr, + &sensor_dev_attr_qsfp12_int.dev_attr.attr, + &sensor_dev_attr_qsfp13_int.dev_attr.attr, + &sensor_dev_attr_qsfp14_int.dev_attr.attr, + &sensor_dev_attr_qsfp15_int.dev_attr.attr, + &sensor_dev_attr_qsfp16_int.dev_attr.attr, + &sensor_dev_attr_qsfp17_int.dev_attr.attr, + &sensor_dev_attr_qsfp18_int.dev_attr.attr, + &sensor_dev_attr_qsfp19_int.dev_attr.attr, + &sensor_dev_attr_qsfp20_int.dev_attr.attr, + &sensor_dev_attr_qsfp21_int.dev_attr.attr, + &sensor_dev_attr_qsfp22_int.dev_attr.attr, + &sensor_dev_attr_qsfp23_int.dev_attr.attr, + &sensor_dev_attr_qsfp24_int.dev_attr.attr, + &sensor_dev_attr_qsfp25_int.dev_attr.attr, + &sensor_dev_attr_qsfp26_int.dev_attr.attr, + &sensor_dev_attr_qsfp27_int.dev_attr.attr, + &sensor_dev_attr_qsfp28_int.dev_attr.attr, + &sensor_dev_attr_qsfp29_int.dev_attr.attr, + &sensor_dev_attr_qsfp30_int.dev_attr.attr, + &sensor_dev_attr_qsfp31_int.dev_attr.attr, + &sensor_dev_attr_qsfp32_int.dev_attr.attr, + &sensor_dev_attr_qsfp1_4_int.dev_attr.attr, + &sensor_dev_attr_qsfp2_4_int.dev_attr.attr, + &sensor_dev_attr_qsfp3_4_int.dev_attr.attr, + &sensor_dev_attr_qsfp4_4_int.dev_attr.attr, + &sensor_dev_attr_qsfp1_4_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp2_4_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp3_4_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp4_4_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp1_4_int_mask.dev_attr.attr, + &sensor_dev_attr_qsfp2_4_int_mask.dev_attr.attr, + &sensor_dev_attr_qsfp3_4_int_mask.dev_attr.attr, + &sensor_dev_attr_qsfp4_4_int_mask.dev_attr.attr, + &sensor_dev_attr_qsfp1_4_modprs_mask.dev_attr.attr, + &sensor_dev_attr_qsfp2_4_modprs_mask.dev_attr.attr, + &sensor_dev_attr_qsfp3_4_modprs_mask.dev_attr.attr, + &sensor_dev_attr_qsfp4_4_modprs_mask.dev_attr.attr, + NULL +}; +/* end of sysfs attributes for hwmon */ + +/* struct attribute_group */ +static const struct attribute_group ESCC601_SYS_group = +{ + .name = "ESCC601_SYS", + .attrs = ESCC601_SYS_attributes, +}; + +static const struct attribute_group ESCC601_LED_group = +{ + .name = "ESCC601_LED", + .attrs = ESCC601_LED_attributes, +}; + +static const struct attribute_group ESCC601_THERMAL_group = +{ + .name = "ESCC601_THERMAL", + .attrs = ESCC601_THERMAL_attributes, +}; + +static const struct attribute_group ESCC601_FAN_group = +{ + .name = "ESCC601_FAN", + .attrs = ESCC601_FAN_attributes, +}; + +static const struct attribute_group ESCC601_POWER_group = +{ + .name = "ESCC601_POWER", + .attrs = ESCC601_POWER_attributes, +}; + +static const struct attribute_group ESCC601_QSFP_group = +{ + .name = "ESCC601_QSFP", + .attrs = ESCC601_QSFP_attributes, +}; +/* end of struct attribute_group */ diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/zrh2800k2.c b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/zrh2800k2.c new file mode 100644 index 0000000000..a24b2b8836 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/modules/zrh2800k2.c @@ -0,0 +1,684 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_MSG +#ifdef DEBUG_MSG + #define debug_print(s) printk s +#else + #define debug_print(s) +#endif + +//#define SYMBOL_FOR_LM_SENSOR + + +struct zrh2800k2_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 last_energy_value_EIN; + u64 last_smaple_count_EIN; + u64 last_energy_value_EOUT; + u64 last_smaple_count_EOUT; +}; + +typedef enum _access_type_{ + READ_BYTE, + READ_WORD, + READ_BLOCK +}ACCESS_TYPE; + +typedef enum _value_format_{ + FORMAT_NORMAL, + FORMAT_DIRECT, + FORMAT_LINEAR +}VALUE_FORMAT; + +typedef enum _zrh2800k2_regs_ { + REG_CAPABILITY = 0x19, + REG_QUERY = 0X1A, + REG_VOUT_MODE = 0x20, + REG_COEFFICIENTS = 0X30, + REG_FAN_CONFIG_1_2 = 0x3A, + REG_STATUS_WORD = 0x79, + REG_STATUS_VOUT = 0x7A, + REG_STATUS_IOUT = 0x7B, + REG_STATUS_INPUT = 0x7C, + REG_STATUS_TEMPERATURE = 0x7D, + REG_STATUS_FANS_1_2 = 0x81, + REG_READ_EIN = 0x86, /* direct data format */ + REG_READ_EOUT = 0x87, /* direct data format */ + REG_READ_VIN = 0x88, + REG_READ_IIN = 0x89, + REG_READ_VOUT = 0x8B, /* linear data format */ + REG_READ_IOUT = 0x8C, /* linear data format */ + REG_READ_TEMPERATURE1 = 0x8D, /* linear data format */ + REG_READ_FAN_SPEED_1 = 0x90, /* linear data format */ + REG_READ_POUT = 0x96, /* linear data format */ + REG_READ_PIN = 0x97, /* linear data format */ + REG_READ_PMBUS_REVISION = 0x98, + REG_READ_MFR_ID = 0x99, /* ZIPPY 5 BYTES */ + REG_READ_MFR_MODEL = 0x9A, + REG_READ_MFR_VIN_MAX = 0xA4, /* linear data format */ + REG_READ_MFR_IOUT_MAX = 0xA6 /* lineat data format */ +}ZRH2800K2_REGS; + +enum zrh2800k2_sysfs_attributes { + PSU_CAPABILITY, /* 0 */ + PSU_QUERY, + PSU_VOUT_MODE, + PSU_COEFFICIENTS, + PSU_FAN_CONFIG_1_2, + PSU_STATUS_WORD, /* 5 */ + PSU_STATUS_VOUT, + PSU_STATUS_IOUT, + PSU_STATUS_INPUT, + PSU_STATUS_TEMPERATURE, + PSU_STATUS_FANS_1_2, /* 10 */ + PSU_EIN, + PSU_EOUT, + PSU_VIN, + PSU_IIN, + PSU_VOUT, /* 15 */ + PSU_IOUT, + PSU_TEMPERATURE_1, + PSU_FAN_SPEED_1, + PSU_POUT, + PSU_PIN, /* 20 */ + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_VIN_MAX, + PSU_MFR_IOUT_MAX +}; + +struct _OPERATION_SET_ { + ZRH2800K2_REGS reg; + ACCESS_TYPE type; + u8 data_size; // unit: byte, only used for block read +}; + +/* the index of operations are mapping to the zrh2800k2_sysfs_attributes */ +static struct _OPERATION_SET_ operation_set[] = { + { REG_CAPABILITY, READ_BYTE, 1 }, // 0 + { REG_QUERY, READ_BYTE, 1}, // 1 + { REG_VOUT_MODE, READ_BYTE, 1 }, // 2 + { REG_COEFFICIENTS, READ_BLOCK, 5 }, // 3 + { REG_FAN_CONFIG_1_2 , READ_BYTE, 1 }, // 4 + { REG_STATUS_WORD, READ_WORD, 2 }, // 5 + { REG_STATUS_VOUT, READ_BYTE, 1 }, // 6 + { REG_STATUS_IOUT, READ_BYTE, 1 }, // 7 + { REG_STATUS_INPUT, READ_BYTE, 1 }, // 8 + { REG_STATUS_TEMPERATURE, READ_BYTE, 1 }, //9 + { REG_STATUS_FANS_1_2, READ_BYTE, 1 }, // 10 + { REG_READ_EIN, READ_BLOCK, 6 }, // 11 + { REG_READ_EOUT, READ_BLOCK, 6 }, // 12 + { REG_READ_VIN, READ_WORD, 2 }, // 13 + { REG_READ_IIN, READ_WORD, 2 }, // 14 + { REG_READ_VOUT, READ_WORD, 2 }, // 15 + { REG_READ_IOUT, READ_WORD, 2 }, // 16 + { REG_READ_TEMPERATURE1, READ_WORD, 2 }, // 17 + { REG_READ_FAN_SPEED_1, READ_WORD, 2 }, // 18 + { REG_READ_POUT, READ_WORD, 2 }, // 19 + { REG_READ_PIN, READ_WORD, 2 }, // 20 + { REG_READ_PMBUS_REVISION, READ_BYTE, 1 }, //21 + { REG_READ_MFR_ID, READ_BLOCK, 5 }, // 22 + { REG_READ_MFR_MODEL, READ_BLOCK, 9 }, // 23 + { REG_READ_MFR_VIN_MAX, READ_WORD, 2 }, // 24 + { REG_READ_MFR_IOUT_MAX, READ_WORD, 2 } // 25 +}; + + +static int zrh2800k2_remove(struct i2c_client *client); +static int zrh2800k2_probe(struct i2c_client *client, const struct i2c_device_id *dev_id); +static ssize_t show_value(struct device *dev, struct device_attribute *da, char *buf); + +static ssize_t show_capability(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t psu_pm_query(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t psu_coefficient(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_config(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x58, 0x59, I2C_CLIENT_END }; + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(psu_query, S_IRUGO, psu_pm_query, NULL, PSU_QUERY); +static SENSOR_DEVICE_ATTR(psu_coeff, S_IRUGO, psu_coefficient,NULL, PSU_COEFFICIENTS); +static SENSOR_DEVICE_ATTR(psu_fan_config_1_2, S_IRUGO|S_IWUSR, show_value, set_fan_config, PSU_FAN_CONFIG_1_2); +static SENSOR_DEVICE_ATTR(psu_capability, S_IRUGO, show_capability, NULL, PSU_CAPABILITY); +static SENSOR_DEVICE_ATTR(psu_vout_mode, S_IRUGO, show_value, NULL, PSU_VOUT_MODE); +static SENSOR_DEVICE_ATTR(psu_status_word, S_IRUGO, show_value, NULL, PSU_STATUS_WORD); +static SENSOR_DEVICE_ATTR(psu_status_vout, S_IRUGO, show_value, NULL, PSU_STATUS_VOUT); +static SENSOR_DEVICE_ATTR(psu_status_iout, S_IRUGO, show_value, NULL, PSU_STATUS_IOUT); +static SENSOR_DEVICE_ATTR(psu_status_input, S_IRUGO, show_value, NULL, PSU_STATUS_INPUT); +static SENSOR_DEVICE_ATTR(psu_status_temp, S_IRUGO, show_value, NULL, PSU_STATUS_TEMPERATURE); +static SENSOR_DEVICE_ATTR(psu_status_fan_1_2, S_IRUGO, show_value, NULL, PSU_STATUS_FANS_1_2); +static SENSOR_DEVICE_ATTR(psu_ein, S_IRUGO, show_value, NULL, PSU_EIN); +static SENSOR_DEVICE_ATTR(psu_eout, S_IRUGO, show_value, NULL, PSU_EOUT); +static SENSOR_DEVICE_ATTR(psu_pmbus_rev,S_IRUGO, show_value, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_value, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model,S_IRUGO, show_value, NULL, PSU_MFR_MODEL); + +static SENSOR_DEVICE_ATTR(psu_vin, S_IRUGO, show_value, NULL, PSU_VIN); +static SENSOR_DEVICE_ATTR(psu_vout, S_IRUGO, show_value, NULL, PSU_VOUT); +static SENSOR_DEVICE_ATTR(psu_iin, S_IRUGO, show_value, NULL, PSU_IIN); +static SENSOR_DEVICE_ATTR(psu_iout, S_IRUGO, show_value, NULL, PSU_IOUT); +static SENSOR_DEVICE_ATTR(psu_iout_max, S_IRUGO, show_value, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_pin, S_IRUGO, show_value, NULL, PSU_PIN); +static SENSOR_DEVICE_ATTR(psu_pout, S_IRUGO, show_value, NULL, PSU_POUT); + +static SENSOR_DEVICE_ATTR(psu_temp_1, S_IRUGO, show_value, NULL, PSU_TEMPERATURE_1); +static SENSOR_DEVICE_ATTR(psu_fan_speed_1, S_IRUGO, show_value, NULL, PSU_FAN_SPEED_1); + +/* section for lm-sensor */ +#ifdef SYMBOL_FOR_LM_SENSOR +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_value, NULL, PSU_VIN); +// static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO, show_value, NULL, PSU_MFR_VIN_MAX); -> not support +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_value, NULL, PSU_VOUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_value, NULL, PSU_IIN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_value, NULL, PSU_IOUT); +static SENSOR_DEVICE_ATTR(curr2_max, S_IRUGO, show_value, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_value, NULL, PSU_PIN); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_value, NULL, PSU_POUT); + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_value, NULL, PSU_TEMPERATURE_1); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_value, NULL, PSU_FAN_SPEED_1); +#endif + +static struct attribute *zrh2800k2_attributes[] = { + &sensor_dev_attr_psu_query.dev_attr.attr, + &sensor_dev_attr_psu_coeff.dev_attr.attr, + &sensor_dev_attr_psu_fan_config_1_2.dev_attr.attr, + &sensor_dev_attr_psu_capability.dev_attr.attr, + &sensor_dev_attr_psu_vout_mode.dev_attr.attr, + &sensor_dev_attr_psu_status_word.dev_attr.attr, + &sensor_dev_attr_psu_status_vout.dev_attr.attr, + &sensor_dev_attr_psu_status_iout.dev_attr.attr, + &sensor_dev_attr_psu_status_input.dev_attr.attr, + &sensor_dev_attr_psu_status_temp.dev_attr.attr, + &sensor_dev_attr_psu_status_fan_1_2.dev_attr.attr, + &sensor_dev_attr_psu_ein.dev_attr.attr, + &sensor_dev_attr_psu_eout.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_rev.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_vin.dev_attr.attr, + &sensor_dev_attr_psu_vout.dev_attr.attr, + &sensor_dev_attr_psu_iin.dev_attr.attr, + &sensor_dev_attr_psu_iout.dev_attr.attr, + &sensor_dev_attr_psu_iout_max.dev_attr.attr, + &sensor_dev_attr_psu_pin.dev_attr.attr, + &sensor_dev_attr_psu_pout.dev_attr.attr, + &sensor_dev_attr_psu_temp_1.dev_attr.attr, + &sensor_dev_attr_psu_fan_speed_1.dev_attr.attr, +#ifdef SYMBOL_FOR_LM_SENSOR + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_curr2_max.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, +#endif + NULL +}; + +static const struct attribute_group zrh2800k2_group = { + .attrs = zrh2800k2_attributes, +}; + +static u32 easy_pow(u32 num, u32 power) +{ + if(power == 0) + return 1; + + power--; + + while(power) { + num = num*num; + power--; + } + return num; +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + + +static int zrh2800k2_read(struct device *dev, ACCESS_TYPE rtype , ZRH2800K2_REGS reg) +{ + + struct i2c_client *client = to_i2c_client(dev); + struct zrh2800k2_data *data = i2c_get_clientdata(client); + + int result; + + mutex_lock(&data->update_lock); + + if (rtype == READ_BYTE) { + result = i2c_smbus_read_byte_data(client, (u8)reg); + }else if(rtype == READ_WORD) { + result = i2c_smbus_read_word_data(client, (u8)reg); + }else{ + printk(KERN_ALERT "ERROR: unknown read type"); + } + + mutex_unlock(&data->update_lock); + + return result; + +} + + +static int zrh2800k2_read_block(struct device *dev, ZRH2800K2_REGS reg, u8* block_data, int block_data_len) +{ + + struct i2c_client *client = to_i2c_client(dev); + struct zrh2800k2_data *data = i2c_get_clientdata(client); + + int result; + + mutex_lock(&data->update_lock); + + result = i2c_smbus_read_i2c_block_data(client, (u8)reg, block_data_len, block_data); + + mutex_unlock(&data->update_lock); + + if (unlikely(result < 0)) { + goto read_block_exit; + } + + if (result != block_data_len) { + result = -EIO; + goto read_block_exit; + } + + result = 0; + +read_block_exit: + return result; + +} + +static int get_coefficient(struct device* dev, u16* m, u16* b, u8* R) +{ + u8 buf_block[6] = {0}; + int ret = zrh2800k2_read_block(dev, REG_COEFFICIENTS, buf_block, 6); + + + // [ byte_count,m-l,m-h,b-l,b-h,R ] + if (ret < 0) { + printk(KERN_ALERT "get coefficient fail(%d)\n", ret); + return -1; + } + + *R = buf_block[5]; + *m = buf_block[2]; + *m = ((*m)<<8 )+ buf_block[1]; + *b = buf_block[4]; + *b = ((*b)<<8 )+ buf_block[3]; + + debug_print((KERN_DEBUG " coefficient read : 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x \n", buf_block[0], buf_block[1], buf_block[2], + buf_block[3], buf_block[4], buf_block[5])); + debug_print((KERN_DEBUG " coefficient r m b: 0x%x, 0x%x, 0x%x \n", *R, *m, *b)); + + return 0; + +} + + +/* read a byte or word value and show*/ +static ssize_t show_value(struct device *dev, struct device_attribute *da, char *buf) +{ + + u16 u16_val = 0; + int exponent = 0, mantissa = 0; + int multiplier = 1000; // lm-sensor uint: mV, mA, mC + + u8 buf_block[11] = {0}; // used to save enough data from read block. + + char *ascii = NULL; + int ret = 0; + + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + debug_print((KERN_DEBUG "show value op[%d]: reg %d\n", attr->index, + operation_set[attr->index].reg )); + + switch (operation_set[attr->index].type) { + + case READ_BYTE: + case READ_WORD: + ret = zrh2800k2_read(dev, operation_set[attr->index].type , operation_set[attr->index].reg); + break; + + case READ_BLOCK: + ret = zrh2800k2_read_block(dev, operation_set[attr->index].reg, buf_block, operation_set[attr->index].data_size + 1); + break; + + default: + printk(KERN_ALERT "unknown access type\n"); + return 0; + + } + + if (ret < 0) { + printk(KERN_ALERT "ERROR: Read fail ret(%d)\n", ret); + return 0; + } + + /* arrange return buf */ + switch (attr->index) { + + /* case directly return */ + case PSU_STATUS_WORD: + case PSU_VOUT_MODE: + return sprintf(buf, "%d\n", ret); + + case PSU_STATUS_VOUT: + return sprintf(buf, + "VOUT Over Voltage Fault : %d \nVOUT Over Voltage Warning : %d \nVOUT Under Voltage Warning : %d \nVOUT Under Voltage Fault : %d \n", + (ret>>7)&0x1,(ret>>6)&0x1, + (ret>>5)&0x1,(ret>>4)&0x1); + + case PSU_STATUS_IOUT: + return sprintf(buf, + "IOUT Overcurrent Fault : %d \nIOUT Overcurrent Warnning : %d \nPOUT Overcurrent Fault : %d \nPOUT Overcurrent Warnning : %d \n", + (ret>>7)&0x1, (ret>>5)&0x1, + (ret>>1)&0x1, ret&0x1); + + case PSU_STATUS_INPUT: + return sprintf(buf, + "PIN Overpower Warning : %d \n", (ret&0x1)); + + case PSU_STATUS_TEMPERATURE: + return sprintf(buf, + "Overtemperature Fault : %d \nOvertemperature Warning : %d \nUbdertemperature Warning : %d \nUbdertemperature Fault : %d \n", + (ret>>7)&0x1,(ret>>6)&0x1, + (ret>>5)&0x1,(ret>>4)&0x1); + + case PSU_STATUS_FANS_1_2: + return sprintf(buf, + "Fan Fault : %d \nFan Warning : %d \n", + (ret>>7)&0x1, (ret>>5)&0x1); + + case PSU_FAN_CONFIG_1_2: + debug_print((KERN_DEBUG "PSU_FAN_CONFIG_1_2: 0x%X\n",ret)); + return sprintf(buf, + "Fan is installed in Position1: %s\n" \ + "Fan1 speed Unit: %s\n" \ + "Fan1 Tachometer Pulses Per Revolution 0x%x\n" \ + "Fan install in Position2: %s\n" \ + "Fan2 speed Unit: %s\n" \ + "Fan2 Tachometer Pulses Per Revolution 0x%x\n", + (ret>>7)?"YES":"NONE", + ((ret>>6)&0x1)?"RPM":"Duty Cycle", + (ret>>4)&0x3, + (ret>>3&0x01)?"YES":"NONE", + ((ret>>2)&0x1)?"RPM":"Duty Cycle", + ret&0x3); + + /* special case for READ_VOUT */ + case PSU_VOUT: + /* save mantissa */ + mantissa = ret; + + debug_print((KERN_DEBUG "PSU_VOUT: mantissa 0x%X\n",mantissa)); + + /* read the exponent from REG_READ_VMODE */ + ret = zrh2800k2_read(dev, READ_BYTE , REG_VOUT_MODE); + if (ret < 0) { + printk(KERN_ALERT "Error: Read fail ret(%d)\n", ret); + return 0; + } + exponent = two_complement_to_int(ret & 0x1f, 5, 0x1f); + + debug_print((KERN_DEBUG "PSU_VOUT: VOUT_MODE 0x%X\n",ret)); + debug_print((KERN_DEBUG "PSU_VOUT: exponent 0x%X\n",exponent)); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent)*multiplier ) : \ + sprintf(buf, "%d\n", (mantissa*multiplier / (1 << -exponent))); + + /* word data with linear format */ + case PSU_POUT: + case PSU_PIN: + multiplier = 1000000; // lm-sensor unit: uW + case PSU_VIN: + case PSU_IIN: + case PSU_IOUT: + case PSU_TEMPERATURE_1: + case PSU_FAN_SPEED_1: + case PSU_MFR_VIN_MAX: + case PSU_MFR_IOUT_MAX: + + if (attr->index == PSU_FAN_SPEED_1) + multiplier = 1; + + u16_val = ret; + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + + debug_print((KERN_DEBUG "REG(%d): ret 0x%X, u16_val: 0x%x\n", attr->index, ret, u16_val)); + debug_print((KERN_DEBUG "REG(%d): exponent 0x%X\n", attr->index, exponent)); + debug_print((KERN_DEBUG "REG(%d): mantissa 0x%X\n", attr->index, mantissa)); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent)*multiplier ) : \ + sprintf(buf, "%d\n", (mantissa*multiplier / (1 << -exponent))); + + case PSU_EIN: + case PSU_EOUT: { + + u16 m,b; + u8 R; + + u64 ev = buf_block[2]; + u8 rc = buf_block[3]; + u64 sc = buf_block[6]; + u32 sc_mid = buf_block[5]; + u64 average_value = 0; + + struct i2c_client *client = to_i2c_client(dev); + struct zrh2800k2_data *data = i2c_get_clientdata(client); + + if (get_coefficient(dev, &m, &b, &R) < 0) { + return sprintf(buf, "ERROR, fail to get coefficient\n"); + } + + // [ bytecount, energy_count-l, energy_count-h, ROLLOVER_count , + // sample_count-l, sample_count-mid, sample_count-h ] + // maximum_direct_format_value = (m*32767+b)*(10)^R + // energy_value = Rollover_count * maximum_direct_format_value + energy_count + + debug_print((KERN_DEBUG "[ec-l,ec-h,rc,sc-l,sc-,sc-h]: [0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x]\n", buf_block[0], buf_block[1], buf_block[2], + buf_block[3], buf_block[4], buf_block[5], buf_block[6])); + + ev = rc * (m*32767+b)*easy_pow(10,R) + ((ev<<8) + buf_block[1]); + sc = (sc<<16) + (sc_mid<<8) + buf_block[4]; + + if(attr->index == PSU_EIN) { + average_value = ((ev - data->last_energy_value_EIN)*1000) / (sc - data->last_smaple_count_EIN); + data->last_energy_value_EIN = ev; + data->last_smaple_count_EIN = sc; + } else { + average_value = ((ev - data->last_energy_value_EOUT)*1000) / (sc - data->last_smaple_count_EOUT); + data->last_energy_value_EOUT = ev; + data->last_smaple_count_EOUT = sc; + } + return sprintf(buf, "%llu.%llu\n", average_value/1000, average_value%1000); + + } + + case PSU_MFR_ID: + case PSU_MFR_MODEL: + debug_print((KERN_DEBUG "[0x%x,0x%x,0x%x,0x%x,0x%x,0x%x]\n", buf_block[0], buf_block[1], buf_block[2], + buf_block[3], buf_block[4], buf_block[5])); + + ascii = &buf_block[1]; + return sprintf(buf, "%s\n", ascii); + + + case PSU_PMBUS_REVISION: + return sprintf(buf, "Part1 Revision: 1.%d, Part2 Revision: 1.%d\n", + (ret>>5), (ret&0x7) ); + + /* not implement yet */ + default: + return sprintf(buf, "not implement yet\n"); + + } + + /* should not goto here */ + return sprintf(buf, "unknown case\n"); + +} + + +static ssize_t show_capability(struct device *dev, struct device_attribute *da, char *buf) +{ + /* todo */ + return sprintf(buf, "not implement yet\n"); +} + +static ssize_t psu_pm_query(struct device *dev, struct device_attribute *da, char *buf) +{ + /* todo */ + return sprintf(buf, "not implement yet\n"); +} + +static ssize_t psu_coefficient(struct device *dev, struct device_attribute *da, char *buf) +{ + /* todo */ + return sprintf(buf, "not implement yet\n"); +} + +static ssize_t set_fan_config(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct zrh2800k2_data *data = i2c_get_clientdata(client); + + int result; + u8 input_val; + + mutex_lock(&data->update_lock); + + input_val = simple_strtol(buf, NULL, 10); + + result = i2c_smbus_write_byte_data(client, REG_FAN_CONFIG_1_2, input_val); + + mutex_unlock(&data->update_lock); + + if (result < 0) { + printk(KERN_ALERT "ERROR: SET_FAN_CONFIG %s fail\n", buf); + } else { + debug_print((KERN_DEBUG "SET_FAN_CONFIG %s success\n", buf)); + } + + + return count; + +} + + +static const struct i2c_device_id zrh2800k2_id[] = { + { "zrh2800k2", 0 }, + {} +}; + +static struct i2c_driver zrh2800k2_driver = { + .class = I2C_CLASS_HWMON, + .driver = + { + .name = "ZRH2800K2", + }, + .probe = zrh2800k2_probe, + .remove = zrh2800k2_remove, + .id_table = zrh2800k2_id, + .address_list = normal_i2c, +}; + +static int zrh2800k2_remove(struct i2c_client *client) +{ + struct zrh2800k2_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &zrh2800k2_group); + kfree(data); + return 0; + +} + +static int zrh2800k2_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + + struct zrh2800k2_data *data; + int status; + + if(!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct zrh2800k2_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &zrh2800k2_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", dev_name(data->hwmon_dev), + client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &zrh2800k2_group); + +exit_free: + kfree(data); + +exit: + return status; + +} + + +module_i2c_driver(zrh2800k2_driver); +MODULE_AUTHOR("Cameo Inc."); +MODULE_DESCRIPTION("Power Supply zrh-2800k2 driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/scripts/sensors b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/scripts/sensors new file mode 100755 index 0000000000..2dccbf952c --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/scripts/sensors @@ -0,0 +1,8 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" + +#To probe sensors not part of lm-sensors +if [ -r /usr/local/bin/cameo_escc601_sensors.py ]; then + python /usr/local/bin/cameo_escc601_sensors.py fan_status + python /usr/local/bin/cameo_escc601_sensors.py sensor_status +fi diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/service/escc601-platform-init.service b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/service/escc601-platform-init.service new file mode 100644 index 0000000000..03e2674bfd --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/service/escc601-platform-init.service @@ -0,0 +1,14 @@ +[Unit] +Description=Cameo Escc601-32q Platform initialization service +After=local-fs.target innovium_platform_driver.service +Before=pmon.service + + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/cameo_escc601_startup start +ExecStop=/usr/local/bin/cameo_escc601_startup stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/setup.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/setup.py new file mode 100755 index 0000000000..665d5b0177 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='escc601-32Q sonic platform API', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'escc601-32q/sonic_platform'}, +) \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/__init__.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/__init__.py new file mode 100755 index 0000000000..0b887c8c6b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/__init__.py @@ -0,0 +1 @@ +__all__ = ["platform", "chassis", "fan", "psu"] diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/chassis.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/chassis.py new file mode 100755 index 0000000000..1fb378b51b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/chassis.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + import os + import time + import subprocess + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.platDev import PlatDev + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" + + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + _global_port_pres_dict = {} + + def __init__(self): + super(Chassis, self).__init__() + + # Initialize SKU name and Platform name + self.sku_name = self._get_sku_name() + self.platform_name = self._get_platform_name() + self.name = self.sku_name + + # get the device infomation of platform + self.platdev = PlatDev() + + #self._component_list = [] + #self._module_list = [] + #self._fan_drawer_list = [] + + self._eeprom = Eeprom() + # init component + for i in range(self.platdev.get_component_count()): + component = Component(i, self.platdev.get_component_name(i), self.platdev.get_component_descript(i)) + self._component_list.append(component) + # init fan list + if self.platdev.get_fan_support(): + fanlist = self.platdev.get_fan_list() + for index in range(0,len(fanlist)): + fan_name = fanlist[index] + for pos in range(0, self.platdev.get_fan_num_by_name(fan_name)): + fan = Fan( index, pos, [self.platdev.get_fan_sysfile_path_by_name(fan_name),'']) + self._fan_list.append(fan) + + # init psu list + psulist = self.platdev.get_psu_list() + for index in range(0, len(psulist)): + psu_name = psulist[index] + psu = Psu(index, [ self.platdev.get_psu_attr_path_by_name(psu_name), \ + self.platdev.get_psu_status_path_by_name(psu_name) ], \ + self.platdev.bmc_is_exist()) + self._psu_list.append(psu) + + # init thermal list + thermal_info_list = self.platdev.get_thermal_dev_info_all() + for index in range(0, len(thermal_info_list)): + if len(self.platdev.get_thermal_dev_tempidx_by_idx(index)) > 1: + for idx in self.platdev.get_thermal_dev_tempidx_by_idx(index): + thermal = Thermal(idx, self.platdev.get_thermal_dev_name_by_idx(index)+"-{}".format(idx), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(),\ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + else: + thermal = Thermal(1, self.platdev.get_thermal_dev_name_by_idx(index), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(), \ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + + # init sfp list + port_num = 1 + for sfpg_name in self.platdev.get_sfp_group_list(): + if self.platdev.get_sfp_group_type_by_name(sfpg_name) == 'QSFP28': + sfp_type = QSFP_TYPE + else: + sfp_type = SFP_TYPE + + for x in range(0,self.platdev.get_sfp_group_number_by_name(sfpg_name)): + eeprom_path_list = ['n/a','n/a'] + if self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] != 'n/a': + eeprom_path_list[0] = self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] + '/eeprom' + if os.path.exists(eeprom_path_list[0].replace("0050", "0051")): + eeprom_path_list[1] = eeprom_path_list[0].replace("0050", "0051") + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + sfp = Sfp(port_num, eeprom_path_list, sfp_type, self.platdev.get_sfp_ext_sysfile_list()) + port_num += 1 + self._sfp_list.append(sfp) + + self.init_global_port_presence() + + def _get_sku_name(self): + p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + + def _get_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.name + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr('') + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + # not support any hardware reboot, just return REBOOT_CAUSE_NON_HARDWARE + # to keep reboot cause as software reboot + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + ############################################## + # System LED methods + ############################################## + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + return False + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + raise NotImplementedError + + ############################################## + # Other methods + ############################################## + + def init_global_port_presence(self): + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + port_dict = {} + while True: + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, {'sfp':port_dict} + + time.sleep(1) + + + def sfp_debugger(self): + """ + Try to show all parameters read from eeprom with sfp methods + """ + print("SFP EEPROM data:") + for n in range(0, len(self._sfp_list)): + print("======SFP{}==TYPE {}====".format(n, self._sfp_list[n].sfp_type)) + print("get_transceiver_info:") + print(self._sfp_list[n].get_transceiver_info()) + print(" ") + + print("get_transceiver_threshold_info:") + print(self._sfp_list[n].get_transceiver_threshold_info()) + print(" ") + + print("get_transceiver_bulk_status:") + print(self._sfp_list[n].get_transceiver_bulk_status()) + print(" ") + + print("get_lpmode:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_lpmode())) + # set_lpmode + + print("get_power_override:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_power_override())) + + print("get_temperature:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_temperature())) + + print("get_voltage") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_voltage())) + + print("get_tx_bias") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_bias())) + + print("get_rx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_rx_power())) + + print("get_tx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_power())) + + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/component.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/component.py new file mode 100755 index 0000000000..261c31c3d1 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/component.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +######################################################################## +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + def __init__(self, idx,name,descript): + self.index = idx + self.name = name + self.description = descript + + def _get_cpld_register(self, syspath): + rv = 'ERR' + if (not os.path.isfile(syspath)): + return rv + # noinspection PyBroadException + try: + with open(syspath, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def _get_cpld_version(self, cpld_number): + cpld_version_reg = { + 1: "/sys/class/hwmon/hwmon2/device/ESCC601_SYS/cpld_30_ver", + 2: "master_cpld_ver", + 3: "slave_cpld_ver" + } + + cpld_version = self._get_cpld_register(cpld_version_reg[cpld_number]) + + if cpld_version != 'ERR': + return cpld_version[-4:] + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + bios_ver = self._get_bios_version() + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index <= 3: + return self._get_cpld_version(self.index) + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/eeprom.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/eeprom.py new file mode 100755 index 0000000000..8740c4c11a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/eeprom.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +try: + import os + import sys + import re + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + # noinspection PyBroadException + try: + match = re.search( + '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) + if match is not None: + idx = match.group(1) + value = match.group(3).rstrip('\0') + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + err = self.read_eeprom_db() + if err: + # Failed to read EEPROM information from database. Read from cache file + pass + else: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + return self.__parse_output(decode_output) + + status = self.check_status() + if status < 'ok': + return {} + + if not os.path.exists(CACHE_ROOT): + # noinspection PyBroadException + try: + os.makedirs(CACHE_ROOT) + except Exception: + pass + + # + # only the eeprom classes that inherit from eeprom_base + # support caching. Others will work normally + # + # noinspection PyBroadException + try: + self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE)) + except Exception: + pass + + data = self.read_eeprom() + if data is None: + return 0 + # noinspection PyBroadException + try: + self.update_cache(data) + except Exception: + pass + + self.decode_eeprom(data) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(data) + if not is_valid: + return {} + + return self.__parse_output(decode_output) + + def get_eeprom(self): + return self._eeprom + + + def serial_number_str(self): + """ + Returns the serial number + """ + return self._eeprom.get('0x23', "Undefined.") + + def base_mac_addr(self, e): + """ + Returns the base mac address found in the system EEPROM + """ + return self._eeprom.get('0x24', "Undefined.") + + def modelstr(self): + """ + Returns the Model name + """ + return self._eeprom.get('0x28', "Undefined.") + + def part_number_str(self): + """ + Returns the part number + """ + return self._eeprom.get('0x22', "Undefined.") + + def revision_str(self): + """ + Returns the device revision + """ + return self._eeprom.get('0x26', "Undefined.") + + def serial_str(self): + return self._eeprom.get('0x2F', "Undefined.") + + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self._eeprom \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/fan.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/fan.py new file mode 100755 index 0000000000..278b5cb998 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/fan.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +FAN_POSITION_NAME = ["Front","Rear"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_index, position_index, attr_path, psu_fan = False): + # fan_index: the index of a fan module belongs to + # position_index : position of the fan in a fan module, 0 -> front, 1 -> rear, + # position_index : index of PSU belongs to if psu_fan is True, start from 0 + super(Fan, self).__init__() + self.index = fan_index + 1 + self.position = position_index + self.is_psu_fan = psu_fan + self.attr_path = attr_path[0] + + if psu_fan is True: + self.fan_name = "PSU{}_FAN{}".format(self.index, self.position+1) + self.speed_file = attr_path[1] + else: + self.fan_name = "FAN{}-{}".format(self.index, FAN_POSITION_NAME[self.position]) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_presence(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_prnt'.format(self.index)) + if data == '1': + return True + else: + return False + ret = self.__read_attr_file(self.attr_path + 'fan{}_present'.format(self.index)) + if ret == '1': + return True + elif ret == '0': + return False + else: + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.fan_name + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + return self.FAN_DIRECTION_NOT_APPLICABLE + + def get_status(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_good'.format(self.index)) + if data == '1': + return True + else: + return False + data = self.__read_attr_file(self.attr_path + 'fan{}_stat'.format(self.index)) + if data == '1': + return True + elif data == '0': + return False + else: + return False + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan is True and self.get_presence(): + speed = self.__read_attr_file( self.speed_file, 0) + if speed is not None: + return (int(speed)*100)//16000 + else: + return 0 + + if self.get_presence(): + if self.position ==0: + speed_file =self.attr_path + 'fan{}_front_rpm'.format(self.index) + else: + speed_file =self.attr_path + 'fan{}_rear_rpm'.format(self.index) + data = self.__read_attr_file(speed_file) + if data is not None: + for sdata in data.split(' '): + if sdata.isdigit(): + return (int(sdata)*100)//18000 + return 0 + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + return self.get_speed() + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + """ + raise NotImplementedError + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platDev.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platDev.py new file mode 100755 index 0000000000..a6a94c09ac --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platDev.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python + +try: + import os + import copy + import json + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("paltDev") +PLATFORM_INSTALL_INFO_FILE = "/etc/sonic/platform_install.json" +PLATFORM_NAME = "escc601_32q" +MAX_FAN_MODULE = 5 +MAX_FAN = 2 + +# THERMAL_SENSOR_LIST +# index is used to indicate the default temp{}_* under sysfile_path +# support_mask: 1:support 0:not support +# bit 0 : temperature (always 1) +# bit 1 : high threshold +# bit 2 : low threshold +# bit 3 : high critical threshold +# bit 4 : low critical threshold +# bit 7 : cpu internal sensor +# ext_sysfile_list: each specified path of each supported function, +# which not follows the (default) genernal naming rule +# [0] ext_temp_file : temperature +# [1] ext_high_thr : high threshold +# [2] ext_low_thr : low threshold +# [3] ext_high_cri_thr : high critical threshold +# [4] ext_low_cri_thr : low critical threshold + +THERMAL_SENSOR_LIST = [ + { + 'name': "pch_haswell", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon0/", + 'support_mask': 0x81, + 'ext_sysfile_list': None + }, + { + 'name': "CPU core temp", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon1/", + 'support_mask': 0x8B, + 'ext_sysfile_list': None + }, + { + 'name': "NCT7511Y(U73)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon6/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_r_b_f', 'temp_r_b_f_max', 'temp_r_b_f_min', 'temp_r_b_f_crit', 'temp_r_b_f_lcrit'], + 2:['temp_r_b_b', 'temp_r_b_b_max', 'temp_r_b_b_min', 'temp_r_b_b_crit', 'temp_r_b_b_lcrit']} + }, + { + 'name': "G781(U94)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon3/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_l_b_f', 'temp_l_b_f_max', 'temp_l_b_f_min', 'temp_l_b_f_crit', 'temp_l_b_f_lcrit'], + 2:['temp_l_b_b', 'temp_l_b_b_max', 'temp_l_b_b_min', 'temp_l_b_b_crit', 'temp_l_b_b_lcrit']} + }, + { + 'name': "G781(U34)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon5/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_r_t_f', 'temp_r_t_f_max', 'temp_r_t_f_min', 'temp_r_t_f_crit', 'temp_r_t_f_lcrit'], + 2:['temp_r_t_b', 'temp_r_t_b_max', 'temp_r_t_b_min', 'temp_r_t_b_crit', 'temp_r_t_b_lcrit']} + }, + { + 'name': "G781(U4)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon4/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_l_t_f', 'temp_l_t_f_max', 'temp_l_t_f_min', 'temp_l_t_f_crit', 'temp_l_t_f_lcrit'], + 2:['temp_l_t_b', 'temp_l_t_b_max', 'temp_l_t_b_min', 'temp_l_t_b_crit', 'temp_l_t_b_lcrit']} + } +] + +# PSU LIST +# ext_sysfile_list +# [0] : sysfile path for present +# [1] : sysfile path for status +# +PSU_LIST = ['PSU1', 'PSU2'] + +PSU_INFO = { + 'PSU1': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESCC601_POWER/" + }, + 'PSU2': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESCC601_POWER/" + } +} + +# SFP LIST +# +# +FAN_LIST = ['FAN1', 'FAN2', 'FAN3', 'FAN4', 'FAN5'] + +FAN_INFO = { + 'FAN1': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESCC601_FAN/' + }, + 'FAN2': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESCC601_FAN/' + }, + 'FAN3': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESCC601_FAN/' + }, + 'FAN4': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESCC601_FAN/' + }, + 'FAN5': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESCC601_FAN/' + } +} + + +# SFP LIST +# +# +# 0: QSFP +# 1: SFP +# sfp not port on escc601 platform + +SFP_EXT_SYSFILE_LIST = ["/sys/class/hwmon/hwmon2/device/ESCC601_QSFP/", ""] + +SFP_GROUP_LIST = ['SFP-G01', 'SFP-G02', 'SFP-G03', 'SFP-G04'] + +PORT_NUM = 32 + +# SFP-eeprom paths /sys/bus/i2c/devices/XX-0050 +SFP_GROUP_INFO = { + "SFP-G01": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G02": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G03": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + }, + "SFP-G04": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + } +} + +# +#Component +# ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " +# "modules (1-16)")], +# ["Slave-CPLD", "Used for managing QSFP modules (17-32)"] + +CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["System-CPLD", "Used for managing CPU board devices and power"] +] + +class PlatDev(): + def __init__(self): + self.plat_name = PLATFORM_NAME + self.psu_info = copy.deepcopy(PSU_INFO) + self.thermal_info = [] + self.fan_info = copy.deepcopy(FAN_INFO) + self.sfp_info = copy.deepcopy(SFP_GROUP_INFO) + self.device_install_info = dict() + self.sfp_install_info = dict() + + # get install info + self.get_dev_install_info() + # update path info with install info + # Item 1/2 not changed, append directly + self.thermal_info.append(THERMAL_SENSOR_LIST[0]) + self.thermal_info.append(THERMAL_SENSOR_LIST[1]) + + for i in range(2, len(THERMAL_SENSOR_LIST)): + install_info = self.device_install_info.get(THERMAL_SENSOR_LIST[i]['name']) + if install_info : + if self.bmc_is_exist(): + THERMAL_SENSOR_LIST[i]['sysfile_path'] = '/sys/class/hwmon/hwmon2/device/ESCC601_THERMAL/' + else: + if install_info.get('hwmon_path') is None: + continue + THERMAL_SENSOR_LIST[i]['sysfile_path'] = install_info.get('hwmon_path') + self.thermal_info.append(THERMAL_SENSOR_LIST[i]) + + for psu_name in PSU_LIST: + install_info = self.device_install_info.get(psu_name) + if install_info: + if self.bmc_is_exist(): + self.psu_info[psu_name]['attr_path']= '/sys/class/hwmon/hwmon2/device/ESCC601_POWER/' + else: + self.psu_info[psu_name]['attr_path'] = install_info.get('hwmon_path')+ '/device/' + + for sfp_group_name in SFP_GROUP_LIST: + install_info = self.sfp_install_info.get(sfp_group_name) + if install_info: + self.sfp_info[sfp_group_name]['paths'] = install_info.get('paths') + + def get_dev_install_info(self): + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + self.sfp_install_info = install_info[2] + self.device_install_info = install_info[1] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def bmc_is_exist(self): + bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESCC601_SYS/bmc_present' + if os.path.exists(bmc_filePath): + value = self.__read_attr_file(bmc_filePath) + if int(value) == 1: + return True + else: + return False + else: + return False + ######Componet method ##### + def get_component_count(self): + return len(CHASSIS_COMPONENTS) + + def get_component_name(self,idx): + return CHASSIS_COMPONENTS[idx][0] + + def get_component_descript(self,idx): + return CHASSIS_COMPONENTS[idx][1] + + ###### PSU method ###### + def get_psu_list(self): + return PSU_LIST + + def get_psu_info_all(self): + return self.psu_info + + def get_psu_info_by_name(self, name): + return self.psu_info.get(name) + + def get_psu_attr_path_by_name(self, name): + return self.psu_info[name].get('attr_path') + + def get_psu_status_path_by_name(self, name): + return self.psu_info[name].get('status_path') + + ###### Thermal method ###### + def get_thermal_dev_info_all(self): + return self.thermal_info + + def get_thermal_dev_name_by_idx(self, index): + return self.thermal_info[index].get('name') + + def get_thermal_dev_tempidx_by_idx(self, index): + return self.thermal_info[index].get('temp_index') + + def get_thermal_dev_sysfile_path_by_idx(self, index): + return self.thermal_info[index].get('sysfile_path') + + def get_thermal_dev_support_mask_by_idx(self, index): + return self.thermal_info[index].get('support_mask') + + def get_thermal_dev_ext_sysfile_list_by_idx(self, index): + return self.thermal_info[index].get('ext_sysfile_list') + + ###### Fan method ###### + def get_fan_support(self): + return True + + def get_fan_list(self): + return FAN_LIST + + def get_fan_info_all(self): + return self.fan_info + + def get_fan_info_by_name(self, name): + return self.fan_info.get(name) + + def get_fan_sysfile_path_by_name(self, name): + return self.fan_info[name].get('attr_path') + + def get_fan_is_draw_by_name(self, name): + return self.fan_info[name].get('isdraw') + + def get_fan_num_by_name(self, name): + return self.fan_info[name].get('fan_num') + + ###### SFP method ###### + def get_sfp_num(self): + return PORT_NUM + + def get_sfp_group_list(self): + return SFP_GROUP_LIST + + def get_sfp_group_info(self): + return self.sfp_info + + def get_sfp_group_info_by_name(self, name): + return self.sfp_info.get(name) + + def get_sfp_group_type_by_name(self, name): + return self.sfp_info[name].get('type') + + def get_sfp_group_path_by_name(self, name): + return self.sfp_info[name].get('paths') + + def get_sfp_group_number_by_name(self, name): + return self.sfp_info[name].get('number') + + def get_sfp_ext_sysfile_list(self): + return SFP_EXT_SYSFILE_LIST + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platform.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platform.py new file mode 100755 index 0000000000..2456a6f2e7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/platform.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/psu.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/psu.py new file mode 100755 index 0000000000..20e365e73d --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/psu.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common.logger import Logger + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +# To do: should be defined in platDev +PSU_MAX_VOUT = 12.0 # voltage +PSU_MIN_VOUT = 3.3 # voltage +PSU_MAX_TEMP = 50.0 # C + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, index, info_list,is_bmc): + PsuBase.__init__(self) + self.index = index + self.is_bmc = is_bmc + self.attr_path = info_list[0] + self.status_path = info_list[1] + if is_bmc: + speed_file = self.attr_path + 'psu{}_fan_speed'.format(index+1) + else: + speed_file = self.attr_path + 'psu_fan_speed_1' + + fan = Fan( index, 0, [self.status_path, speed_file ],True) + self._fan_list.append(fan) + self.psu_name = "PSU{}".format(self.index+1) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.psu_name + + def get_presence(self): + """ + Retrieves the presence status of power supply unit (PSU) defined + Returns: + bool: True if PSU is present, False if not + """ + data = self.__read_attr_file(self.status_path + 'psu{}_prnt'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + data = self.__read_attr_file(self.status_path + 'psu{}_good'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_vout'.format(self.index+1) + else: + path = self.attr_path + "/psu_vout" + vout = self.__read_attr_file( path, 0) + if vout is not None: + return float(vout) / 1000 + + return False + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_iout'.format(self.index+1) + else: + path = self.attr_path + "/psu_iout" + iout = self.__read_attr_file( path, 0) + if iout is not None: + return float(iout) / 1000 + return False + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_pout'.format(self.index+1) + else: + path = self.attr_path + "/psu_pout" + pout = self.__read_attr_file( path, 0) + if pout is not None: + return float(pout) / 1000000 + return False + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + raise NotImplementedError + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.is_bmc: + path = self.attr_path+'psu{}_temp'.format(self.index+1) + else: + path = self.attr_path + "/psu_temp_1" + temperature = self.__read_attr_file( path, 0) + if temperature is not None: + return float(temperature) / 1000 + + return False + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return PSU_MAX_TEMP + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MAX_VOUT + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MIN_VOUT diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/sfp.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/sfp.py new file mode 100755 index 0000000000..76dda53aab --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/sfp.py @@ -0,0 +1,1175 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common.logger import Logger + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("sfp") + +############################################################################# +# +# SFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# ------------------------------------------------ 0 +# | Serial ID Defined by SFP MSA (96 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 95 +# | Vendor Specific (32 bytes) | +# |----------------------------------------------| 127 +# | Reserved, SFF-8079 (128 byte) | +# ------------------------------------------------ 255 +# +# 2 wire address 1010001x (A2h) (i2c 0x51) +# ------------------------------------------------ 0 +# | Alarm and Warning Threshold (56 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 55 +# | Cal Constants (40 bytes) | +# |----------------------------------------------| 95 +# | Real Time Diagnostic Interface(24 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 119 +# | Vendor Specific (7 bytes) | +# |----------------------------------------------| 126 +# | Page Select Byte (Optional) | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# Page 00h/01h +# |----------------------------------------------| 128 +# | User Writeable EEPROM (120 bytes) | +# |----------------------------------------------| 247 +# | Vendor Specific (8 bytes) | +# ------------------------------------------------ 255 +# Page 02h +# |----------------------------------------------| 128 +# | Control Function (128 bytes) | +# ------------------------------------------------ 255 +# Page 03h-7Fh +# |----------------------------------------------| 128 +# | Reserved (128 bytes) | +# ------------------------------------------------ 255 +# Page 80h-FFh +# |----------------------------------------------| 128 +# | Vendor Specific (128 bytes) | +# ------------------------------------------------ 255 +# +# ========================================================== +# QSFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# +# ------------------------------------------------ 0 +# | ID and status (3 bytes) | +# |----------------------------------------------| 2 +# | Interrupt Flags (19 bytes) | +# |----------------------------------------------| 21 +# | Module Monitors (12 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 33 +# | Channel Monitors (12 bytes) | +# |----------------------------------------------| 81 +# | Reserved (4 bytes) | +# |----------------------------------------------| 85 +# | Control (12 bytes) | <- get_power_override +# |----------------------------------------------| 97 +# | ~~~ | +# |----------------------------------------------| 126 +# | Page Select Byte | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# +# Page 00h +# |----------------------------------------------| 128 +# | Base ID Filed (64 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 191 +# | Extended ID (32 bytes) | +# |----------------------------------------------| 223 +# | Vendor Specific ID (8 bytes) | +# ------------------------------------------------ 255 +# Page 01h (optional) +# |----------------------------------------------| 128 +# | ~~~~ (128 bytes) | +# ------------------------------------------------ 255 +# Page 02h (optional) +# |----------------------------------------------| 128 +# | User EEPROM Data (128 bytes) | +# ------------------------------------------------ 255 + +# Page 03h (optional on QSFP28) +# |----------------------------------------------| 128 +# | Module Threshold (48 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 175 +# | Channel Threshold (48 bytes) | +# |----------------------------------------------| 223 +# | Reserved (2 bytes) | +# |----------------------------------------------| 225 +# | Vendor Specific Channel Controls (16 bytes) | +# |----------------------------------------------| 241 +# | Channel Monitor Masks (12 bytes) | +# |----------------------------------------------| 253 +# | Reserved (2 bytes) | +# ------------------------------------------------ 255 +# +# +# +# +# +# +# +# +############################################################################# + +# function eunm +SFP_GET_PRESENCE=0 +SFP_RESET =1 +SFP_GET_LOW_POWER_MODE=2 +SFP_SET_LOW_POWER_MODE=3 + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] + +# index for A0H, A2H sysfs file path +INDEX_A0H = 0 +INDEX_A2H = 1 + +# offset/width definition +OFFSET = 0 +WIDTH = 1 + +QSFP_UPPER_MEMORY_PAGE00_OFFSET = 128 +QSFP_UPPER_MEMORY_PAGE03_OFFSET = 512 + +SFP_A0H_OFFSET = 0 +SFP_A2H_OFFSET = 0 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 +ID_FIELD_WIDTH = 92 + +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 1 +QSFP_INTERFACE_BULK_WIDTH = 20 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 5], + 'DEVICE_TECH': [19, 1], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 2], + 'WAVELENGTH': [58, 2], + 'WAVELENGTH_TOLERANCE': [60, 2], + 'MAX_CASE_TEMP': [62, 1], + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 4], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [22, 2], + 'VOLTAGE': [26, 2], + 'CHANNEL_MON': [34, 24], + 'CONTROL': [86, 12], + # PAGE03 + 'MODULE_THRESHOLD': [0, 24], + 'CHANNEL_THRESHOLD': [50, 24] +} +SFP_INTERFACE_BULK_WIDTH = 21 +SFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 6], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 4], + 'WAVELENGTH': [60, 2], + # UNALLOCATED WIDDTH: 1 + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 2], + 'BITRATE_MAX': [66, 1], + # BITRATE_MAX ?? + 'BITRATE_MAX_1': [67, 1], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [96, 2], + 'VOLTAGE': [98, 2], + 'CHANNEL_MON': [100, 6], + 'MODULE_THRESHOLD': [0, 40] +} + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes','FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia','FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + def __init__(self, index, eeprom_path_list, sfp_type, ext_sysfile_list=None): + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + # ext_sysfile_list[0]: QSFP path + # ext_sysfile_list[1]: SFP path + self.index = index + self.eeprom_path_list = eeprom_path_list + #self._get_sfp_type(sfp_type) + self.sfp_type = sfp_type + if self.sfp_type == QSFP_TYPE: + self.present_file = ext_sysfile_list[0]+ 'qsfp{}_present'.format(self.index) + self.reset_file = ext_sysfile_list[0]+ 'qsfp{}_reset'.format(self.index) + self.lp_file = ext_sysfile_list[0]+ 'qsfp{}_low_power'.format(self.index) + else: + self.present_file = ext_sysfile_list[1]+ 'sfp{}_present'.format(self.index) + self.reset_file = None + self.lp_file = None + + def _get_sfp_type(self, sfp_type): + ty = self._read_eeprom_bytes(SFP_ID_FIELDS['TYPE'][OFFSET], SFP_ID_FIELDS['TYPE'][WIDTH], INDEX_A0H) + if ty is not None: + if ty[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + if ty[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + else: + self.sfp_type = sfp_type + logger.log_warning("Unreganized sfp type of module {} . unsupported, treated as specified type {}".format(self.index, sfp_type)) + else: + self.sfp_type = sfp_type + + + def _read_eeprom_bytes(self, offset, num_bytes, path_idx): + eeprom_raw = [] + + eeprom = None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom = open(self.eeprom_path_list[path_idx], mode="rb", buffering=0) + eeprom.seek(offset) + raw_data = eeprom.read(num_bytes) + for nb in range(0, len(raw_data)): + eeprom_raw[nb] = hex(ord(raw_data[nb]))[2:].zfill(2) + except Exception as ex: + logger.log_error("Fail to read eeprom {}".format(self.eeprom_path_list[path_idx])) + logger.log_error(" {}".format(ex)) + if eeprom is not None: + eeprom.close() + return None + + return eeprom_raw + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def __write_attr_file(self, filepath, data): + try: + with open(filepath,'w') as fd: + return fd.write(data) + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + return 0 + + def get_presence(self): + if self.present_file is not None: + data = self.__read_attr_file(self.present_file) + if data is not None: + if int(data) == 1: + return True + return False + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return '-inf' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == QSFP_TYPE: + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self._read_eeprom_bytes((offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self._read_eeprom_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH,INDEX_A0H) + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + qspf_dom_capability = int(qsfp_dom_capability_raw[0], 16) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qspf_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qspf_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qspf_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + qsfp_option_value_raw = self._read_eeprom_bytes(QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH,INDEX_A0H) + if qsfp_option_value_raw is not None: + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + self.optional_capability = sfpd_obj.parse_option_params(qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = self.optional_capability['data']['TxDisable']['value'] == 'On' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + elif self.sfp_type == SFP_TYPE: + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self._read_eeprom_bytes(XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = (int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + transceiver_info_dict_keys = [ + 'type', 'hardware_rev', + 'serial', 'manufacturer', + 'model', 'connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui','application_advertisement'] + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE00_OFFSET # upper memory map: Page 00h + Id_field = QSFP_ID_FIELDS + info_bulk_width = QSFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8436InterfaceId() + + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A0H_OFFSET # lower memory map: A0h (SFP i2c 0x50) + Id_field = SFP_ID_FIELDS + info_bulk_width = SFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8472InterfaceId() + else: + logger.log_error("Unsupported sfp type") + return None + + if sfpi_obj is None: + logger.log_error("sfpi_obj create fail") + return None + + # read Base ID field + sfp_interface_bulk_raw = self._read_eeprom_bytes(field_offset, ID_FIELD_WIDTH, INDEX_A0H) + if sfp_interface_bulk_raw is None: + logger.log_error(" Fail to read BaseID field of module {}".format(self.index+1)) + return None + + start = 0 + end = start + info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_NAME'][OFFSET] + end = start + Id_field['VENDOR_NAME'][WIDTH] + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_PN'][OFFSET] + end = start + Id_field['VENDOR_PN'][WIDTH] + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_REV'][OFFSET] + end = start + Id_field['VENDOR_REV'][WIDTH] + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_SN'][OFFSET] + end = start + Id_field['VENDOR_SN'][WIDTH] + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_OUI'][OFFSET] + end = start + Id_field['VENDOR_OUI'][WIDTH] + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_DATE'][OFFSET] + end = start + Id_field['VENDOR_DATE'][WIDTH] + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + + compliance_code_dict = {} + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = [ + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] + transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] + transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] + transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] + transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] + transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] + transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num(transceiver_dom_info_dict[key]) + + return transceiver_dom_info_dict + + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + dom_info_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + + transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE03_OFFSET # uppper memory map: Page 03h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return transceiver_dom_threshold_info_dict + + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['MODULE_THRESHOLD'][OFFSET], Id_field['MODULE_THRESHOLD'][WIDTH], path_idx) + + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_THRESHOLD'][OFFSET], Id_field['CHANNEL_THRESHOLD'][WIDTH], path_idx) + + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + else: # SFP_TYPE + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + raise NotImplementedError + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + raise NotImplementedError + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + raise NotImplementedError + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + raise NotImplementedError + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + raise NotImplementedError + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.lp_file is not None: + data = self.__read_attr_file(self.lp_file, 0) + if data is not None: + if int(data) == 1: + return True + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + + if self.sfp_type == QSFP_TYPE: + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_bytes(Id_field['CONTROL'][OFFSET], Id_field['CONTROL'][WIDTH], INDEX_A0H) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + + return False + else: + return NotImplementedError + + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + path_idx = INDEX_A0H + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + + return None + + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + path_idx = INDEX_A0H + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + volt = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return volt + + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + path_idx = INDEX_A0H + tx_bias_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value'])) + + return tx_bias_list + + return None + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + path_idx = INDEX_A0H + rx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value'])) + + return rx_power_list + + return None + + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + path_idx = INDEX_A0H + tx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value'])) + + return tx_power_list + + return None + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + if self.reset_file is not None: + ret = self.__write_attr_file(self.reset_file, '1') + if ret != 0: + return True + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.lp_file is not None: + if lpmode is True: + ret = self.__write_attr_file(self.lp_file, "1") + else: + ret = self.__write_attr_file(self.lp_file, "0") + if ret != 0: + return True + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + return False + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/thermal.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/thermal.py new file mode 100755 index 0000000000..3731edaa7b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/sonic_platform/thermal.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +logger = Logger("thermal") +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + def __init__(self, index, name, sysfile_path, is_bmc, support_mask=0x1, ext_sysfile_list=None): + # index is used to indicate the temp{} under sffile_path + # support_mask: 1:support 0:not support + # bit 0 : temperature (always 1) + # bit 1 : high threshold + # bit 2 : low threshold + # bit 3 : high critical threshold + # bit 4 : low critical threshold + # bit 7 : cpu internal sensor + # ext_sysfile_list: each specified path of each supported function, + # which not follows the general naming rule + + self.index = index + self.name = name + self.filepath = sysfile_path + self.support_mask = support_mask + self.is_bmc = is_bmc + + self.temperature_file = None + self.high_thershold_file = None + self.low_threshold_file = None + self.high_critical_file = None + self.low_critical_file = None + + if sysfile_path is None: + return + + if self.is_bmc ==False or support_mask & 0x80 == 0x80: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + "/temp{}_input".format(self.index) + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + "/temp{}_max".format(self.index) + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + "/temp{}_min".format(self.index) + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + "/temp{}_crit".format(self.index) + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + "/temp{}_lcrit".format(self.index) + elif self.is_bmc and ext_sysfile_list is not None: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + ext_sysfile_list[self.index][0] + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + ext_sysfile_list[self.index][1] + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + ext_sysfile_list[self.index][2] + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][3] + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][4] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.name + + def get_presence(self): + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.temperature_file is not None: + temp = self.__read_attr_file( self.temperature_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_thershold_file is not None: + temp = self.__read_attr_file( self.high_thershold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_threshold_file is not None: + temp = self.__read_attr_file( self.low_threshold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_file is not None: + temp = self.__read_attr_file( self.high_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_critical_file is not None: + temp = self.__read_attr_file( self.low_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/templates/cameo_escc601_util.py.j2 b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/templates/cameo_escc601_util.py.j2 new file mode 100644 index 0000000000..f727d3a2da --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/templates/cameo_escc601_util.py.j2 @@ -0,0 +1,737 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Cameo Networks, Inc. + + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +import json + +PROJECT_NAME = 'escc601_32q' +verbose = False +DEBUG = False +FORCE = 0 + +PLATFORM_INSTALL_INFO_FILE="/etc/sonic/platform_install.json" + +PLATFORM_DRIVER_VER = {{ env("PLATFORM_DRIVER_VER") }} + +# default is 'i2c-0', we will choose the correct one from 'i2c-0' and 'i2c-1'. +DEFAULT_BASE_BUS = 'i2c-0' +BASE_BUS = 'i2c-0' + +I2C_BASE_BUS = { + 'i2c-0':{ + 'path':'/sys/bus/i2c/devices/i2c-0', + 'status':'INSTALLED' + }, + 'i2c-1':{ + 'path':'/sys/bus/i2c/devices/i2c-1', + 'status':'INSTALLED' + } +} + +switch_install_order = [ +'PCA9548_0x73', +'PCA9548_0x71_1', +'PCA9548_0x71_2', +'PCA9548_0x71_3', +'PCA9548_0x71_4', +'PCA9548_0x75' +] + +I2C_SWITCH_LIST = { + # i2c switches + 'PCA9548_0x73': { + 'parent':'base', + 'driver':'pca9548', + 'i2caddr': '0x73', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x75': { + 'parent':'base', + 'driver':'pca9548', + 'i2caddr': '0x75', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_1': { + 'parent':'PCA9548_0x73', + 'parent_ch': 4, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_2': { + 'parent':'PCA9548_0x73', + 'parent_ch': 5, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_3': { + 'parent':'PCA9548_0x73', + 'parent_ch': 6, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + }, + 'PCA9548_0x71_4': { + 'parent':'PCA9548_0x73', + 'parent_ch': 7, + 'driver':'pca9548', + 'i2caddr': '0x71', + 'path': ' ', + 'bus_map': [0,0,0,0,0,0,0,0], + 'status':'NOTINST' + } +} + +I2C_DEVICES = { + # sys eeprom + 'SYS_EEPROM': { + 'parent':'base', + 'driver':'24c64smbus', + 'i2caddr': '0x56', + 'path': ' ', + 'status':'NOTINST' + }, + # NCT7511Y sensor & fan control + 'NCT7511Y(U73)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 0, + 'driver':'nct7511', + 'i2caddr': '0x2e', + 'path': ' ', + 'status':'NOTINST' + }, + # G781 sensors + 'G781(U94)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 1, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U4)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 2, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + 'G781(U34)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 3, + 'driver':'g781', + 'i2caddr': '0x4c', + 'path': ' ', + 'status':'NOTINST' + }, + # PSU + 'PSU1': { + 'parent':'PCA9548_0x75', + 'parent_ch': 4, + 'driver':'zrh2800k2', + 'i2caddr': '0x58', + 'path': ' ', + 'status':'NOTINST' + }, + 'PSU2': { + 'parent':'PCA9548_0x75', + 'parent_ch': 4, + 'driver':'zrh2800k2', + 'i2caddr': '0x59', + 'path': ' ', + 'status':'NOTINST' + }, + 'TPS53681(0x6C)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 5, + 'driver':'tps53679', + 'i2caddr': '0x6c', + 'path': ' ', + 'status':'NOTINST' + }, + 'TPS53681(0x6E)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 5, + 'driver':'tps53679', + 'i2caddr': '0x6e', + 'path': ' ', + 'status':'NOTINST' + }, + 'TPS53681(0x70)': { + 'parent':'PCA9548_0x75', + 'parent_ch': 5, + 'driver':'tps53679', + 'i2caddr': '0x70', + 'path': ' ', + 'status':'NOTINST' + } +} + +SFP_GROUPS = { + 'SFP-G01' :{ + 'number': 8, + 'parent':'PCA9548_0x71_1', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G02' :{ + 'number': 8, + 'parent':'PCA9548_0x71_2', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G03' :{ + 'number': 8, + 'parent':'PCA9548_0x71_3', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + }, + 'SFP-G04' :{ + 'number': 8, + 'parent':'PCA9548_0x71_4', + 'channels':[0,1,2,3,4,5,6,7], + 'driver':'optoe1', + 'i2caddr': '0x50', + 'paths': [], + 'status':'NOTINST' + } +} + + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv) < 2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + devices_info() + elif arg == 'version': + show_version() + else: + show_help() + + return 0 + +def show_version(): + print("platform driver version: {}\n".format(PLATFORM_DRIVER_VER)) + +def show_help(): + print __doc__ % {'scriptName': sys.argv[0].split("/")[-1]} + sys.exit(0) + +def log_os_system(cmd, show): + logging.info('Run :' + cmd) + status, output = commands.getstatusoutput(cmd) + logging.info(cmd + "with result:" + str(status)) + logging.info(" output:" + output) + if status: + logging.info('Failed :' + cmd) + if show: + print('Failed ({}):'.format(status) + cmd) + return status, output + + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep cameo", 0) + logging.info('mods:' + lsmod) + if len(lsmod) == 0: + return False + return True + + +kos = [ + 'depmod -a', + 'modprobe i2c_dev', + 'modprobe x86-64-cameo-escc601-32q', + 'modprobe i2c_mux_pca954x force_deselect_on_exit=1', + 'modprobe nct7511', + 'modprobe at24_smbus', + 'modprobe at24', + 'modprobe zrh2800k2', + 'modprobe tps53679' +] + + +def driver_install(): + global FORCE + for i in range(0, len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + + +def driver_uninstall(): + global FORCE + for i in range(0, len(kos)): + rm = kos[-(i + 1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + rm = rm.replace("force_deselect_on_exit=1", " ") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def check_base_bus(): + global I2C_SWITCH_LIST + global I2C_DEVICES + global SFP_GROUPS + global BASE_BUS + # we start check with the first i2c switch to install which on base bus + switch = I2C_SWITCH_LIST[switch_install_order[0]] + for bbus in I2C_BASE_BUS.keys(): + install_path = I2C_BASE_BUS[bbus]['path'] + cmd = "echo {} {} > {}/new_device".format(switch['driver'], switch['i2caddr'], install_path) + log_os_system(cmd, 1) + time.sleep(1) + cmd = "ls /sys/bus/i2c/devices/{}-00{}/channel-0".format(bbus[-1],switch['i2caddr'][-2:]) + result = log_os_system(cmd, 1)[0] + #uninstall + cmd = "echo {} > {}/delete_device".format(switch['i2caddr'], install_path) + log_os_system(cmd, 1) + if result == 0: + BASE_BUS = bbus + break + + logging.info('Base bus is {}'.format(BASE_BUS)) + + #exchange all base bus + for dev_name in I2C_SWITCH_LIST.keys(): + if I2C_SWITCH_LIST[dev_name]['parent'] == 'base': + I2C_SWITCH_LIST[dev_name]['parent'] = BASE_BUS + for dev_name in I2C_DEVICES.keys(): + if I2C_DEVICES[dev_name]['parent'] == 'base': + I2C_DEVICES[dev_name]['parent'] = BASE_BUS + for dev_name in SFP_GROUPS.keys(): + if SFP_GROUPS[dev_name]['parent'] == 'base': + SFP_GROUPS[dev_name]['parent'] = BASE_BUS + + +def get_next_bus_num(): + num_list = [] + device_list = os.listdir("/sys/bus/i2c/devices") + for x in device_list: + t = re.match(r'i2c-(\d+)', x) + if t: + num_list.append(int(t.group(1))) + logging.info('next_bus_id is {}'.format(max(num_list)+1)) + return max(num_list)+1 + +def install_i2c_switch(): + + for switch_name in switch_install_order: + next_bus_id = get_next_bus_num() + switch = I2C_SWITCH_LIST[switch_name] + if switch['parent'] in I2C_BASE_BUS: + install_path = I2C_BASE_BUS[switch['parent']]['path'] + else: + install_path = I2C_SWITCH_LIST[switch['parent']]['path'] + + if 'parent_ch' in switch: + install_path = install_path+"/channel-{}".format(switch['parent_ch']) + if I2C_SWITCH_LIST[switch['parent']]['status'] != 'INSTALLED': + continue + + cmd = "echo {} {} > {}/new_device".format(switch['driver'], switch['i2caddr'], install_path) + status, output = log_os_system(cmd, 1) + if status != 0: + switch['status'] = 'FAILED' + continue + + if switch['parent'] in I2C_BASE_BUS: + switch['path'] = "/sys/bus/i2c/devices/{}-00{}".format(switch['parent'][-1],switch['i2caddr'][-2:]) + else: + switch['path'] = "/sys/bus/i2c/devices/{}-00{}".format(I2C_SWITCH_LIST[switch['parent']]['bus_map'][switch['parent_ch']],switch['i2caddr'][-2:]) + + # add delay to make sure the root switch for sfp is installed completely, + # so we can start the installation of next switch + if switch_name == 'PCA9548_0x73': + time.sleep(1) + + #Check if bus are actually created + for busid in range(next_bus_id,next_bus_id+8): + if not os.path.exists("/sys/bus/i2c/devices/i2c-{}".format(busid)): + print("Fail to create bus when install {}".format(switch_name)) + switch['status'] = 'FAILED' + break + else: + # exit loop normally; not breakout + switch['bus_map'] = list(range(next_bus_id,next_bus_id+8)) + switch['status'] = 'INSTALLED' + +def remove_install_status(): + if os.path.exists(PLATFORM_INSTALL_INFO_FILE): + os.remove(PLATFORM_INSTALL_INFO_FILE) + +def restore_install_status(): + output = [] + output.append(I2C_SWITCH_LIST) + output.append(I2C_DEVICES) + output.append(SFP_GROUPS) + jsondata = json.dumps(output) + with open(PLATFORM_INSTALL_INFO_FILE,'w') as fd: + fd.write(jsondata) + +def update_hwmon(): + for dev_name in I2C_DEVICES.keys(): + dev = I2C_DEVICES[dev_name] + if dev['status'] == 'INSTALLED': + if os.path.exists(dev['path']+'/hwmon'): + dev['hwmon_path'] = os.path.join(dev['path']+'/hwmon', os.listdir(dev['path']+'/hwmon')[0]) + + +def install_i2c_device(): + for dev_name in I2C_DEVICES.keys(): + dev = I2C_DEVICES[dev_name] + if dev['parent'] in I2C_BASE_BUS: + install_path = I2C_BASE_BUS[dev['parent']]['path'] + else: + install_path = I2C_SWITCH_LIST[dev['parent']]['path'] + + if 'parent_ch' in dev: + install_path = install_path+"/channel-{}".format(dev['parent_ch']) + if I2C_SWITCH_LIST[dev['parent']]['status'] != 'INSTALLED': + continue + + cmd = "echo {} {} > {}/new_device".format(dev['driver'], dev['i2caddr'], install_path) + status, output = log_os_system(cmd, 1) + if status != 0: + dev['status'] = 'FAILED' + continue + + if dev['parent'] in I2C_BASE_BUS: + dev['path'] = "/sys/bus/i2c/devices/{}-00{}".format(dev['parent'][-1],dev['i2caddr'][-2:]) + else: + dev['path'] = "/sys/bus/i2c/devices/{}-00{}".format(I2C_SWITCH_LIST[dev['parent']]['bus_map'][dev['parent_ch']],dev['i2caddr'][-2:]) + + dev['status'] = 'INSTALLED' + + +def install_sfp(): + for sfp_group_name in SFP_GROUPS.keys(): + sfp_group = SFP_GROUPS[sfp_group_name] + if sfp_group['parent'] in I2C_BASE_BUS: + install_path = I2C_BASE_BUS[sfp_group['parent']]['path'] + else: + install_path = I2C_SWITCH_LIST[sfp_group['parent']]['path'] + + # parent switch is not installed, skip this sfp group + if I2C_SWITCH_LIST[sfp_group['parent']]['status'] != 'INSTALLED': + sfp_group['paths'] = ['n/a']*sfp_group['number'] + continue + + for n in range(0,sfp_group['number']): + sfp_install_path = install_path+"/channel-{}".format(sfp_group['channels'][n]) + cmd = "echo {} {} > {}/new_device".format(sfp_group['driver'], sfp_group['i2caddr'], sfp_install_path) + status, output = log_os_system(cmd, 1) + if status != 0: + sfp_group['status'] = 'FAILED' + sfp_group['paths'].append("n/a") + continue + + if sfp_group['parent'] in I2C_BASE_BUS: + sfp_group['paths'].append("/sys/bus/i2c/devices/{}-00{}".format(sfp_group['parent'][-1],sfp_group['i2caddr'][-2:])) + else: + sfp_group['paths'].append("/sys/bus/i2c/devices/{}-00{}".format(I2C_SWITCH_LIST[sfp_group['parent']]['bus_map'][sfp_group['channels'][n]],sfp_group['i2caddr'][-2:])) + + # if all sfps in a group are success + if len(sfp_group['paths']) == sfp_group['number']: + sfp_group['status'] = "INSTALLED" + +def uninstall_sfp(): + for sfp_group_name in SFP_GROUPS.keys(): + sfp_group = SFP_GROUPS[sfp_group_name] + if sfp_group['parent'] in I2C_BASE_BUS: + uninst_path = I2C_BASE_BUS[sfp_group['parent']]['path'] + else: + uninst_path = I2C_SWITCH_LIST[sfp_group['parent']]['path'] + + # sfp is not installed, skip this sfp group + if sfp_group['status'] != 'INSTALLED': + continue + + for n in range(0,sfp_group['number']): + sfp_uninst_path = uninst_path+"/channel-{}".format(sfp_group['channels'][n]) + cmd = "echo {} > {}/delete_device".format(sfp_group['i2caddr'], sfp_uninst_path) + log_os_system(cmd, 1) + +def uninstall_i2c_device(): + for dev_name in I2C_DEVICES.keys(): + dev = I2C_DEVICES[dev_name] + if dev['parent'] in I2C_BASE_BUS: + uninst_path = I2C_BASE_BUS[dev['parent']]['path'] + else: + uninst_path = I2C_SWITCH_LIST[dev['parent']]['path'] + + # device is not installed, skip this device + if dev['status'] != 'INSTALLED': + continue + + if 'parent_ch' in dev: + uninst_path = uninst_path+"/channel-{}".format(dev['parent_ch']) + + cmd = "echo {} > {}/delete_device".format(dev['i2caddr'], uninst_path) + log_os_system(cmd, 1) + +def uninstall_i2c_switch(): + for switch_name in reversed(switch_install_order): + switch = I2C_SWITCH_LIST[switch_name] + if switch['parent'] in I2C_BASE_BUS: + uninst_path = I2C_BASE_BUS[switch['parent']]['path'] + else: + uninst_path = I2C_SWITCH_LIST[switch['parent']]['path'] + + # switch is not installed, skip this switch + if switch['status'] != 'INSTALLED': + continue + + if 'parent_ch' in switch: + uninst_path = uninst_path+"/channel-{}".format(switch['parent_ch']) + + cmd = "echo {} > {}/delete_device".format(switch['i2caddr'], uninst_path) + log_os_system(cmd, 1) + +def hw_adjustment(): + global SFP_GROUPS + global I2C_DEVICES + global switch_install_order + if bmc_is_exist(): + switch_install_order.remove('PCA9548_0x75') + for device_name in I2C_DEVICES.keys(): + device = I2C_DEVICES[device_name] + if device['parent'] == 'PCA9548_0x75': + device['status'] = 'viaBMC' + + +def set_led_control(): + cmd = "echo 1 > /sys/class/hwmon/hwmon2/device/ESCC601_LED/led_fiber" + status, output = log_os_system(cmd, 1) + if status: + print output + +def device_install(): + remove_install_status() + hw_adjustment() + check_base_bus() + set_led_control() + install_i2c_switch() + # add delay to make sure all switch is installed completely, + # so we can start install other slave device safely. + time.sleep(1) + install_i2c_device() + install_sfp() + update_hwmon() + restore_install_status() + return 0 + +def device_uninstall(): + global SFP_GROUPS + global I2C_DEVICES + global I2C_SWITCH_LIST + try: + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + SFP_GROUPS = install_info[2] + I2C_DEVICES = install_info[1] + I2C_SWITCH_LIST = install_info[0] + uninstall_sfp() + uninstall_i2c_device() + uninstall_i2c_switch() + remove_install_status() + return 0 + except IOError as e: + print(e) + print("Platform install information file is not exist, please do install first") + return 1 + +i2c_prefix = '/sys/bus/i2c/devices/' + +def get_attr_value(attr_path): + retval = 'ERR' + if not os.path.isfile(attr_path): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + fd.close() + return retval + +def bmc_is_exist(): + value = '' + bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESCC601_SYS/bmc_present' + if os.path.exists(bmc_filePath): + value = get_attr_value(bmc_filePath) + if int(value) == 1: + return True + else: + return False + else: + return False + + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper() + " drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper() + " devices detected...." + return + + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() + " has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + + if FORCE == 0: + return status + + if driver_check() == False: + print PROJECT_NAME.upper() + " has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + bus_list = [] + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for i in range(0,2): + for device_name in install_info[i].keys(): + device = install_info[i][device_name] + print("{} :".format(device_name)) + if device['parent'] in I2C_BASE_BUS: + print(" On Bus: {}".format(device['parent'])) + else: + print(" On Bus: i2c-{}".format(install_info[0][device['parent']]['bus_map'][device['parent_ch']])) + print(" i2c Address: {}".format(device['i2caddr'])) + print(" status: {}".format(device['status'])) + if device['status'] == 'INSTALLED': + print(" install path: {}".format(device['path'])) + if device.get('hwmon_path'): + print(" hwmon_path: {}".format(device['hwmon_path'])) + print(' ') + + for sfp_group_name in install_info[2].keys(): + bus_list = [] + sfp_group = install_info[2][sfp_group_name] + print("{} :".format(sfp_group_name)) + print(" sfp number: {}".format(sfp_group['number'])) + for n in range(0,sfp_group['number']): + bus_list.append("i2c-{}".format(install_info[0][sfp_group['parent']]['bus_map'][sfp_group['channels'][n]])) + print(" On Bus: {}".format(bus_list)) + print(" status: {}".format(sfp_group['status'])) + print(" install path: {}".format(', '.join(sfp_group['paths']))) + print(' ') + +def device_exist(): + ret1, log = log_os_system("ls " + i2c_prefix + "*0056", 0) + return not ret1 + + +if __name__ == "__main__": + main() diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_platform.sh b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_platform.sh new file mode 100755 index 0000000000..d4414dee45 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_platform.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Install escc601-32q python package +DEVICE="/usr/share/sonic/device" +PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + +if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl ]; then + pip install $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl +fi + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_sensors.py b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_sensors.py new file mode 100755 index 0000000000..43a50622ae --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_sensors.py @@ -0,0 +1,318 @@ +#!/usr/bin/python + +from __future__ import print_function +from tabulate import tabulate +import os +import sys +import logging +import json + +MAX_FAN_NUM = 5 +MAX_PSU_NUM = 2 +PSU_LIST = ['PSU1','PSU2'] #0x58, 0x59 + +THERMAL_SENSOR_LIST = ['NCT7511Y(U73)', 'G781(U94)', 'G781(U34)', 'G781(U4)'] + +PLATFORM_INSTALL_INFO_FILE = '/etc/sonic/platform_install.json' +BMC_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESCC601_SYS/' +FAN_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESCC601_FAN/' +POWER_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESCC601_POWER/' +THERMAL_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESCC601_THERMAL/' + +def get_psu_path(): + """ + get psu path when without BMC control + """ + psu_path = [] + try: + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for psu_name in PSU_LIST: + psu = install_info[1][psu_name] + psu_path.append(psu['path']+'/') + return psu_path + except Exception: + print("Fail to get psu sysfsfile path") + + return psu_path + +def get_thermal_sensor_path(): + sensor_path = [] + try: + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + for sensor_name in THERMAL_SENSOR_LIST: + sensor = install_info[1][sensor_name] + sensor_path.append(sensor['hwmon_path']+'/') + return sensor_path + except Exception: + print("Fail to get sensor sysfsfile path") + + return sensor_path + +# Get sysfs attribute +def get_attr_value(attr_path): + retval = 'ERR' + if not os.path.isfile(attr_path): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + fd.close() + return retval + +def bmc_is_exist(): + value = '' + bmc_filePath = BMC_SYSFILE_PATH+'bmc_present' + if os.path.exists(bmc_filePath): + value = get_attr_value(bmc_filePath) + if int(value) == 1: + return True + else: + return False + else: + return False + +def print_attr_value_lines(sys_path): + retval = 'ERR' + if not os.path.isfile(sys_path): + return retval + try: + fo = open(sys_path, "r") + except Exception as error: + logging.error("Unable to open ", sys_path, " file !") + for line in fo.readlines(): + line = line.strip() + print (" %s" % line) + fo.close() + return retval + +def show_sensor_table(): + + headers = ['Sensor', 'Temperature', 'High', 'Low', 'Critical High', 'Critical Low'] + table = list() + temp = list() + + if bmc_is_exist(): + sensor_table = [ + ['Right Bottom Front' , 'temp_r_b_f', 'temp_r_b_f_max', 'temp_r_b_f_min', 'temp_r_b_f_crit', 'temp_r_b_f_lcrit'], + ['Right Bottom Back' , 'temp_r_b_b', 'temp_r_b_b_max', 'temp_r_b_b_min', 'temp_r_b_b_crit', 'temp_r_b_b_lcrit'], + ['Left Bottom Front' , 'temp_l_b_f', 'temp_l_b_f_max', 'temp_l_b_f_min', 'temp_l_b_f_crit', 'temp_l_b_f_lcrit'], + ['Left Bottom Back' , 'temp_l_b_b', 'temp_l_b_b_max', 'temp_l_b_b_min', 'temp_l_b_b_crit', 'temp_l_b_b_lcrit'], + ['Right Top Front' , 'temp_r_t_f', 'temp_r_t_f_max', 'temp_r_t_f_min', 'temp_r_t_f_crit', 'temp_r_t_f_lcrit'], + ['Right Top Back Sensor', 'temp_r_t_b', 'temp_r_t_b_max', 'temp_r_t_b_min', 'temp_r_t_b_crit', 'temp_r_t_b_lcrit'], + ['Left Top Front Sensor', 'temp_l_t_f', 'temp_l_t_f_max', 'temp_l_t_f_min', 'temp_l_t_f_crit', 'temp_l_t_f_lcrit'], + ['Left Top Back Sensor' , 'temp_l_t_b', 'temp_l_t_b_max', 'temp_l_t_b_min', 'temp_l_t_b_crit', 'temp_l_t_b_lcrit'], + ] + else: + sensor_path = get_thermal_sensor_path() + sensor_table = [ + ['Right Bottom Front' , sensor_path[0]+'temp1_input', sensor_path[0]+'temp1_max', sensor_path[0]+'temp1_min', sensor_path[0]+'temp1_crit', sensor_path[0]+'temp1_lcrit'], + ['Right Bottom Back' , sensor_path[0]+'temp2_input', sensor_path[0]+'temp2_max', sensor_path[0]+'temp2_min', sensor_path[0]+'temp2_crit', sensor_path[0]+'temp2_lcrit'], + ['Left Bottom Front' , sensor_path[1]+'temp1_input', sensor_path[1]+'temp1_max', sensor_path[1]+'temp1_min', sensor_path[1]+'temp1_crit', sensor_path[1]+'temp1_lcrit'], + ['Left Bottom Back' , sensor_path[1]+'temp2_input', sensor_path[1]+'temp2_max', sensor_path[1]+'temp2_min', sensor_path[1]+'temp2_crit', sensor_path[1]+'temp2_lcrit'], + ['Right Top Front' , sensor_path[2]+'temp1_input', sensor_path[2]+'temp1_max', sensor_path[2]+'temp1_min', sensor_path[2]+'temp1_crit', sensor_path[2]+'temp1_lcrit'], + ['Right Top Back Sensor', sensor_path[2]+'temp2_input', sensor_path[2]+'temp2_max', sensor_path[2]+'temp2_min', sensor_path[2]+'temp2_crit', sensor_path[2]+'temp2_lcrit'], + ['Left Top Front Sensor', sensor_path[3]+'temp1_input', sensor_path[3]+'temp1_max', sensor_path[3]+'temp1_min', sensor_path[3]+'temp1_crit', sensor_path[3]+'temp1_lcrit'], + ['Left Top Back Sensor' , sensor_path[3]+'temp2_input', sensor_path[3]+'temp2_max', sensor_path[3]+'temp2_min', sensor_path[3]+'temp2_crit', sensor_path[3]+'temp2_lcrit'], + ] + + for index in range(len(sensor_table)): + name = sensor_table[index][0] + for x in range(0, 5): + if bmc_is_exist(): + sys_path = THERMAL_SYSFILE_PATH + sensor_table[index][x+1] + else: + sys_path = sensor_table[index][x+1] + t = get_attr_value(sys_path) + if t == 'ERR': + temp.append('N/A') + else: + if t.isdigit(): + t = int(t)/1000.0 + temp.append('{} C'.format(t)) + + table.append([name, temp[0], temp[1], temp[2], temp[3], temp[4]]) + del temp[:] + + print(tabulate(table, headers, tablefmt='simple', stralign='right')) + print('') + +def show_fan_table(): + headers = ['Fan', 'Speed', 'Presence', 'Status', 'Power'] + table = [] + for index in range(1, MAX_FAN_NUM+1): + name_front = "FAN{}-Front".format(index) + name_rear = "FAN{}-Rear".format(index) + speed_front, speed_rear = fan_speed_dual(index) + present = fan_present(index) + status = fan_status(index) + power = fan_power(index) + table.append( [name_front, speed_front, present, status, power] ) + table.append( [name_rear , speed_front, present, status, power] ) + + print(tabulate(table, headers, tablefmt='simple', stralign='right')) + print('') + +def fan_status(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_stat'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'OK' + elif ret == '0': + return 'NG' + else: + return 'N/A' + +def fan_present(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_present'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'Present' + elif ret == '0': + return 'Not Present' + else: + return 'N/A' + +def fan_power(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_power'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'On' + elif ret == '0': + return 'Off' + else: + return 'N/A' + +def fan_speed_dual(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_front_rpm'.format(index) + front_ret = get_attr_value(sys_path) + if front_ret == 'ERR': + front_ret = 'N/A' + else: + front_ret = front_ret+'RPM' + + sys_path = FAN_SYSFILE_PATH + 'fan{}_rear_rpm'.format(index) + rear_ret = get_attr_value(sys_path) + if rear_ret == 'ERR': + rear_ret = 'N/A' + else: + rear_ret = rear_ret+'RPM' + + return (front_ret, rear_ret) + +def is_psu_present(psu_number): + sys_path = POWER_SYSFILE_PATH + 'psu{}_prnt'.format(psu_number) + if os.path.exists(sys_path): + value = get_attr_value(sys_path) + if value == '1': + return True + else: + return False + + return False + +def is_psu_power_up(psu_number): + sys_path = POWER_SYSFILE_PATH + 'psu{}_good'.format(psu_number) + if os.path.exists(sys_path): + value = get_attr_value(sys_path) + if value == '1': + return True + else: + return False + + return False + +def show_psu_table(): + headers = ['PSU', 'Presence', 'Power', 'Fan Speed(RPM)', 'Temperature(C)', 'Vin(V)', 'Vout(V)', 'Pin(W)', 'Pout(W)', 'Iin(A)', 'Iout(A)', 'Max Iout(A)'] + table = [] + psu_sysfiles_list = [] + isbmc = bmc_is_exist() + if isbmc is False: + PSU_PATH = get_psu_path() + + for index in range(0, MAX_PSU_NUM): + if isbmc: + psu_sysfiles_list = [ + POWER_SYSFILE_PATH+'psu{}_fan_speed'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_temp'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_vin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_vout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_pin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_pout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_iin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_iout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_mfr_iout_max'.format(index+1) + ] + else: + psu_sysfiles_list = [ + PSU_PATH[index]+'psu_fan_speed_1', + PSU_PATH[index]+'psu_temp_1', + PSU_PATH[index]+'psu_vin', + PSU_PATH[index]+'psu_vout', + PSU_PATH[index]+'psu_pin', + PSU_PATH[index]+'psu_pout', + PSU_PATH[index]+'psu_iin', + PSU_PATH[index]+'psu_iout', + PSU_PATH[index]+'psu_iout_max' + ] + status_list = get_psu_status(index+1, psu_sysfiles_list) + table.append(status_list) + + print(tabulate(table, headers, tablefmt='simple', stralign='right')) + print('') + +def get_psu_status(index, sysfile_list): + # result_list: [name, presence, power, fanSpeed(RPM), temperature(C), vin(V), vout(V), pin(W), pout(W), iin(A), iout(A), maxIout(A)] + name = 'PSU{}'.format(index) + result_list = [name, 'Not Present', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A'] + result_mutipler = [None, None, None, None, 1000.0, 1000.0, 1000.0, 1000000.0, 1000000.0, 1000.0, 1000.0, 1000.0] + + if is_psu_present(index): + result_list[1] = 'Present' + else: + return result_list + + if is_psu_power_up(index): + result_list[2] = 'up' + else: + result_list[2] = 'down' + + for x in range(0, 9): + result_list[x+3] = get_attr_value(sysfile_list[x]) + + for x in range(0, 12): + if result_mutipler[x] != None and result_list[x] != 'ERR': + result_list[x] = int(result_list[x]) / result_mutipler[x] + + return result_list + + +def main(): + """ + Usage: %(scriptName)s command object + + command: + fan_status : display fans status(present/power good) + """ + + if len(sys.argv)<2: + print (main.__doc__) + + for arg in sys.argv[1:]: + if arg == 'fan_status': + show_fan_table() + elif arg == 'sensor_status': + show_sensor_table() + show_psu_table() + + else: + print (main.__doc__) + +if __name__ == "__main__": + main() diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_startup b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_startup new file mode 100755 index 0000000000..2e318d99eb --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/cameo_escc601_startup @@ -0,0 +1,17 @@ +#!/bin/bash + + +start() { + # load platform driver, native drivers + /usr/local/bin/cameo_escc601_util.py install +} + +stop() { + /usr/local/bin/cameo_escc601_util.py clean +} + + +case $1 in + start|stop) "$1" ;; +esac + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/halt b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/halt new file mode 100755 index 0000000000..4a1c177c57 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/halt @@ -0,0 +1,18 @@ +#!/bin/sh + +mr_reboot() { + + sudo rmmod x86-64-cameo-escc601-32q + sudo i2cset -y 0 0x30 0xa1 0 + +} + +if [ $# -eq 0 ] || [ $@ = "--halt" ] || [ $@ = "-f" ] || [ $@ = "--force" ]; then + sudo /sbin/halt +elif [ $@ = "-p" ] || [ $@ = "--reboot" ] || [ $@ = "--poweroff" ]; then + sync;sync + mr_reboot +else + echo "unsupported option" +fi + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/poweroff b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/poweroff new file mode 100755 index 0000000000..4227071866 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/poweroff @@ -0,0 +1,18 @@ +#!/bin/sh + +mr_reboot() { + + sudo rmmod x86-64-cameo-escc601-32q + sudo i2cset -y 0 0x30 0xa1 0 + +} + +if [ $# -eq 0 ] || [ $@ = "-p" ] || [ $@ = "--reboot" ] || [ $@ = "--poweroff" ] || [ $@ = "-f" ] || [ $@ = "--force" ]; then + sync;sync + mr_reboot +elif [ $@ = "--halt" ]; then + sudo halt +else + echo "unsupported option" +fi + diff --git a/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/shutdown b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/shutdown new file mode 100755 index 0000000000..36e3eafbcc --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/escc601-32q/utils/shutdown @@ -0,0 +1,18 @@ +#!/bin/sh + +mr_reboot() { + + sudo rmmod x86-64-cameo-escc601-32q + sudo i2cset -y 0 0x31 0xa1 0 + +} + +if [ $# -eq 0 ] || [ $@ = "-r" ] || [ $@ = "--reboot" ] || [ $@ = "-h" ] || [ $@ = "-P" ] || [ $@ = "--poweroff" ]; then + sync;sync + mr_reboot +elif [ $@ = "-H" ] || [ $@ = "--halt" ]; then + sudo halt +else + echo "unsupported option" +fi + diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/Makefile b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/Makefile index 4f51487255..b4c9c37576 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/Makefile +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/Makefile @@ -1 +1,5 @@ -obj-m := x86-64-cameo-esqc610-56sq.o nct7511.o zrh2800k2.o at24_smbus.o +obj-m := nct7511.o zrh2800k2.o at24_smbus.o +obj-m += x86-64-cameo-esqc610-56sq.o +x86-64-cameo-esqc610-56sq-objs := x86-64-cameo-esqc610-56sq-common.o x86-64-cameo-esqc610-56sq-sys.o \ +x86-64-cameo-esqc610-56sq-led.o x86-64-cameo-esqc610-56sq-fan.o x86-64-cameo-esqc610-56sq-power.o \ +x86-64-cameo-esqc610-56sq-thermal.o x86-64-cameo-esqc610-56sq-qsfp.o x86-64-cameo-esqc610-56sq-sfp.o \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/nct7511.mod.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/nct7511.mod.c deleted file mode 100644 index 01d8c4b362..0000000000 --- a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/nct7511.mod.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include - -MODULE_INFO(vermagic, VERMAGIC_STRING); - -__visible struct module __this_module -__attribute__((section(".gnu.linkonce.this_module"))) = { - .name = KBUILD_MODNAME, - .init = init_module, -#ifdef CONFIG_MODULE_UNLOAD - .exit = cleanup_module, -#endif - .arch = MODULE_ARCH_INIT, -}; - -#ifdef RETPOLINE -MODULE_INFO(retpoline, "Y"); -#endif - -static const struct modversion_info ____versions[] -__used -__attribute__((section("__versions"))) = { - { 0xd1a11d1c, __VMLINUX_SYMBOL_STR(module_layout) }, - { 0x8308dcad, __VMLINUX_SYMBOL_STR(i2c_del_driver) }, - { 0x851c3bfc, __VMLINUX_SYMBOL_STR(i2c_register_driver) }, - { 0xbba4aa3a, __VMLINUX_SYMBOL_STR(devm_hwmon_device_register_with_groups) }, - { 0x888680a0, __VMLINUX_SYMBOL_STR(__mutex_init) }, - { 0x2daa70fe, __VMLINUX_SYMBOL_STR(__devm_regmap_init_i2c) }, - { 0x32a81c89, __VMLINUX_SYMBOL_STR(devm_kmalloc) }, - { 0x5792f848, __VMLINUX_SYMBOL_STR(strlcpy) }, - { 0x14c72286, __VMLINUX_SYMBOL_STR(i2c_smbus_read_byte_data) }, - { 0xa46f2f1b, __VMLINUX_SYMBOL_STR(kstrtouint) }, - { 0x60ea2d6, __VMLINUX_SYMBOL_STR(kstrtoull) }, - { 0x783815ef, __VMLINUX_SYMBOL_STR(regmap_update_bits_base) }, - { 0x94218140, __VMLINUX_SYMBOL_STR(mutex_unlock) }, - { 0x86b8d7be, __VMLINUX_SYMBOL_STR(mutex_lock) }, - { 0x1b17e06c, __VMLINUX_SYMBOL_STR(kstrtoll) }, - { 0xaee034fd, __VMLINUX_SYMBOL_STR(regmap_write) }, - { 0x5a5a94a6, __VMLINUX_SYMBOL_STR(kstrtou8) }, - { 0x91715312, __VMLINUX_SYMBOL_STR(sprintf) }, - { 0xdb7305a1, __VMLINUX_SYMBOL_STR(__stack_chk_fail) }, - { 0x12872e73, __VMLINUX_SYMBOL_STR(regmap_read) }, - { 0xbdfb6dbb, __VMLINUX_SYMBOL_STR(__fentry__) }, -}; - -static const char __module_depends[] -__used -__attribute__((section(".modinfo"))) = -"depends="; - -MODULE_ALIAS("i2c:nct7511"); diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.c new file mode 100644 index 0000000000..a1e60f3766 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.c @@ -0,0 +1,376 @@ +/* An hwmon driver for Cameo ESQC610-56SQ Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x30, 0x31, 0x32, I2C_CLIENT_END }; +static int debug = 0; + + +/* i2c_client Declaration */ +struct i2c_client *Cameo_CPLD_30_client; //0x30 for SYS CPLD +struct i2c_client *Cameo_CPLD_31_client; //0x31 for Port 01-16 +struct i2c_client *Cameo_CPLD_32_client; //0x32 for Port 17-32 +struct i2c_client *Cameo_CPLD_23_client; //0x23 for Fan CPLD +struct i2c_client *Cameo_CPLD_35_client; //0x35 for Power CPLD +struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of i2c_client Declaration */ + +/* register offset define */ +#define BMC_EN_REG 0xA4 +/* end of register offset define */ + +/* common function */ +int bmc_enable(void) +{ + if ((i2c_smbus_read_byte_data(Cameo_CPLD_30_client, BMC_EN_REG) & BIT_0_MASK) == 0x01) + { + return ENABLE; + } + else + { + return DISABLE; + } +} + +int read_8bit_temp(u8 sign,u8 value) +{ + int result = 0; + if(sign) + { + //printf("read_8bit_temp UP %d\n", value & 0x80); + value = ~(value)+1; + result = value; + return result; + } + else + { + //printf("read_8bit_temp DOWN %d\n", value & 0x80); + result = value; + return result; + } +} + +/* end of common function*/ + +static int Cameo_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + struct Cameo_i2c_data *Cameo_CPLD_30_data; + struct Cameo_i2c_data *Cameo_CPLD_31_data; + struct Cameo_i2c_data *Cameo_CPLD_32_data; + struct Cameo_i2c_data *Cameo_CPLD_23_data; + struct Cameo_i2c_data *Cameo_CPLD_35_data; + struct Cameo_i2c_data *Cameo_BMC_14_data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + { + status = -EIO; + goto exit; + } + Cameo_CPLD_30_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_30_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_31_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_31_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_32_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_32_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_23_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_23_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_CPLD_35_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_CPLD_35_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + Cameo_BMC_14_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL); + if (!Cameo_BMC_14_data) + { + printk(KERN_ALERT "kzalloc fail\n"); + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(Cameo_CPLD_30_client, Cameo_CPLD_30_data); + i2c_set_clientdata(Cameo_CPLD_31_client, Cameo_CPLD_31_data); + i2c_set_clientdata(Cameo_CPLD_32_client, Cameo_CPLD_32_data); + i2c_set_clientdata(Cameo_CPLD_23_client, Cameo_CPLD_23_data); + i2c_set_clientdata(Cameo_CPLD_35_client, Cameo_CPLD_35_data); + i2c_set_clientdata(Cameo_BMC_14_client , Cameo_BMC_14_data); + + mutex_init(&Cameo_CPLD_30_data->update_lock); + mutex_init(&Cameo_CPLD_31_data->update_lock); + mutex_init(&Cameo_CPLD_32_data->update_lock); + mutex_init(&Cameo_CPLD_23_data->update_lock); + mutex_init(&Cameo_CPLD_35_data->update_lock); + mutex_init(&Cameo_BMC_14_data->update_lock); + + Cameo_CPLD_30_data->valid = 0; + mutex_init(&Cameo_CPLD_30_data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ESQC610_SYS_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESQC610_LED_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESQC610_FAN_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESQC610_THERMAL_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESQC610_POWER_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESQC610_SFP_group); + if (status) + { + goto exit_free; + } + + status = sysfs_create_group(&client->dev.kobj, &ESQC610_QSFP_group); + if (status) + { + goto exit_free; + } + + Cameo_CPLD_30_data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(Cameo_CPLD_30_data->hwmon_dev)) + { + status = PTR_ERR(Cameo_CPLD_30_data->hwmon_dev); + goto exit_remove; + } + dev_info(&client->dev, "%s: '%s'\n", dev_name(Cameo_CPLD_30_data->hwmon_dev), client->name); + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ESQC610_SYS_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_LED_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_FAN_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_THERMAL_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_POWER_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_SFP_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_QSFP_group); + +exit_free: + kfree(Cameo_CPLD_30_data); + +exit: + return status; +} + +static int Cameo_i2c_remove(struct i2c_client *client) +{ + struct Cameo_i2c_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ESQC610_SYS_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_LED_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_FAN_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_THERMAL_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_POWER_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_SFP_group); + sysfs_remove_group(&client->dev.kobj, &ESQC610_QSFP_group); + + kfree(data); + return 0; +} + +static const struct i2c_device_id Cameo_i2c_id[] = +{ + { "Cameo_CPLD_30", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, Cameo_i2c_id); + +static struct i2c_driver Cameo_i2c_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = + { + .name = "ESQC_610_i2c", + }, + .probe = Cameo_i2c_probe, + .remove = Cameo_i2c_remove, + .id_table = Cameo_i2c_id, + .address_list = normal_i2c, +}; + +/*For main Switch board*/ +static struct i2c_board_info Cameo_CPLD_30_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_30", 0x30), + .platform_data = NULL, + }, +}; + +/*For QSFP Port 01 - 16*/ +static struct i2c_board_info Cameo_CPLD_31_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_31", 0x31), + .platform_data = NULL, + }, +}; +/*For QSFP Port 17 - 32*/ +static struct i2c_board_info Cameo_CPLD_32_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_32", 0x32), + .platform_data = NULL, + }, +}; +/*For Fan status*/ +static struct i2c_board_info Cameo_CPLD_23_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_23", 0x23), + .platform_data = NULL, + }, +}; +/*For Power status*/ +static struct i2c_board_info Cameo_CPLD_35_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_CPLD_35", 0x35), + .platform_data = NULL, + }, +}; +/*For BMC Slave*/ +static struct i2c_board_info Cameo_BMC_14_info[] __initdata = +{ + { + I2C_BOARD_INFO("Cameo_BMC_14", 0x14), + .platform_data = NULL, + }, +}; + +static int __init Cameo_i2c_init(void) +{ + int ret; + int cmp; + char keyword[] = "SMBus I801"; + char buf1[128]; + struct i2c_adapter *i2c_adap; + struct file *fp; + mm_segment_t fs; + loff_t pos; + + printk("Open file...\n"); + fp = filp_open("/sys/class/i2c-dev/i2c-0/name", O_RDONLY , 0644); + if (IS_ERR(fp)) { + printk("Open file FAILED\n"); + return -1; + } + + fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_read(fp, buf1, sizeof(buf1), &pos); + printk("Detect %s\n", buf1); + cmp = strncmp(keyword, buf1, sizeof(keyword)-1); + set_fs(fs); + + filp_close(fp, NULL); + + if(cmp == 0) + { + i2c_adap = i2c_get_adapter(0); + printk("SMBus I801 is at bus 0\n"); + } + else + { + i2c_adap = i2c_get_adapter(1); + printk("SMBus I801 is at bus 1\n"); + } + + if (i2c_adap == NULL) + { + printk("ERROR: i2c_get_adapter FAILED!\n"); + return -1; + } + Cameo_CPLD_30_client = i2c_new_device(i2c_adap, &Cameo_CPLD_30_info[0]); + Cameo_CPLD_31_client = i2c_new_device(i2c_adap, &Cameo_CPLD_31_info[0]); + Cameo_CPLD_32_client = i2c_new_device(i2c_adap, &Cameo_CPLD_32_info[0]); + Cameo_CPLD_23_client = i2c_new_device(i2c_adap, &Cameo_CPLD_23_info[0]); + Cameo_CPLD_35_client = i2c_new_device(i2c_adap, &Cameo_CPLD_35_info[0]); + Cameo_BMC_14_client = i2c_new_device(i2c_adap, &Cameo_BMC_14_info[0]); + + if (Cameo_CPLD_30_info == NULL || Cameo_CPLD_31_info == NULL || Cameo_CPLD_32_info == NULL + || Cameo_CPLD_23_info == NULL || Cameo_CPLD_35_info == NULL || Cameo_BMC_14_info == NULL) + { + printk("ERROR: i2c_new_device FAILED!\n"); + return -1; + } + + i2c_put_adapter(i2c_adap); + ret = i2c_add_driver(&Cameo_i2c_driver); + printk(KERN_ALERT "ESQC610-56SQ i2c Driver Version: %s\n", DRIVER_VERSION); + printk(KERN_ALERT "ESQC610-56SQ i2c Driver INSTALL SUCCESS\n"); + return ret; +} + +static void __exit Cameo_i2c_exit(void) +{ + i2c_unregister_device(Cameo_CPLD_30_client); + i2c_unregister_device(Cameo_CPLD_31_client); + i2c_unregister_device(Cameo_CPLD_32_client); + i2c_unregister_device(Cameo_CPLD_23_client); + i2c_unregister_device(Cameo_CPLD_35_client); + i2c_unregister_device(Cameo_BMC_14_client); + i2c_del_driver(&Cameo_i2c_driver); + printk(KERN_ALERT "ESQC610-56SQ i2c Driver UNINSTALL SUCCESS\n"); +} + +MODULE_AUTHOR("Cameo Inc."); +MODULE_DESCRIPTION("Cameo ESQC610-56SQ i2c Driver"); +MODULE_LICENSE("GPL"); +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Enable debugging (0-1)"); + +module_init(Cameo_i2c_init); +module_exit(Cameo_i2c_exit); diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.h new file mode 100644 index 0000000000..39e5ab15e9 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-common.h @@ -0,0 +1,25 @@ +/* register offset define */ +#define ENABLE 1 +#define DISABLE 0 + +#define PASSED 1 +#define FAILED 0 + +#define TRUE 1 +#define FALSE 0 + +#define ABNORMAL 1 +#define NORMAL 0 + +#define BIT_0_MASK 0x01 +#define BIT_1_MASK 0x02 +#define BIT_2_MASK 0x04 +#define BIT_3_MASK 0x08 +#define BIT_4_MASK 0x10 +#define BIT_5_MASK 0x20 +#define BIT_6_MASK 0x40 +#define BIT_7_MASK 0x80 +/* end of register offset define */ + +int bmc_enable(void); +int read_8bit_temp(u8 sign,u8 value); \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.c new file mode 100644 index 0000000000..49c5ce614e --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.c @@ -0,0 +1,339 @@ +/* An hwmon driver for Cameo esqc610-56sq Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" +#include "x86-64-cameo-esqc610-56sq-fan.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_23_client; //0x23 for Fan CPLD +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t fan_ctrl_mode_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_BMC_14_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == FANCTRL_MODE) + { + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, FANCTRL_MODE_REG); + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s0x%x\n", buf, status); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t fan_ctrl_rpm_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_BMC_14_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == FANCTRL_RPM) + { + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, FANCTRL_RPM_REG); + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s0x%x\n", buf, status); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_23_data = i2c_get_clientdata(Cameo_CPLD_23_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_23_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, FAN_STAT_REG); + mutex_unlock(&Cameo_CPLD_23_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_23_data = i2c_get_clientdata(Cameo_CPLD_23_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_PRESENT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_23_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, FAN_PRESENT_REG); + mutex_unlock(&Cameo_CPLD_23_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_23_data = i2c_get_clientdata(Cameo_CPLD_23_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_FAN_POWER_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_23_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, FAN_POWER_REG); + mutex_unlock(&Cameo_CPLD_23_data->update_lock); + } + + result = FAILED; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = PASSED; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = PASSED; + } + break; + case 3: + if(status & BIT_2_MASK) + { + result = PASSED; + } + break; + case 4: + if(status & BIT_3_MASK) + { + result = PASSED; + } + break; + } + if(result != PASSED) + { + return sprintf(buf, "%s%d\n", buf, FAILED); + } + return sprintf(buf, "%s%d\n", buf, PASSED); +} + +ssize_t fan_rpm_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int fan_location = 0; + int fan_offset = 0; + u16 fan_speed = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *target_client = NULL; + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + target_client = Cameo_BMC_14_client; + } + else + { + target_client = Cameo_CPLD_23_client; + } + + switch (attr->index) + { + case FAN1_FRONT_RPM: + fan_location = 0; + fan_offset = 0; + break; + case FAN2_FRONT_RPM: + fan_location = 0; + fan_offset = 1; + break; + case FAN3_FRONT_RPM: + fan_location = 0; + fan_offset = 2; + break; + case FAN4_FRONT_RPM: + fan_location = 0; + fan_offset = 3; + break; + case FAN1_REAR_RPM: + fan_location = 1; + fan_offset = 0; + break; + case FAN2_REAR_RPM: + fan_location = 1; + fan_offset = 1; + break; + case FAN3_REAR_RPM: + fan_location = 1; + fan_offset = 2; + break; + case FAN4_REAR_RPM: + fan_location = 1; + fan_offset = 3; + break; + } + if(fan_location == 0) + { + // front fan of couple + // read high byte + status = i2c_smbus_read_byte_data(target_client, FAN_F_RPM_REG+(fan_offset*2)+1); + fan_speed = status; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + // read low byte + status = i2c_smbus_read_byte_data(target_client, FAN_F_RPM_REG+(fan_offset*2)); + fan_speed = ((fan_speed<<8) + status)*30; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + } + else + { + // rear fan of couple + // read high byte + status = i2c_smbus_read_byte_data(target_client, FAN_R_RPM_REG+(fan_offset*2)+1); + fan_speed = status; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + // read low byte + status = i2c_smbus_read_byte_data(target_client, FAN_R_RPM_REG+(fan_offset*2)); + fan_speed = ((fan_speed<<8) + status)*30; + if(status < 0 || status == 0xff) + { + fan_speed = 0; + } + } + sprintf(buf, "%s%d\n", buf, fan_speed); + return sprintf(buf, "%s\n",buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.h new file mode 100644 index 0000000000..6622c01d87 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-fan.h @@ -0,0 +1,12 @@ +/* register offset define */ +#define FANCTRL_RPM_REG 0xc4 +#define FANCTRL_MODE_REG 0xc5 +#define FAN_STAT_REG 0x00 +#define FAN_POWER_REG 0x01 +#define FAN_PRESENT_REG 0x02 +#define BMC_FAN_STAT_REG 0x80 +#define BMC_FAN_POWER_REG 0x81 +#define BMC_FAN_PRESENT_REG 0x82 +#define FAN_F_RPM_REG 0xa0 +#define FAN_R_RPM_REG 0xb0 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.c new file mode 100644 index 0000000000..b8c07d7fd1 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.c @@ -0,0 +1,220 @@ +/* An hwmon driver for Cameo esqc610-56sq Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" +#include "x86-64-cameo-esqc610-56sq-led.h" + +/* i2c_client Declaration */ +extern struct i2c_client *Cameo_CPLD_30_client; //0x30 for SYS CPLD +/* end of i2c_client Declaration */ + +/* implement i2c_function */ +ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int res = 0x1; + int i; + int led_a_status = 0; + int led_g_status = 0; + int led_b_status = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG); + sprintf(buf, ""); + + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_a_status = ENABLE; + } + else + { + led_a_status = DISABLE; + } + } + res = res << 1; + if( i == (attr->index + 1) ) + { + if (status & res) + { + led_g_status = ENABLE; + } + else + { + led_g_status = DISABLE; + } + } + res = res << 1; + } + res = 0x1; + + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_BLINK_REG); + for (i = 1; i <= 4; i++) + { + if ( i == attr->index) + { + if (status & res) + { + led_b_status = ENABLE; + } + else + { + led_b_status = DISABLE; + } + } + res = res << 1; + } + if(led_a_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s2\n", buf); + } + else if(led_a_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s1\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == ENABLE) + { + sprintf(buf, "%s4\n", buf); + } + else if(led_g_status == ENABLE && led_b_status == DISABLE) + { + sprintf(buf, "%s3\n", buf); + } + else + { + sprintf(buf, "%s0\n", buf); + } + + return sprintf(buf, "%s", buf); +} + +ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int led_value = -EPERM; + int blk_value = -EPERM; + int result = -EPERM; + int offset = 0; + u16 i; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + led_value = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG); + blk_value = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_BLINK_REG); + if (attr->index != 0) + { + i = simple_strtol(buf, NULL, 10); + if(attr->index == 1) + { + offset = 0; + } + else + { + offset = 2*((attr->index)-1); + } + switch(i) + { + case SWITCH_LED_OFF: //i=0 + led_value &= ~(0x03 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_N: //i=1 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_A_B: //i=2 + led_value &= ~(0x03 << offset); + led_value |= (0x01 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_N: //i=3 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value &= ~(1 << ((attr->index)-1)); + break; + case SWITCH_LED_G_B: //i=4 + led_value &= ~(0x03 << offset); + led_value |= (0x02 << offset); + blk_value |= (1 << ((attr->index)-1)); + break; + default: + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + return count; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG, led_value); + result |= i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_BLINK_REG, blk_value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t led_fiber_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == LED_FIBER) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_FIBER_REG) & BIT_0_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} +ssize_t led_fiber_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, LED_CTRL_REG); + if (attr->index == LED_FIBER) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | LED_FIBER_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_FIBER_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & LED_FIBER_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, LED_FIBER_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: led_ctrl_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "led_ctrl_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.h new file mode 100644 index 0000000000..c07a246447 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-led.h @@ -0,0 +1,12 @@ +/* register offset define */ +#define LED_CTRL_REG 0xa2 +#define LED_BLINK_REG 0xa3 +#define LED_FIBER_REG 0xa0 +#define LED_FIBER_ENABLE 0x01 +#define LED_FIBER_DISABLE 0xfe +#define SWITCH_LED_OFF 0 +#define SWITCH_LED_A_N 1 +#define SWITCH_LED_A_B 2 +#define SWITCH_LED_G_N 3 +#define SWITCH_LED_G_B 4 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.c new file mode 100644 index 0000000000..9eff0ab68c --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.c @@ -0,0 +1,652 @@ +/* An hwmon driver for Cameo esqc610-56sq Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" +#include "x86-64-cameo-esqc610-56sq-power.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_35_client; //0x35 for Power CPLD +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* convert function */ +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} +/* end of convert function */ + +/* implement i2c_function */ +ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_PSU_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, PSU_STAT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = TRUE; + switch (attr->index) + { + case 1: + if(status & BIT_2_MASK) + { + result = FALSE; + } + break; + case 2: + if(status & BIT_3_MASK) + { + result = FALSE; + } + break; + } + if(result != TRUE) + { + return sprintf(buf, "%s%d\n", buf, FALSE); + } + return sprintf(buf, "%s%d\n", buf, TRUE); +} +ssize_t psu_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + u32 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_35_data = i2c_get_clientdata(Cameo_CPLD_35_client); + struct Cameo_i2c_data *Cameo_BMC_14_data = i2c_get_clientdata(Cameo_BMC_14_client); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + mutex_lock(&Cameo_BMC_14_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, BMC_PSU_STAT_REG); + mutex_unlock(&Cameo_BMC_14_data->update_lock); + } + else + { + mutex_lock(&Cameo_CPLD_35_data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_35_client, PSU_STAT_REG); + mutex_unlock(&Cameo_CPLD_35_data->update_lock); + } + + result = FALSE; + switch (attr->index) + { + case 1: + if(status & BIT_0_MASK) + { + result = TRUE; + } + break; + case 2: + if(status & BIT_1_MASK) + { + result = TRUE; + } + break; + } + if(result != TRUE) + { + return sprintf(buf, "%s%d\n", buf, FALSE); + } + return sprintf(buf, "%s%d\n", buf, TRUE); +} +ssize_t psu_vin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_VIN_REG); + break; + case PSU2_VIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_VIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t psu_iin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_IIN_REG); + break; + case PSU2_IIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_IIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t psu_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0; + int multiplier = 1000; + u16 u16_vmode = 0; + u16 u16_vout = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_VOUT_REG); + break; + case PSU2_VOUT: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); + u16_vout = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_VOUT_REG); + break; + } + if(u16_vout == 0xffff || u16_vout == -1) + { + return sprintf(buf, "%s0\n", buf); + } + /* vout mode */ + multiplier = 1000; + exponent = two_complement_to_int(u16_vmode & 0x1f, 5, 0x1f); + /* vout */ + result = (exponent >= 0) ? ((u16_vout << exponent)*multiplier) : \ + (u16_vout*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_IOUT_REG); + break; + case PSU2_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_IOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_temp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_TEMP_1_REG); + break; + case PSU2_TEMP: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_TEMP_1_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_fan_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_FAN_SPEED_REG); + break; + case PSU2_FAN_SPEED: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_FAN_SPEED_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_pout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_POUT_REG); + break; + case PSU2_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_POUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_pin_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_PIN_REG); + break; + case PSU2_PIN: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_PIN_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 u16_val = 0; + char model[I2C_SMBUS_BLOCK_MAX] = {0}; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_1_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + case PSU2_MFR_MODEL: + u16_val = i2c_smbus_read_i2c_block_data(Cameo_BMC_14_client, PSU_2_MFR_MODEL_REG, I2C_SMBUS_BLOCK_MAX, model); + break; + } + if(u16_val != I2C_SMBUS_BLOCK_MAX) + { + return sprintf(buf, "%sERROR\n", buf); + } + if (model[1] < 0x20 || model[1] > 0x7f) + { + return sprintf(buf, "%sERROR\n", buf); + } + sprintf(buf, "%s%s", buf, model); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_iout_max_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_1_MFR_IOUT_MAX_REG); + break; + case PSU2_MFR_IOUT_MAX: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, PSU_2_MFR_IOUT_MAX_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; // lm-sensor unit: uW + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t psu_vmode_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u16 u16_vmode = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case PSU1_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_1_VMODE_REG); + break; + case PSU2_VMODE: + u16_vmode = i2c_smbus_read_byte_data(Cameo_BMC_14_client, PSU_2_VMODE_REG); + break; + } + if(u16_vmode == 0xffff || u16_vmode == -1) + { + return sprintf(buf, "%s0\n", buf); + } + /* vout mode */ + sprintf(buf, "%s%d\n", buf, u16_vmode); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_vout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC6E_P0_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P0_VOUT_REG); + break; + case DC6E_P1_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P1_VOUT_REG); + break; + case DC70_P0_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P0_VOUT_REG); + break; + case DC70_P1_VOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P1_VOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_iout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC6E_P0_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P0_IOUT_REG); + break; + case DC6E_P1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P1_IOUT_REG); + break; + case DC70_P0_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P0_IOUT_REG); + break; + case DC70_P1_IOUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P1_IOUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t dc_pout_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u32 result = -EPERM; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + u16 u16_val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + sprintf(buf, ""); + if( bmc_enable() == ENABLE) + { + switch(attr->index) + { + case DC6E_P0_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P0_POUT_REG); + break; + case DC6E_P1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_6E_P1_POUT_REG); + break; + case DC70_P0_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P0_POUT_REG); + break; + case DC70_P1_POUT: + u16_val = i2c_smbus_read_word_data(Cameo_BMC_14_client, DC_CHIP_70_P1_POUT_REG); + break; + } + if(u16_val == 0xffff || u16_val == -1) + { + return sprintf(buf, "%s0\n", buf); + } + exponent = two_complement_to_int(u16_val >> 11, 5, 0x1f); + mantissa = two_complement_to_int(u16_val & 0x7ff, 11, 0x7ff); + multiplier = 1000000; + result = (exponent >= 0) ? ((mantissa << exponent)*multiplier) : \ + (mantissa*multiplier / (1 << -exponent)); + sprintf(buf, "%s%d\n", buf, result); + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + return sprintf(buf, "%s\n", buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.h new file mode 100644 index 0000000000..2290699ff9 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-power.h @@ -0,0 +1,38 @@ +/* register offset define */ +#define PSU_STAT_REG 0xa0 +#define BMC_PSU_STAT_REG 0xc0 +#define PSU_1_VIN_REG 0x50 +#define PSU_1_IIN_REG 0x51 +#define PSU_1_VOUT_REG 0x52 +#define PSU_1_IOUT_REG 0x53 +#define PSU_1_TEMP_1_REG 0x54 +#define PSU_1_FAN_SPEED_REG 0x55 +#define PSU_1_POUT_REG 0x56 +#define PSU_1_PIN_REG 0x57 +#define PSU_1_MFR_MODEL_REG 0x58 +#define PSU_1_MFR_IOUT_MAX_REG 0x59 +#define PSU_1_VMODE_REG 0x5a +#define PSU_2_VIN_REG 0x60 +#define PSU_2_IIN_REG 0x61 +#define PSU_2_VOUT_REG 0x62 +#define PSU_2_IOUT_REG 0x63 +#define PSU_2_TEMP_1_REG 0x64 +#define PSU_2_FAN_SPEED_REG 0x65 +#define PSU_2_POUT_REG 0x66 +#define PSU_2_PIN_REG 0x67 +#define PSU_2_MFR_MODEL_REG 0x68 +#define PSU_2_MFR_IOUT_MAX_REG 0x69 +#define PSU_2_VMODE_REG 0x6a +#define DC_CHIP_6E_P0_VOUT_REG 0x90 +#define DC_CHIP_6E_P0_IOUT_REG 0x91 +#define DC_CHIP_6E_P0_POUT_REG 0x92 +#define DC_CHIP_6E_P1_VOUT_REG 0x94 +#define DC_CHIP_6E_P1_IOUT_REG 0x95 +#define DC_CHIP_6E_P1_POUT_REG 0x96 +#define DC_CHIP_70_P0_VOUT_REG 0x98 +#define DC_CHIP_70_P0_IOUT_REG 0x99 +#define DC_CHIP_70_P0_POUT_REG 0x9a +#define DC_CHIP_70_P1_VOUT_REG 0x9c +#define DC_CHIP_70_P1_IOUT_REG 0x9d +#define DC_CHIP_70_P1_POUT_REG 0x9e +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.c new file mode 100644 index 0000000000..94ad235ff6 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.c @@ -0,0 +1,478 @@ +/* An hwmon driver for Cameo esqc610-56sq Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" +#include "x86-64-cameo-esqc610-56sq-qsfp.h" + +/* i2c_client Declaration */ +extern struct i2c_client *Cameo_CPLD_32_client; //0x32 for Port 01-08 +/* end of i2c_client Declaration */ + +/* extern i2c_function */ +/* end of extern i2c_function */ + +/* implement i2c_function */ +ssize_t qsfp_low_power_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u8 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == QSFP_LOW_POWER_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_LOW_POWER_REG); //1-8 + result = status; + sprintf(buf, "%s0x%x\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_low_power_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int value = 0x0; + int result = 0; + int input = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + + mutex_lock(&Cameo_CPLD_32_data->update_lock); + if (attr->index == QSFP_LOW_POWER_ALL) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = 0xff; + } + else if(input == DISABLE) + { + value = 0x00; + } + else + { + printk(KERN_ALERT "qsfp_low_power_all_set wrong value\n"); + return count; + } + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, QSFP_LOW_POWER_REG, value); + + if(result != 0) + { + printk(KERN_ALERT "qsfp_low_power_all_set FAILED\n"); + return count; + } + } + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + return count; +} + +ssize_t qsfp_low_power_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 8) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_low_power_regs[port_index][0]); + } + + if (status & qsfp_low_power_regs[port_index][1]) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_low_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + port_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (port_index >= 1 && port_index <= 8) + { + target_client = Cameo_CPLD_32_client; + + } + + status = i2c_smbus_read_byte_data(target_client, qsfp_low_power_regs[port_index][0]); + if( input == ENABLE) + { + status |= qsfp_low_power_regs[port_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_low_power_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_low_power_set ON FAILED!\n"); + } + } + else if( input == DISABLE) + { + status &= ~(qsfp_low_power_regs[port_index][1]); + result = i2c_smbus_write_byte_data(target_client, qsfp_low_power_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_low_power_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_low_power_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} + +ssize_t qsfp_reset_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int value = 0x0; + int result = 0; + int input = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + + mutex_lock(&Cameo_CPLD_32_data->update_lock); + if (attr->index == QSFP_RESET_ALL) + { + input = simple_strtol(buf, NULL, 10); + if (input == QSFP_RESET) + { + value = 0x00; + } + else + { + printk(KERN_ALERT "qsfp_reset_all_set wrong value\n"); + return count; + } + + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, QSFP_RESET_REG, value); + + if(result != 0) + { + printk(KERN_ALERT "qsfp_reset_all_set FAILED\n"); + return count; + } + } + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + return count; +} + +ssize_t qsfp_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + port_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (port_index >= 1 && port_index <= 8) + { + target_client = Cameo_CPLD_32_client; + + } + + status = i2c_smbus_read_byte_data(target_client, qsfp_reset_regs[port_index][0]); + if( input == QSFP_RESET) + { + status |= qsfp_reset_regs[port_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_reset_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_reset_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_reset_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} + +ssize_t qsfp_present_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u8 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == QSFP_PRESENT_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_PRESENT_REG); //1-8 + result = status; + result = ~(result); + sprintf(buf, "%s0x%x\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 8) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_present_regs[port_index][0]); + } + + if (status & qsfp_present_regs[port_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} +ssize_t qsfp_int_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u8 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == QSFP_INT_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, QSFP_INT_REG); //1-8 + result = status; + sprintf(buf, "%s0x%x\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} +ssize_t qsfp_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 8) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_int_regs[port_index][0]); + } + + if (status & qsfp_int_regs[port_index][1]) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_quter_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_quter_int_regs[quter_index][0]); + + if (status & qsfp_quter_int_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_quter_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_quter_int_mask_regs[quter_index][0]); + + if (status & qsfp_quter_int_mask_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_quter_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + quter_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + target_client = Cameo_CPLD_32_client; + + status = i2c_smbus_read_byte_data(target_client, qsfp_quter_int_mask_regs[quter_index][0]); + if( input == DISABLE) + { + status |= qsfp_quter_int_mask_regs[quter_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_quter_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_quter_int_mask_set ON FAILED!\n"); + } + } + else if( input == ENABLE) + { + status &= ~(qsfp_quter_int_mask_regs[quter_index][1]); + result = i2c_smbus_write_byte_data(target_client, qsfp_quter_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_quter_int_mask_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_quter_int_mask_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} + +ssize_t qsfp_modprs_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_modprs_int_regs[quter_index][0]); + + if (status & qsfp_modprs_int_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_modprs_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + quter_index = attr->index; + sprintf(buf, ""); + + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, qsfp_modprs_int_mask_regs[quter_index][0]); + + if (status & qsfp_modprs_int_mask_regs[quter_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t qsfp_modprs_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + quter_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + target_client = Cameo_CPLD_32_client; + + status = i2c_smbus_read_byte_data(target_client, qsfp_modprs_int_mask_regs[quter_index][0]); + if( input == DISABLE) + { + status |= qsfp_modprs_int_mask_regs[quter_index][1]; + result = i2c_smbus_write_byte_data(target_client, qsfp_modprs_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_modprs_int_mask_set ON FAILED!\n"); + } + } + else if( input == ENABLE) + { + status &= ~(qsfp_modprs_int_mask_regs[quter_index][1]); + result = i2c_smbus_write_byte_data(target_client, qsfp_modprs_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: qsfp_modprs_int_mask_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: qsfp_modprs_int_mask_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.h new file mode 100644 index 0000000000..ddee23b525 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-qsfp.h @@ -0,0 +1,75 @@ +/* register offset define */ +#define QSFP_LOW_POWER_REG 0x62 +#define QSFP_RESET_REG 0x72 +#define QSFP_PRESENT_REG 0x82 +#define QSFP_INT_REG 0x92 +#define QSFP_RESET 1 + +unsigned char qsfp_low_power_regs[9][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x62, 0x01}, + {0x62, 0x02}, + {0x62, 0x04}, + {0x62, 0x08}, + {0x62, 0x10}, + {0x62, 0x20}, + {0x62, 0x40}, + {0x62, 0x80} +}; + +unsigned char qsfp_reset_regs[9][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x72, 0x01}, + {0x72, 0x02}, + {0x72, 0x04}, + {0x72, 0x08}, + {0x72, 0x10}, + {0x72, 0x20}, + {0x72, 0x40}, + {0x72, 0x80} +}; + +unsigned char qsfp_present_regs[9][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x82, 0x01}, + {0x82, 0x02}, + {0x82, 0x04}, + {0x82, 0x08}, + {0x82, 0x10}, + {0x82, 0x20}, + {0x82, 0x40}, + {0x82, 0x80} +}; + +unsigned char qsfp_int_regs[33][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x92, 0x01}, + {0x92, 0x02}, + {0x92, 0x04}, + {0x92, 0x08}, + {0x92, 0x10}, + {0x92, 0x20}, + {0x92, 0x40}, + {0x92, 0x80} +}; + +unsigned char qsfp_quter_int_regs[2][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd0, 0x20} +}; + +unsigned char qsfp_quter_int_mask_regs[2][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd1, 0x20} +}; + +unsigned char qsfp_modprs_int_regs[2][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd0, 0x04} +}; + +unsigned char qsfp_modprs_int_mask_regs[2][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd1, 0x04} +}; +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.c new file mode 100644 index 0000000000..1fb7d0ae2a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.c @@ -0,0 +1,511 @@ +/* An hwmon driver for Cameo esqc610-56sq Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" +#include "x86-64-cameo-esqc610-56sq-sfp.h" + +/* i2c_client Declaration */ +extern struct i2c_client *Cameo_CPLD_31_client; //0x31 for Port 01-32 +extern struct i2c_client *Cameo_CPLD_32_client; //0x32 for Port 33-48 +/* end of i2c_client Declaration */ + +/* extern i2c_function */ +/* end of extern i2c_function */ + +/* implement i2c_function */ +ssize_t sfp_tx_enable_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u64 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == SFP_TX_ENABLE_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, SFP_41_48_TX_ENABLE_REG); //41-48 + result = status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, SFP_33_40_TX_ENABLE_REG); //33-40 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_25_32_TX_ENABLE_REG); //25-32 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_17_24_TX_ENABLE_REG); //17-24 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_9_16_TX_ENABLE_REG); //9-16 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_1_8_TX_ENABLE_REG); //1-8 + result = (result << 8) | status; + result = (~(result)) & 0xFFFFFFFFFFFF; + sprintf(buf, "%s0x%llx\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_tx_enable_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int value = 0x0; + int result = 0; + int input = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + if (attr->index == SFP_TX_ENABLE_ALL) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = 0xff; + } + else if(input == DISABLE) + { + value = 0x00; + } + else + { + printk(KERN_ALERT "sfp_tx_enable_all_set wrong value\n"); + return count; + } + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, SFP_1_8_TX_ENABLE_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, SFP_9_16_TX_ENABLE_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, SFP_17_24_TX_ENABLE_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_31_client, SFP_25_32_TX_ENABLE_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, SFP_33_40_TX_ENABLE_REG, value); + result += i2c_smbus_write_byte_data(Cameo_CPLD_32_client, SFP_41_48_TX_ENABLE_REG, value); + + if(result != 0) + { + printk(KERN_ALERT "sfp_tx_enable_all_set FAILED\n"); + return count; + } + } + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + return count; +} + +ssize_t sfp_tx_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 32) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, sfp_tx_enable_regs[port_index][0]); + } + else if (port_index >= 33 && port_index <= 48) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, sfp_tx_enable_regs[port_index][0]); + } + + if (status & sfp_tx_enable_regs [port_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_tx_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + port_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (port_index >= 1 && port_index <= 32) + { + target_client = Cameo_CPLD_31_client; + + } + else if (port_index >= 33 && port_index <= 48) + { + target_client = Cameo_CPLD_32_client; + } + + status = i2c_smbus_read_byte_data(target_client, sfp_tx_enable_regs[port_index][0]); + if( input == ENABLE) + { + status |= sfp_tx_enable_regs[port_index][1]; + result = i2c_smbus_write_byte_data(target_client, sfp_tx_enable_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_enable_set ON FAILED!\n"); + } + } + else if( input == DISABLE) + { + status &= ~(sfp_tx_enable_regs[port_index][1]); + result = i2c_smbus_write_byte_data(target_client, sfp_tx_enable_regs[port_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_tx_enable_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: sfp_tx_enable_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} + +ssize_t sfp_rx_loss_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u64 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == SFP_RX_LOSS_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, SFP_41_48_RX_LOSS_REG); //41-48 + result = status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, SFP_33_40_RX_LOSS_REG); //33-40 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_25_32_RX_LOSS_REG); //25-32 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_17_24_RX_LOSS_REG); //17-24 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_9_16_RX_LOSS_REG); //9-16 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_1_8_RX_LOSS_REG); //1-8 + result = (result << 8) | status; + result = (~(result)) & 0xFFFFFFFFFFFF; + sprintf(buf, "%s0x%llx\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_rx_loss_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 32) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, sfp_rx_loss[port_index][0]); + } + else if (port_index >= 33 && port_index <= 48) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, sfp_rx_loss[port_index][0]); + } + + if (status & sfp_rx_loss [port_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_present_all_get(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 status = -EPERM; + u64 result = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (attr->index == SFP_PRESENT_ALL) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, SFP_41_48_PRESENT_REG); //41-48 + result = status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, SFP_33_40_PRESENT_REG); //33-40 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_25_32_PRESENT_REG); //25-32 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_17_24_PRESENT_REG); //17-24 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_9_16_PRESENT_REG); //9-16 + result = (result << 8) | status; + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, SFP_1_8_PRESENT_REG); //1-8 + result = (result << 8) | status; + result = (~(result)) & 0xFFFFFFFFFFFF; + sprintf(buf, "%s0x%llx\n", buf, result); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_present_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int port_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + port_index = attr->index; + sprintf(buf, ""); + + if (port_index >= 1 && port_index <= 32) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, sfp_present_regs[port_index][0]); + } + else if (port_index >= 33 && port_index <= 48) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, sfp_present_regs[port_index][0]); + } + + if (status & sfp_present_regs[port_index][1]) + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t sfp_rx_loss_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int int_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + int_index = attr->index; + sprintf(buf, ""); + + if (int_index >= 1 && int_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, sfp_rx_loss_int_regs[int_index][0]); + } + else if (int_index >= 5 && int_index <= 6) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, sfp_rx_loss_int_regs[int_index][0]); + } + + if (status & sfp_rx_loss_int_regs[int_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} +ssize_t sfp_rx_loss_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int int_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + int_index = attr->index; + sprintf(buf, ""); + + if (int_index >= 1 && int_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, sfp_rx_loss_int_mask_regs[int_index][0]); + } + else if (int_index >= 5 && int_index <= 6) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, sfp_rx_loss_int_mask_regs[int_index][0]); + } + + if (status & sfp_rx_loss_int_mask_regs[int_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} +ssize_t sfp_rx_loss_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + quter_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (quter_index >= 1 && quter_index <= 4) + { + target_client = Cameo_CPLD_31_client; + + } + else if (quter_index >= 5 && quter_index <= 6) + { + target_client = Cameo_CPLD_32_client; + } + + status = i2c_smbus_read_byte_data(target_client, sfp_rx_loss_int_mask_regs[quter_index][0]); + if( input == DISABLE) + { + status |= sfp_rx_loss_int_mask_regs[quter_index][1]; + result = i2c_smbus_write_byte_data(target_client, sfp_rx_loss_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_rx_loss_int_mask_set ON FAILED!\n"); + } + } + else if( input == ENABLE) + { + status &= ~(sfp_rx_loss_int_mask_regs[quter_index][1]); + result = i2c_smbus_write_byte_data(target_client, sfp_rx_loss_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_rx_loss_int_mask_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: sfp_rx_loss_int_mask_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} +ssize_t sfp_present_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int int_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + int_index = attr->index; + sprintf(buf, ""); + + if (int_index >= 1 && int_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, sfp_present_int_regs[int_index][0]); + } + else if (int_index >= 5 && int_index <= 6) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, sfp_present_int_regs[int_index][0]); + } + + if (status & sfp_present_int_regs[int_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} +ssize_t sfp_present_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + int int_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + int_index = attr->index; + sprintf(buf, ""); + + if (int_index >= 1 && int_index <= 4) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, sfp_present_int_mask_regs[int_index][0]); + } + else if (int_index >= 5 && int_index <= 6) + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, sfp_present_int_mask_regs[int_index][0]); + } + + if (status & sfp_present_int_mask_regs[int_index][1]) + { + sprintf(buf, "%s%d\n", buf, NORMAL); + } + else + { + sprintf(buf, "%s%d\n", buf, ABNORMAL); + } + + return sprintf(buf, "%s\n", buf); +} +ssize_t sfp_present_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int result = 0; + int input = 0; + int quter_index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *Cameo_CPLD_31_data = i2c_get_clientdata(Cameo_CPLD_31_client); + struct Cameo_i2c_data *Cameo_CPLD_32_data = i2c_get_clientdata(Cameo_CPLD_32_client); + struct i2c_client *target_client = NULL; + + quter_index = attr->index; + input = simple_strtol(buf, NULL, 10); + mutex_lock(&Cameo_CPLD_31_data->update_lock); + mutex_lock(&Cameo_CPLD_32_data->update_lock); + + if (quter_index >= 1 && quter_index <= 4) + { + target_client = Cameo_CPLD_31_client; + + } + else if (quter_index >= 5 && quter_index <= 6) + { + target_client = Cameo_CPLD_32_client; + } + + status = i2c_smbus_read_byte_data(target_client, sfp_present_int_mask_regs[quter_index][0]); + if( input == DISABLE) + { + status |= sfp_present_int_mask_regs[quter_index][1]; + result = i2c_smbus_write_byte_data(target_client, sfp_present_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_present_int_mask_set ON FAILED!\n"); + } + } + else if( input == ENABLE) + { + status &= ~(sfp_present_int_mask_regs[quter_index][1]); + result = i2c_smbus_write_byte_data(target_client, sfp_present_int_mask_regs[quter_index][0], status); + if (result < 0) + { + printk(KERN_ALERT "ERROR: sfp_present_int_mask_set OFF FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "ERROR: sfp_present_int_mask_set WRONG VALUE\n"); + } + + mutex_unlock(&Cameo_CPLD_31_data->update_lock); + mutex_unlock(&Cameo_CPLD_32_data->update_lock); + + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.h new file mode 100644 index 0000000000..fc7885f18c --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sfp.h @@ -0,0 +1,218 @@ +/* register offset define */ +#define SFP_1_8_TX_ENABLE_REG 0x70 +#define SFP_9_16_TX_ENABLE_REG 0x71 +#define SFP_17_24_TX_ENABLE_REG 0x72 +#define SFP_25_32_TX_ENABLE_REG 0x73 +#define SFP_33_40_TX_ENABLE_REG 0x70 +#define SFP_41_48_TX_ENABLE_REG 0x71 + +#define SFP_1_8_RX_LOSS_REG 0x90 +#define SFP_9_16_RX_LOSS_REG 0x91 +#define SFP_17_24_RX_LOSS_REG 0x92 +#define SFP_25_32_RX_LOSS_REG 0x93 +#define SFP_33_40_RX_LOSS_REG 0x90 +#define SFP_41_48_RX_LOSS_REG 0x91 + +#define SFP_1_8_PRESENT_REG 0x80 +#define SFP_9_16_PRESENT_REG 0x81 +#define SFP_17_24_PRESENT_REG 0x82 +#define SFP_25_32_PRESENT_REG 0x83 +#define SFP_33_40_PRESENT_REG 0x80 +#define SFP_41_48_PRESENT_REG 0x81 + +unsigned char sfp_tx_enable_regs[49][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x70, 0x01}, + {0x70, 0x02}, + {0x70, 0x04}, + {0x70, 0x08}, + {0x70, 0x10}, + {0x70, 0x20}, + {0x70, 0x40}, + {0x70, 0x80}, + {0x71, 0x01}, + {0x71, 0x02}, + {0x71, 0x04}, + {0x71, 0x08}, + {0x71, 0x10}, + {0x71, 0x20}, + {0x71, 0x40}, + {0x71, 0x80}, + {0x72, 0x01}, + {0x72, 0x02}, + {0x72, 0x04}, + {0x72, 0x08}, + {0x72, 0x10}, + {0x72, 0x20}, + {0x72, 0x40}, + {0x72, 0x80}, + {0x73, 0x01}, + {0x73, 0x02}, + {0x73, 0x04}, + {0x73, 0x08}, + {0x73, 0x10}, + {0x73, 0x20}, + {0x73, 0x40}, + {0x73, 0x80}, + {0x70, 0x01}, + {0x70, 0x02}, + {0x70, 0x04}, + {0x70, 0x08}, + {0x70, 0x10}, + {0x70, 0x20}, + {0x70, 0x40}, + {0x70, 0x80}, + {0x71, 0x01}, + {0x71, 0x02}, + {0x71, 0x04}, + {0x71, 0x08}, + {0x71, 0x10}, + {0x71, 0x20}, + {0x71, 0x40}, + {0x71, 0x80} +}; + +unsigned char sfp_rx_loss[49][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x90, 0x01}, + {0x90, 0x02}, + {0x90, 0x04}, + {0x90, 0x08}, + {0x90, 0x10}, + {0x90, 0x20}, + {0x90, 0x40}, + {0x90, 0x80}, + {0x91, 0x01}, + {0x91, 0x02}, + {0x91, 0x04}, + {0x91, 0x08}, + {0x91, 0x10}, + {0x91, 0x20}, + {0x91, 0x40}, + {0x91, 0x80}, + {0x92, 0x01}, + {0x92, 0x02}, + {0x92, 0x04}, + {0x92, 0x08}, + {0x92, 0x10}, + {0x92, 0x20}, + {0x92, 0x40}, + {0x92, 0x80}, + {0x93, 0x01}, + {0x93, 0x02}, + {0x93, 0x04}, + {0x93, 0x08}, + {0x93, 0x10}, + {0x93, 0x20}, + {0x93, 0x40}, + {0x93, 0x80}, + {0x90, 0x01}, + {0x90, 0x02}, + {0x90, 0x04}, + {0x90, 0x08}, + {0x90, 0x10}, + {0x90, 0x20}, + {0x90, 0x40}, + {0x90, 0x80}, + {0x91, 0x01}, + {0x91, 0x02}, + {0x91, 0x04}, + {0x91, 0x08}, + {0x91, 0x10}, + {0x91, 0x20}, + {0x91, 0x40}, + {0x91, 0x80} +}; + +unsigned char sfp_present_regs[49][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0x80, 0x01}, + {0x80, 0x02}, + {0x80, 0x04}, + {0x80, 0x08}, + {0x80, 0x10}, + {0x80, 0x20}, + {0x80, 0x40}, + {0x80, 0x80}, + {0x81, 0x01}, + {0x81, 0x02}, + {0x81, 0x04}, + {0x81, 0x08}, + {0x81, 0x10}, + {0x81, 0x20}, + {0x81, 0x40}, + {0x81, 0x80}, + {0x82, 0x01}, + {0x82, 0x02}, + {0x82, 0x04}, + {0x82, 0x08}, + {0x82, 0x10}, + {0x82, 0x20}, + {0x82, 0x40}, + {0x82, 0x80}, + {0x83, 0x01}, + {0x83, 0x02}, + {0x83, 0x04}, + {0x83, 0x08}, + {0x83, 0x10}, + {0x83, 0x20}, + {0x83, 0x40}, + {0x83, 0x80}, + {0x80, 0x01}, + {0x80, 0x02}, + {0x80, 0x04}, + {0x80, 0x08}, + {0x80, 0x10}, + {0x80, 0x20}, + {0x80, 0x40}, + {0x80, 0x80}, + {0x81, 0x01}, + {0x81, 0x02}, + {0x81, 0x04}, + {0x81, 0x08}, + {0x81, 0x10}, + {0x81, 0x20}, + {0x81, 0x40}, + {0x81, 0x80} +}; + +unsigned char sfp_rx_loss_int_regs[7][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd0, 0x10}, //1-8 + {0xd0, 0x20}, //9-16 + {0xd0, 0x40}, //17-24 + {0xd0, 0x80}, //25-32 + {0xd0, 0x08}, //33-40 + {0xd0, 0x10} //41-48 +}; + +unsigned char sfp_present_int_regs[7][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd0, 0x01}, //1-8 + {0xd0, 0x02}, //9-16 + {0xd0, 0x04}, //17-24 + {0xd0, 0x08}, //25-32 + {0xd0, 0x01}, //33-40 + {0xd0, 0x02} //41-48 +}; + +unsigned char sfp_rx_loss_int_mask_regs[7][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd1, 0x10}, //1-8 + {0xd1, 0x20}, //9-16 + {0xd1, 0x40}, //17-24 + {0xd1, 0x80}, //25-32 + {0xd1, 0x08}, //33-40 + {0xd1, 0x10} //41-48 +}; + +unsigned char sfp_present_int_mask_regs[7][2] = { + {0x00, 0x00}, //cpld offset, bit mask + {0xd1, 0x01}, //1-8 + {0xd1, 0x02}, //9-16 + {0xd1, 0x04}, //17-24 + {0xd1, 0x08}, //25-32 + {0xd1, 0x01}, //33-40 + {0xd1, 0x02} //41-48 +}; +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.c new file mode 100644 index 0000000000..e6b9e84ba8 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.c @@ -0,0 +1,789 @@ +/* An hwmon driver for Cameo esqc610-56sq Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" +#include "x86-64-cameo-esqc610-56sq-sys.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_CPLD_30_client; //0x30 for SYS CPLD +extern struct i2c_client *Cameo_CPLD_31_client; //0x31 for Port 01-16 +extern struct i2c_client *Cameo_CPLD_32_client; //0x32 for Port 17-32 +extern struct i2c_client *Cameo_CPLD_23_client; //0x23 for Fan CPLD +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t cpld_hw_ver_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case 23: + if( bmc_enable() == ENABLE) + { + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, 0xc6); + } + else + { + status = i2c_smbus_read_byte_data(Cameo_CPLD_23_client, CPLD_VER_REG); + } + break; + case 30: + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, CPLD_VER_REG); + break; + case 31: + status = i2c_smbus_read_byte_data(Cameo_CPLD_31_client, CPLD_VER_REG); + break; + case 32: + status = i2c_smbus_read_byte_data(Cameo_CPLD_32_client, CPLD_VER_REG); + break; + } + if(status < 0) + { + mutex_unlock(&data->update_lock); + return status; + } + else + { + mutex_unlock(&data->update_lock); + sprintf(buf, "%s0x%x\n", buf, status); + } + return sprintf(buf, "%s\n", buf); +} + +ssize_t wdt_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == WDT_EN) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, WDT_EN_REG) & BIT_4_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t wdt_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, WDT_EN_REG); + if (attr->index == WDT_EN) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | WDT_EN_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, WDT_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: wdt_enable_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & WDT_EN_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, WDT_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: wdt_enable_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "wdt_enable_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t eeprom_wp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == EEPROM_WP) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG) & BIT_2_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t eeprom_wp_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG); + if (attr->index == EEPROM_WP) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | EEPROM_WP_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: eeprom_wp_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & EEPROM_WP_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, EEPROM_WP_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: eeprom_wp_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "eeprom_wp_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t usb_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == USB_EN) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG) & BIT_1_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t usb_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, USB_EN_REG); + if (attr->index == USB_EN) + { + input = simple_strtol(buf, NULL, 10); + if (input == ENABLE) + { + value = status | USB_EN_ENABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, USB_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: usb_enable_set FAILED!\n"); + } + } + else if (input == DISABLE) + { + value = status & USB_EN_DISABLE; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, USB_EN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: usb_enable_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "usb_enable_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t reset_mac_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, MAC_RESET_REG); + if (attr->index == RESET) + { + input = simple_strtol(buf, NULL, 10); + if (input == MAC_RESET) + { + value = MAC_RESET; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, MAC_RESET_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: reset_mac_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "reset_mac_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t shutdown_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SHUTDOWN_REG); + if (attr->index == SHUTDOWN_SET) + { + input = simple_strtol(buf, NULL, 10); + if (input == SHUTDOWN) + { + value = status | SHUTDOWN; + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, SHUTDOWN_REG, value); + if (result < 0) + { + printk(KERN_ALERT "ERROR: shutdown_set FAILED!\n"); + } + } + else + { + printk(KERN_ALERT "shutdown_set wrong Value\n"); + } + } + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t bmc_enable_get(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + if (attr->index == BMC_PRESENT) + { + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, BMC_EN_REG) & BIT_0_MASK) + { + sprintf(buf, "%s%d\n", buf, ENABLE); + } + else + { + sprintf(buf, "%s%d\n", buf, DISABLE); + } + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case TEMP_TH0_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_TH1_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_TH2_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_TH3_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case TEMP_TH0_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_0_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_TH1_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_1_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_TH2_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case TEMP_TH3_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + switch (attr->index) + { + case TEMP_TH0_INT_MASK: + if (input == ENABLE) + { + value = status | 0x01; + } + else if (input == DISABLE) + { + value = status & 0xfe; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + case TEMP_TH1_INT_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + case TEMP_TH2_INT_MASK: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + case TEMP_TH3_INT_MASK: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + else + { + printk(KERN_ALERT "themal_int_mask_set wrong Value\n"); + return count; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, THERMAL_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} + +ssize_t sys_int_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case CPLD_FP_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_RP_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_FAN_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_PSU_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case THERMAL_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_6_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case USB_INT: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_REG) & BIT_7_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sys_int_mask_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int result = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + sprintf(buf, ""); + switch (attr->index) + { + case CPLD_FP_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_2_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_RP_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_3_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_FAN_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_4_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case CPLD_PSU_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_5_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case THERMAL_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_6_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + case USB_INT_MASK: + if (i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG) & BIT_7_MASK) + { + result = ENABLE; + } + else + { + result = DISABLE; + } + break; + } + mutex_unlock(&data->update_lock); + sprintf(buf, "%s%d\n", buf, result); + return sprintf(buf, "%s\n", buf); +} + +ssize_t sys_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int status = -EPERM; + int value = -EPERM; + int result = -EPERM; + int input; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct Cameo_i2c_data *data = i2c_get_clientdata(Cameo_CPLD_30_client); + + mutex_lock(&data->update_lock); + status = i2c_smbus_read_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG); + + input = simple_strtol(buf, NULL, 10); + switch (attr->index) + { + case CPLD_FP_INT_MASK: + if (input == ENABLE) + { + value = status | 0x02; + } + else if (input == DISABLE) + { + value = status & 0xfd; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case CPLD_RP_INT_MASK: + if (input == ENABLE) + { + value = status | 0x04; + } + else if (input == DISABLE) + { + value = status & 0xfb; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case CPLD_FAN_INT_MASK: + if (input == ENABLE) + { + value = status | 0x08; + } + else if (input == DISABLE) + { + value = status & 0xf7; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case CPLD_PSU_INT_MASK: + if (input == ENABLE) + { + value = status | 0x10; + } + else if (input == DISABLE) + { + value = status & 0xef; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case THERMAL_INT_MASK: + if (input == ENABLE) + { + value = status | 0x20; + } + else if (input == DISABLE) + { + value = status & 0xdf; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + case USB_INT_MASK: + if (input == ENABLE) + { + value = status | 0x40; + } + else if (input == DISABLE) + { + value = status & 0xbf; + } + else + { + printk(KERN_ALERT "sys_int_mask_set wrong Value\n"); + return count; + } + break; + } + result = i2c_smbus_write_byte_data(Cameo_CPLD_30_client, SYS_INT_MASK_REG, value); + mutex_unlock(&data->update_lock); + return count; +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.h new file mode 100644 index 0000000000..400aeaf3d7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-sys.h @@ -0,0 +1,23 @@ +/* register offset define */ +#define CPLD_VER_REG 0x20 +#define WDT_EN_REG 0xa0 +#define WDT_EN_ENABLE 0x10 +#define WDT_EN_DISABLE 0xef +#define EEPROM_WP_REG 0xa0 +#define EEPROM_WP_ENABLE 0x04 +#define EEPROM_WP_DISABLE 0xfB +#define USB_EN_REG 0xa0 +#define USB_EN_ENABLE 0x02 +#define USB_EN_DISABLE 0xfD +#define MAC_RESET_REG 0xa1 +#define MAC_RESET 0x00 +#define SHUTDOWN_REG 0xa1 +#define SHUTDOWN 0x10 +#define BMC_EN_REG 0xa4 +#define BMC_EN_ENABLE 0x01 +#define BMC_EN_DISABLE 0x00 +#define THERMAL_INT_REG 0xc0 +#define THERMAL_INT_MASK_REG 0xc1 +#define SYS_INT_REG 0xd0 +#define SYS_INT_MASK_REG 0xd1 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.c new file mode 100644 index 0000000000..f62a7f2d72 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.c @@ -0,0 +1,286 @@ +/* An hwmon driver for Cameo esqc610-56sq Innovium i2c Module */ +#pragma GCC diagnostic ignored "-Wformat-zero-length" +#include "x86-64-cameo-esqc610-56sq.h" +#include "x86-64-cameo-esqc610-56sq-common.h" +#include "x86-64-cameo-esqc610-56sq-thermal.h" + +/* extern i2c_client */ +extern struct i2c_client *Cameo_BMC_14_client; //0x14 for BMC slave +/* end of extern i2c_client */ + +/* implement i2c_function */ +ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_TH0_T: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_T_REG); + break; + case TEMP_TH0_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_B_REG); + break; + case TEMP_TH0_R: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_R_REG); + break; + case TEMP_TH1_T: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_T_REG); + break; + case TEMP_TH1_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_B_REG); + break; + case TEMP_TH3_T: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_T_REG); + break; + case TEMP_TH3_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_B_REG); + break; + case TEMP_TH2_T: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_T_REG); + break; + case TEMP_TH2_B: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_B_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_max_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_TH0_T_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_T_MAX_REG); + break; + case TEMP_TH1_T_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_T_MAX_REG); + break; + case TEMP_TH3_T_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_T_MAX_REG); + break; + case TEMP_TH2_T_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_T_MAX_REG); + break; + case TEMP_TH0_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_B_MAX_REG); + break; + case TEMP_TH0_R_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_R_MAX_REG); + break; + case TEMP_TH1_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_B_MAX_REG); + break; + case TEMP_TH3_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_B_MAX_REG); + break; + case TEMP_TH2_B_MAX: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_B_MAX_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_min_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_TH0_T_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_T_MIN_REG); + break; + case TEMP_TH1_T_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_T_MIN_REG); + break; + case TEMP_TH3_T_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_T_MIN_REG); + break; + case TEMP_TH2_T_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_T_MIN_REG); + break; + case TEMP_TH0_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_B_MIN_REG); + break; + case TEMP_TH0_R_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_R_MIN_REG); + break; + case TEMP_TH1_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_B_MIN_REG); + break; + case TEMP_TH3_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_B_MIN_REG); + break; + case TEMP_TH2_B_MIN: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_B_MIN_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_crit_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_TH0_T_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_T_CRIT_REG); + break; + case TEMP_TH1_T_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_T_CRIT_REG); + break; + case TEMP_TH3_T_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_T_CRIT_REG); + break; + case TEMP_TH2_T_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_T_CRIT_REG); + break; + case TEMP_TH0_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_B_CRIT_REG); + break; + case TEMP_TH0_R_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_R_CRIT_REG); + break; + case TEMP_TH1_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_B_CRIT_REG); + break; + case TEMP_TH3_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_B_CRIT_REG); + break; + case TEMP_TH2_B_CRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_B_CRIT_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} + +ssize_t themal_temp_lcrit_get(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = -EPERM; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + sprintf(buf, ""); + + if( bmc_enable() == ENABLE) + { + switch (attr->index) + { + case TEMP_TH0_T_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_T_LCRIT_REG); + break; + case TEMP_TH1_T_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_T_LCRIT_REG); + break; + case TEMP_TH3_T_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_T_LCRIT_REG); + break; + case TEMP_TH2_T_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_T_LCRIT_REG); + break; + case TEMP_TH0_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_B_LCRIT_REG); + break; + case TEMP_TH0_R_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH0_R_LCRIT_REG); + break; + case TEMP_TH1_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH1_B_LCRIT_REG); + break; + case TEMP_TH3_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH3_B_LCRIT_REG); + break; + case TEMP_TH2_B_LCRIT: + status = i2c_smbus_read_byte_data(Cameo_BMC_14_client, TEMP_TH2_B_LCRIT_REG); + break; + } + if(status == 0xff || status < 0) + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + else + { + sprintf(buf, "%s%d\n", buf, (read_8bit_temp((status & 0x80), status))*1000); + } + } + else + { + sprintf(buf, "%sAccess BMC module FAILED\n", buf); + } + + return sprintf(buf, "%s\n", buf); +} +/* end of implement i2c_function */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.h new file mode 100644 index 0000000000..1e874b8d63 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq-thermal.h @@ -0,0 +1,50 @@ +/* register offset define */ +#define TEMP_TH0_T_REG 0x10 +#define TEMP_TH0_B_REG 0x11 +#define TEMP_TH0_T_MAX_REG 0x12 +#define TEMP_TH0_T_MIN_REG 0x13 +#define TEMP_TH0_T_CRIT_REG 0x14 +#define TEMP_TH0_T_LCRIT_REG 0x15 +#define TEMP_TH0_B_MAX_REG 0x16 +#define TEMP_TH0_B_MIN_REG 0x17 +#define TEMP_TH0_B_CRIT_REG 0x18 +#define TEMP_TH0_B_LCRIT_REG 0x19 +#define TEMP_TH0_R_REG 0x1a +#define TEMP_TH0_R_MAX_REG 0x1b +#define TEMP_TH0_R_MIN_REG 0x1c +#define TEMP_TH0_R_CRIT_REG 0x1d +#define TEMP_TH0_R_LCRIT_REG 0x1e + +#define TEMP_TH1_T_REG 0x20 +#define TEMP_TH1_B_REG 0x21 +#define TEMP_TH1_T_MAX_REG 0x22 +#define TEMP_TH1_T_MIN_REG 0x23 +#define TEMP_TH1_T_CRIT_REG 0x24 +#define TEMP_TH1_T_LCRIT_REG 0x25 +#define TEMP_TH1_B_MAX_REG 0x26 +#define TEMP_TH1_B_MIN_REG 0x27 +#define TEMP_TH1_B_CRIT_REG 0x28 +#define TEMP_TH1_B_LCRIT_REG 0x29 + +#define TEMP_TH3_T_REG 0x30 +#define TEMP_TH3_B_REG 0x31 +#define TEMP_TH3_T_MAX_REG 0x32 +#define TEMP_TH3_T_MIN_REG 0x33 +#define TEMP_TH3_T_CRIT_REG 0x34 +#define TEMP_TH3_T_LCRIT_REG 0x35 +#define TEMP_TH3_B_MAX_REG 0x36 +#define TEMP_TH3_B_MIN_REG 0x37 +#define TEMP_TH3_B_CRIT_REG 0x38 +#define TEMP_TH3_B_LCRIT_REG 0x39 + +#define TEMP_TH2_T_REG 0x40 +#define TEMP_TH2_B_REG 0x41 +#define TEMP_TH2_T_MAX_REG 0x42 +#define TEMP_TH2_T_MIN_REG 0x43 +#define TEMP_TH2_T_CRIT_REG 0x44 +#define TEMP_TH2_T_LCRIT_REG 0x45 +#define TEMP_TH2_B_MAX_REG 0x46 +#define TEMP_TH2_B_MIN_REG 0x47 +#define TEMP_TH2_B_CRIT_REG 0x48 +#define TEMP_TH2_B_LCRIT_REG 0x49 +/* end of register offset define */ \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq.h b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq.h index e539a411e5..9ccb58a42f 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq.h +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/x86-64-cameo-esqc610-56sq.h @@ -12,45 +12,7 @@ #include #include -#define DRIVER_VERSION "1.4.1" - -#define TURN_OFF 0 -#define TURN_ON 1 -#define GET_USB 2 -#define GET_LOC 3 -#define LOC_OFF 0 -#define LOC_BLINK 1 -#define ALARM_OFF 0 -#define ALARM_AMBER 1 -#define ALARM_GREEN 2 -#define PSU_1_GOOD 3 -#define PSU_2_GOOD 4 -#define PCIE_INT 1 -#define QSFP_1_INT 2 -#define QSFP_2_INT 3 -#define FAN_INT 4 -#define PSU_INT 5 -#define SENSOR_INT 6 -#define USB_INT 7 -#define USB_ON 0x2 -#define USB_OFF 0xfd -#define DIAG_G_ON 0x2 -#define DIAG_G_OFF 0xfd -#define LED_ON 0x1 -#define LED_OFF 0xfe -#define DIAG_A_ON 0x1 -#define DIAG_A_OFF 0xfe -#define LOC_LED_OFF 0x4 -#define LOC_LED_BLINK 0xfb -#define SWITCH_LED_OFF 0 -#define SWITCH_LED_A_N 1 -#define SWITCH_LED_A_B 2 -#define SWITCH_LED_G_N 3 -#define SWITCH_LED_G_B 4 - -#define BMC_PRESENT_OFFSET 0xa4 - -#define SYSFAN_MAX_NUM 4 +#define DRIVER_VERSION "1.0.3" struct i2c_adap { int nr; @@ -63,98 +25,87 @@ struct i2c_adap *gather_i2c_busses(void); void free_adapters(struct i2c_adap *adapters); /* compiler conditional */ -#define LED_CTRL_WANTED -#define USB_CTRL_WANTED -#define ASPEED_BMC_WANTED -#define PSU_STAT_WANTED -//#define WDT_CTRL_WANTED -//#define EEPROM_WP_WANTED -//#define I2C_SWITCH_WANTED -//#define THEMAL_WANTED -//#define FAN_CTRL_WANTED - -//#define DEBUG_MSG -#ifdef DEBUG_MSG - #define debug_print(s) printk s -#else - #define debug_print(s) -#endif - /* end of compiler conditional */ -/* i2c_client Declaration */ -static struct i2c_client *ESQC_610_i2c_client; //0x30 for other device -static struct i2c_client *Cameo_CPLD_2_client; //0x31 for Port 01-32 -static struct i2c_client *Cameo_CPLD_3_client; //0x32 for Port 33-48 QSFP 1-8 -static struct i2c_client *Cameo_CPLD_4_client; //0x23 for Fan Status -static struct i2c_client *Cameo_CPLD_5_client; //0x35 for Power Status -#ifdef I2C_SWITCH_WANTED -static struct i2c_client *Cameo_Switch_1_client; //0x73 -static struct i2c_client *Cameo_Switch_2_client; //0x77 -#endif -#ifdef THEMAL_WANTED -static struct i2c_client *Cameo_Sensor_client; //0x4c themal sensor -static struct i2c_client *Cameo_Sensor_fan_client; //0x2e themal sensor -#endif -#ifdef ASPEED_BMC_WANTED -static struct i2c_client *Cameo_BMC_client; //0x14 ASPEED BMC -#endif -/* end of i2c_client Declaration */ - /* Function Declaration */ /* i2c-0 */ -static ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf); -#ifdef PSU_STAT_WANTED -static ssize_t psu_module_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t dc_chip_switch_get(struct device *dev, struct device_attribute *da, char *buf); -#endif -#ifdef USB_CTRL_WANTED -static ssize_t usb_power_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t usb_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif -#ifdef LED_CTRL_WANTED -static ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif -static ssize_t sys_led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sys_led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t reset_mac_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t shutdown_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t themal_status_get(struct device *dev, struct device_attribute *da, char *buf); -#ifdef THEMAL_WANTED -static ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf); -#endif -static ssize_t themal_mask_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t themal_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t int_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_tx_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t low_power_all_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t low_power_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t low_power_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t low_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t qsfp_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t qsfp_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf); -#ifdef FAN_CTRL_WANTED -static ssize_t fan_mode_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t fan_mode_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t fan_rpm_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t fan_rpm_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif -#ifdef ASPEED_BMC_WANTED -static ssize_t bmc_register_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t bmc_module_detect(struct device *dev, struct device_attribute *da, char *buf); -#endif -#ifdef WDT_CTRL_WANTED -static ssize_t wdt_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t wdt_status_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif -#ifdef EEPROM_WP_WANTED -static ssize_t eeprom_wp_status_get(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t eeprom_wp_status_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -#endif -static ssize_t hw_version_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t cpld_hw_ver_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t wdt_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t wdt_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t eeprom_wp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t eeprom_wp_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t usb_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t usb_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t reset_mac_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t shutdown_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t bmc_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_ctrl_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_ctrl_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t led_fiber_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t led_fiber_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t themal_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sys_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sys_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sys_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t themal_temp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_max_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_min_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_crit_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t themal_temp_lcrit_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_ctrl_mode_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_ctrl_rpm_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_status_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_power_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t fan_rpm_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_status_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_temp_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_fan_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_pout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_pin_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_mfr_model_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_iout_max_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t psu_vmode_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_vout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_iout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t dc_pout_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_tx_enable_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_tx_enable_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sfp_tx_enable_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_tx_enable_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sfp_rx_loss_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_rx_loss_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_rx_loss_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_rx_loss_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_rx_loss_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t sfp_present_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_present_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_present_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t sfp_present_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_low_power_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_low_power_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_low_power_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_low_power_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_reset_all_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_reset_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_present_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_present_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_int_all_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_quter_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_quter_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_quter_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t qsfp_modprs_int_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_modprs_int_mask_get(struct device *dev, struct device_attribute *da, char *buf); +ssize_t qsfp_modprs_int_mask_set(struct device *dev, struct device_attribute *da, const char *buf, size_t count); /* end of Function Declaration */ /* struct i2c_data */ @@ -162,360 +113,1103 @@ struct Cameo_i2c_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status; /* Status register read from CPLD */ + char valid; + unsigned long last_updated; + u8 status; }; /* struct i2c_sysfs_attributes */ enum Cameo_i2c_sysfs_attributes { - /* i2c-0 */ - /*CPLD 0X30*/ - PSU_PRESENT, - PSU_STATUS, -#ifdef PSU_STAT_WANTED - PSU_MODULE_1, - PSU_MODULE_2, - DC_CHIP_SWITCH, -#endif -#ifdef USB_CTRL_WANTED - USB_POWER, -#endif -#ifdef LED_CTRL_WANTED - LED_CTRL, -#endif - SYS_LED, - FLOW_LED, - SW_LED_1, - SW_LED_2, - RESET_MAC, - SHUTDOWN_DUT, - SENSOR_STATUS, -#ifdef THEMAL_WANTED - SENSOR_TEMP, -#endif - SENSOR_INT_MASK, - INT_STATUS, - /*CPLD 0X31 & 0X32*/ - SFP_PRESENT, - SFP_RX_LOSS, - SFP_TX_STAT, + CPLD_23_VER, + CPLD_30_VER, + CPLD_31_VER, + CPLD_32_VER, + WDT_EN, + EEPROM_WP, + USB_EN, + SHUTDOWN_SET, + RESET, + BMC_PRESENT, + LED_1, + LED_2, + LED_FLOW, + LED_SYS, + LED_FIBER, + TEMP_TH0_INT, + TEMP_TH1_INT, + TEMP_TH3_INT, + TEMP_TH2_INT, + TEMP_TH0_INT_MASK, + TEMP_TH1_INT_MASK, + TEMP_TH3_INT_MASK, + TEMP_TH2_INT_MASK, + CPLD_FP_INT, + CPLD_RP_INT, + CPLD_FAN_INT, + CPLD_PSU_INT, + THERMAL_INT, + USB_INT, + CPLD_FP_INT_MASK, + CPLD_RP_INT_MASK, + CPLD_FAN_INT_MASK, + CPLD_PSU_INT_MASK, + THERMAL_INT_MASK, + USB_INT_MASK, + TEMP_TH0_T, + TEMP_TH0_B, + TEMP_TH0_R, + TEMP_TH1_T, + TEMP_TH1_B, + TEMP_TH3_T, + TEMP_TH3_B, + TEMP_TH2_T, + TEMP_TH2_B, + TEMP_TH0_T_MAX, + TEMP_TH1_T_MAX, + TEMP_TH3_T_MAX, + TEMP_TH2_T_MAX, + TEMP_TH0_R_MAX, + TEMP_TH0_B_MAX, + TEMP_TH1_B_MAX, + TEMP_TH3_B_MAX, + TEMP_TH2_B_MAX, + TEMP_TH0_T_MIN, + TEMP_TH1_T_MIN, + TEMP_TH3_T_MIN, + TEMP_TH2_T_MIN, + TEMP_TH0_R_MIN, + TEMP_TH0_B_MIN, + TEMP_TH1_B_MIN, + TEMP_TH3_B_MIN, + TEMP_TH2_B_MIN, + TEMP_TH0_T_CRIT, + TEMP_TH1_T_CRIT, + TEMP_TH3_T_CRIT, + TEMP_TH2_T_CRIT, + TEMP_TH0_R_CRIT, + TEMP_TH0_B_CRIT, + TEMP_TH1_B_CRIT, + TEMP_TH3_B_CRIT, + TEMP_TH2_B_CRIT, + TEMP_TH0_T_LCRIT, + TEMP_TH1_T_LCRIT, + TEMP_TH3_T_LCRIT, + TEMP_TH2_T_LCRIT, + TEMP_TH0_R_LCRIT, + TEMP_TH0_B_LCRIT, + TEMP_TH1_B_LCRIT, + TEMP_TH3_B_LCRIT, + TEMP_TH2_B_LCRIT, + FANCTRL_RPM, + FANCTRL_MODE, + FAN1_STAT, + FAN2_STAT, + FAN3_STAT, + FAN4_STAT, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN1_POWER, + FAN2_POWER, + FAN3_POWER, + FAN4_POWER, + FAN1_FRONT_RPM, + FAN2_FRONT_RPM, + FAN3_FRONT_RPM, + FAN4_FRONT_RPM, + FAN1_REAR_RPM, + FAN2_REAR_RPM, + FAN3_REAR_RPM, + FAN4_REAR_RPM, + PSU1_GOOD, + PSU2_GOOD, + PSU1_PRNT, + PSU2_PRNT, + PSU1_VIN, + PSU1_IIN, + PSU1_VOUT, + PSU1_IOUT, + PSU1_TEMP, + PSU1_FAN_SPEED, + PSU1_POUT, + PSU1_PIN, + PSU1_MFR_MODEL, + PSU1_MFR_IOUT_MAX, + PSU1_VMODE, + PSU2_VIN, + PSU2_IIN, + PSU2_VOUT, + PSU2_IOUT, + PSU2_TEMP, + PSU2_FAN_SPEED, + PSU2_POUT, + PSU2_PIN, + PSU2_MFR_MODEL, + PSU2_MFR_IOUT_MAX, + PSU2_VMODE, + DC6E_P0_VOUT, + DC6E_P0_IOUT, + DC6E_P0_POUT, + DC6E_P1_VOUT, + DC6E_P1_IOUT, + DC6E_P1_POUT, + DC70_P0_VOUT, + DC70_P0_IOUT, + DC70_P0_POUT, + DC70_P1_VOUT, + DC70_P1_IOUT, + DC70_P1_POUT, + SFP_TX_ENABLE_ALL, + SFP1_TX_ENABLE, + SFP2_TX_ENABLE, + SFP3_TX_ENABLE, + SFP4_TX_ENABLE, + SFP5_TX_ENABLE, + SFP6_TX_ENABLE, + SFP7_TX_ENABLE, + SFP8_TX_ENABLE, + SFP9_TX_ENABLE, + SFP10_TX_ENABLE, + SFP11_TX_ENABLE, + SFP12_TX_ENABLE, + SFP13_TX_ENABLE, + SFP14_TX_ENABLE, + SFP15_TX_ENABLE, + SFP16_TX_ENABLE, + SFP17_TX_ENABLE, + SFP18_TX_ENABLE, + SFP19_TX_ENABLE, + SFP20_TX_ENABLE, + SFP21_TX_ENABLE, + SFP22_TX_ENABLE, + SFP23_TX_ENABLE, + SFP24_TX_ENABLE, + SFP25_TX_ENABLE, + SFP26_TX_ENABLE, + SFP27_TX_ENABLE, + SFP28_TX_ENABLE, + SFP29_TX_ENABLE, + SFP30_TX_ENABLE, + SFP31_TX_ENABLE, + SFP32_TX_ENABLE, + SFP33_TX_ENABLE, + SFP34_TX_ENABLE, + SFP35_TX_ENABLE, + SFP36_TX_ENABLE, + SFP37_TX_ENABLE, + SFP38_TX_ENABLE, + SFP39_TX_ENABLE, + SFP40_TX_ENABLE, + SFP41_TX_ENABLE, + SFP42_TX_ENABLE, + SFP43_TX_ENABLE, + SFP44_TX_ENABLE, + SFP45_TX_ENABLE, + SFP46_TX_ENABLE, + SFP47_TX_ENABLE, + SFP48_TX_ENABLE, + SFP_RX_LOSS_ALL, + SFP1_RX_LOSS, + SFP2_RX_LOSS, + SFP3_RX_LOSS, + SFP4_RX_LOSS, + SFP5_RX_LOSS, + SFP6_RX_LOSS, + SFP7_RX_LOSS, + SFP8_RX_LOSS, + SFP9_RX_LOSS, + SFP10_RX_LOSS, + SFP11_RX_LOSS, + SFP12_RX_LOSS, + SFP13_RX_LOSS, + SFP14_RX_LOSS, + SFP15_RX_LOSS, + SFP16_RX_LOSS, + SFP17_RX_LOSS, + SFP18_RX_LOSS, + SFP19_RX_LOSS, + SFP20_RX_LOSS, + SFP21_RX_LOSS, + SFP22_RX_LOSS, + SFP23_RX_LOSS, + SFP24_RX_LOSS, + SFP25_RX_LOSS, + SFP26_RX_LOSS, + SFP27_RX_LOSS, + SFP28_RX_LOSS, + SFP29_RX_LOSS, + SFP30_RX_LOSS, + SFP31_RX_LOSS, + SFP32_RX_LOSS, + SFP33_RX_LOSS, + SFP34_RX_LOSS, + SFP35_RX_LOSS, + SFP36_RX_LOSS, + SFP37_RX_LOSS, + SFP38_RX_LOSS, + SFP39_RX_LOSS, + SFP40_RX_LOSS, + SFP41_RX_LOSS, + SFP42_RX_LOSS, + SFP43_RX_LOSS, + SFP44_RX_LOSS, + SFP45_RX_LOSS, + SFP46_RX_LOSS, + SFP47_RX_LOSS, + SFP48_RX_LOSS, + SFP_1_6_RX_LOSS_INT, + SFP_2_6_RX_LOSS_INT, + SFP_3_6_RX_LOSS_INT, + SFP_4_6_RX_LOSS_INT, + SFP_5_6_RX_LOSS_INT, + SFP_6_6_RX_LOSS_INT, + SFP_1_6_RX_LOSS_INT_MASK, + SFP_2_6_RX_LOSS_INT_MASK, + SFP_3_6_RX_LOSS_INT_MASK, + SFP_4_6_RX_LOSS_INT_MASK, + SFP_5_6_RX_LOSS_INT_MASK, + SFP_6_6_RX_LOSS_INT_MASK, + SFP_PRESENT_ALL, + SFP1_PRESENT, + SFP2_PRESENT, + SFP3_PRESENT, + SFP4_PRESENT, + SFP5_PRESENT, + SFP6_PRESENT, + SFP7_PRESENT, + SFP8_PRESENT, + SFP9_PRESENT, + SFP10_PRESENT, + SFP11_PRESENT, + SFP12_PRESENT, + SFP13_PRESENT, + SFP14_PRESENT, + SFP15_PRESENT, + SFP16_PRESENT, + SFP17_PRESENT, + SFP18_PRESENT, + SFP19_PRESENT, + SFP20_PRESENT, + SFP21_PRESENT, + SFP22_PRESENT, + SFP23_PRESENT, + SFP24_PRESENT, + SFP25_PRESENT, + SFP26_PRESENT, + SFP27_PRESENT, + SFP28_PRESENT, + SFP29_PRESENT, + SFP30_PRESENT, + SFP31_PRESENT, + SFP32_PRESENT, + SFP33_PRESENT, + SFP34_PRESENT, + SFP35_PRESENT, + SFP36_PRESENT, + SFP37_PRESENT, + SFP38_PRESENT, + SFP39_PRESENT, + SFP40_PRESENT, + SFP41_PRESENT, + SFP42_PRESENT, + SFP43_PRESENT, + SFP44_PRESENT, + SFP45_PRESENT, + SFP46_PRESENT, + SFP47_PRESENT, + SFP48_PRESENT, + SFP_1_6_PRESENT_INT, + SFP_2_6_PRESENT_INT, + SFP_3_6_PRESENT_INT, + SFP_4_6_PRESENT_INT, + SFP_5_6_PRESENT_INT, + SFP_6_6_PRESENT_INT, + SFP_1_6_PRESENT_INT_MASK, + SFP_2_6_PRESENT_INT_MASK, + SFP_3_6_PRESENT_INT_MASK, + SFP_4_6_PRESENT_INT_MASK, + SFP_5_6_PRESENT_INT_MASK, + SFP_6_6_PRESENT_INT_MASK, QSFP_LOW_POWER_ALL, - QSFP_RESET, - QSFP_PRESENT, + QSFP1_LOW_POWER, + QSFP2_LOW_POWER, + QSFP3_LOW_POWER, + QSFP4_LOW_POWER, + QSFP5_LOW_POWER, + QSFP6_LOW_POWER, + QSFP7_LOW_POWER, + QSFP8_LOW_POWER, + QSFP_RESET_ALL, + QSFP1_RESET, + QSFP2_RESET, + QSFP3_RESET, + QSFP4_RESET, + QSFP5_RESET, + QSFP6_RESET, + QSFP7_RESET, + QSFP8_RESET, + QSFP_PRESENT_ALL, + QSFP1_PRESENT, + QSFP2_PRESENT, + QSFP3_PRESENT, + QSFP4_PRESENT, + QSFP5_PRESENT, + QSFP6_PRESENT, + QSFP7_PRESENT, + QSFP8_PRESENT, + QSFP_INT_ALL, + QSFP1_INT, + QSFP2_INT, + QSFP3_INT, + QSFP4_INT, + QSFP5_INT, + QSFP6_INT, + QSFP7_INT, + QSFP8_INT, QSFP_INT, - FAN_STATUS, - FAN_PRESENT, - FAN_POWER, - FAN_SPEED_RPM, -#ifdef FAN_CTRL_WANTED - FAN_MODE, - FAN_RPM, -#endif -#ifdef ASPEED_BMC_WANTED - BMC_SERSOR_1, - BMC_SERSOR_2, - BMC_SERSOR_3, - BMC_SERSOR_4, - BMC_DETECT, -#endif -#ifdef WDT_CTRL_WANTED - WDT_CTRL, -#endif -#ifdef EEPROM_WP_WANTED - EEPROM_WP_CTRL, -#endif - HW_VER, + QSFP_MODPRS_INT, + QSFP_INT_MASK, + QSFP_MODPRS_MASK }; /* end of struct i2c_sysfs_attributes */ /* sysfs attributes for SENSOR_DEVICE_ATTR */ -/* i2c-0 */ -/*CPLD 0X30*/ -static SENSOR_DEVICE_ATTR(psu_present , S_IRUGO , psu_status_get , NULL , PSU_PRESENT); -static SENSOR_DEVICE_ATTR(psu_status , S_IRUGO , psu_status_get , NULL , PSU_STATUS); -#ifdef PSU_STAT_WANTED -static SENSOR_DEVICE_ATTR(psu_module_1 , S_IRUGO , psu_module_get , NULL , PSU_MODULE_1); -static SENSOR_DEVICE_ATTR(psu_module_2 , S_IRUGO , psu_module_get , NULL , PSU_MODULE_2); -static SENSOR_DEVICE_ATTR(dc_chip_switch , S_IRUGO , dc_chip_switch_get, NULL , DC_CHIP_SWITCH); -#endif -#ifdef USB_CTRL_WANTED -static SENSOR_DEVICE_ATTR(usb_power , S_IRUGO | S_IWUSR , usb_power_get , usb_power_set , USB_POWER); -#endif -#ifdef LED_CTRL_WANTED -static SENSOR_DEVICE_ATTR(led_ctrl , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , LED_CTRL); -#endif -static SENSOR_DEVICE_ATTR(led_sys , S_IRUGO | S_IWUSR , sys_led_ctrl_get , sys_led_ctrl_set , SYS_LED); -static SENSOR_DEVICE_ATTR(led_flow , S_IRUGO | S_IWUSR , sys_led_ctrl_get , sys_led_ctrl_set , FLOW_LED); -static SENSOR_DEVICE_ATTR(led_sw1 , S_IRUGO | S_IWUSR , sys_led_ctrl_get , sys_led_ctrl_set , SW_LED_1); -static SENSOR_DEVICE_ATTR(led_sw2 , S_IRUGO | S_IWUSR , sys_led_ctrl_get , sys_led_ctrl_set , SW_LED_2); -static SENSOR_DEVICE_ATTR(reset_mac , S_IRUGO | S_IWUSR , NULL , reset_mac_set , RESET_MAC); -static SENSOR_DEVICE_ATTR(shutdown_set , S_IRUGO | S_IWUSR , NULL , shutdown_set , SHUTDOWN_DUT); -static SENSOR_DEVICE_ATTR(sensor_status , S_IRUGO , themal_status_get , NULL , SENSOR_STATUS); -#ifdef THEMAL_WANTED -static SENSOR_DEVICE_ATTR(sensor_temp , S_IRUGO , themal_temp_get , NULL , SENSOR_TEMP); -#endif -static SENSOR_DEVICE_ATTR(sensor_int_mask , S_IRUGO , themal_mask_get , NULL , SENSOR_INT_MASK); -static SENSOR_DEVICE_ATTR(sensor_int_mask_1 , S_IRUGO | S_IWUSR , NULL , themal_mask_set , 1); -static SENSOR_DEVICE_ATTR(sensor_int_mask_2 , S_IRUGO | S_IWUSR , NULL , themal_mask_set , 2); -static SENSOR_DEVICE_ATTR(sensor_int_mask_3 , S_IRUGO | S_IWUSR , NULL , themal_mask_set , 3); -static SENSOR_DEVICE_ATTR(sensor_int_mask_4 , S_IRUGO | S_IWUSR , NULL , themal_mask_set , 4); -static SENSOR_DEVICE_ATTR(int_status , S_IRUGO , int_status_get , NULL , INT_STATUS); -/*CPLD 0X31 & 0X32*/ -static SENSOR_DEVICE_ATTR(SFP_present , S_IRUGO , sfp_status_get , NULL , SFP_PRESENT); -static SENSOR_DEVICE_ATTR(SFP_rx_loss , S_IRUGO , sfp_status_get , NULL , SFP_RX_LOSS); -static SENSOR_DEVICE_ATTR(SFP_tx_stat , S_IRUGO , sfp_status_get , NULL , SFP_TX_STAT); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_1 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 1); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_2 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 2); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_3 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 3); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_4 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 4); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_5 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 5); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_6 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 6); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_7 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 7); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_8 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 8); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_9 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 9); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_10 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 10); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_11 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 11); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_12 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 12); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_13 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 13); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_14 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 14); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_15 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 15); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_16 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 16); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_17 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 17); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_18 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 18); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_19 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 19); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_20 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 20); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_21 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 21); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_22 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 22); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_23 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 23); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_24 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 24); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_25 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 25); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_26 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 26); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_27 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 27); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_28 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 28); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_29 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 29); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_30 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 30); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_31 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 31); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_32 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 32); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_33 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 33); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_34 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 34); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_35 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 35); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_36 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 36); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_37 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 37); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_38 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 38); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_39 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 39); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_40 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 40); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_41 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 41); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_42 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 42); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_43 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 43); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_44 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 44); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_45 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 45); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_46 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 46); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_47 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 47); -static SENSOR_DEVICE_ATTR(SFP_tx_ctrl_48 , S_IRUGO | S_IWUSR , NULL , sfp_tx_set , 48); -static SENSOR_DEVICE_ATTR(QSFP_low_power_all, S_IRUGO | S_IWUSR , low_power_all_get , low_power_all_set , QSFP_LOW_POWER_ALL); -static SENSOR_DEVICE_ATTR(QSFP_low_power_1 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 1); -static SENSOR_DEVICE_ATTR(QSFP_low_power_2 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 2); -static SENSOR_DEVICE_ATTR(QSFP_low_power_3 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 3); -static SENSOR_DEVICE_ATTR(QSFP_low_power_4 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 4); -static SENSOR_DEVICE_ATTR(QSFP_low_power_5 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 5); -static SENSOR_DEVICE_ATTR(QSFP_low_power_6 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 6); -static SENSOR_DEVICE_ATTR(QSFP_low_power_7 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 7); -static SENSOR_DEVICE_ATTR(QSFP_low_power_8 , S_IRUGO | S_IWUSR , low_power_get , low_power_set , 8); -static SENSOR_DEVICE_ATTR(QSFP_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , QSFP_RESET); -static SENSOR_DEVICE_ATTR(QSFP_present , S_IRUGO , qsfp_status_get , NULL , QSFP_PRESENT); -static SENSOR_DEVICE_ATTR(QSFP_int , S_IRUGO , qsfp_status_get , NULL , QSFP_INT); -static SENSOR_DEVICE_ATTR(fan_status , S_IRUGO , fan_status_get , NULL , FAN_STATUS); -static SENSOR_DEVICE_ATTR(fan_present , S_IRUGO , fan_status_get , NULL , FAN_PRESENT); -static SENSOR_DEVICE_ATTR(fan_power , S_IRUGO , fan_status_get , NULL , FAN_POWER); -static SENSOR_DEVICE_ATTR(fan_speed_rpm , S_IRUGO , fan_status_get , NULL , FAN_SPEED_RPM); -#ifdef FAN_CTRL_WANTED -static SENSOR_DEVICE_ATTR(fan_mode , S_IRUGO | S_IWUSR , fan_mode_get , fan_mode_set , FAN_MODE); -static SENSOR_DEVICE_ATTR(fan_rpm , S_IRUGO | S_IWUSR , fan_rpm_get , fan_rpm_set , FAN_RPM); -#endif -#ifdef ASPEED_BMC_WANTED -static SENSOR_DEVICE_ATTR(bmc_sersor_1 , S_IRUGO , bmc_register_get , NULL , BMC_SERSOR_1); -static SENSOR_DEVICE_ATTR(bmc_sersor_2 , S_IRUGO , bmc_register_get , NULL , BMC_SERSOR_2); -static SENSOR_DEVICE_ATTR(bmc_sersor_3 , S_IRUGO , bmc_register_get , NULL , BMC_SERSOR_3); -static SENSOR_DEVICE_ATTR(bmc_sersor_4 , S_IRUGO , bmc_register_get , NULL , BMC_SERSOR_4); -static SENSOR_DEVICE_ATTR(bmc_present , S_IRUGO , bmc_module_detect , NULL , BMC_DETECT); -#endif -#ifdef WDT_CTRL_WANTED -static SENSOR_DEVICE_ATTR(wdt_ctrl , S_IRUGO | S_IWUSR , wdt_status_get , wdt_status_set , WDT_CTRL); -#endif -static SENSOR_DEVICE_ATTR(hw_version , S_IRUGO , hw_version_get , NULL , HW_VER); -#ifdef EEPROM_WP_WANTED -static SENSOR_DEVICE_ATTR(eeprom_wp_ctrl , S_IRUGO | S_IWUSR , eeprom_wp_status_get , eeprom_wp_status_set , EEPROM_WP_CTRL); -#endif +static SENSOR_DEVICE_ATTR(cpld_23_ver , S_IRUGO , cpld_hw_ver_get , NULL , 23); +static SENSOR_DEVICE_ATTR(cpld_30_ver , S_IRUGO , cpld_hw_ver_get , NULL , 30); +static SENSOR_DEVICE_ATTR(cpld_31_ver , S_IRUGO , cpld_hw_ver_get , NULL , 31); +static SENSOR_DEVICE_ATTR(cpld_32_ver , S_IRUGO , cpld_hw_ver_get , NULL , 32); +static SENSOR_DEVICE_ATTR(wdt_en , S_IRUGO | S_IWUSR , wdt_enable_get , wdt_enable_set , WDT_EN); +static SENSOR_DEVICE_ATTR(eeprom_wp , S_IRUGO | S_IWUSR , eeprom_wp_get , eeprom_wp_set , EEPROM_WP); +static SENSOR_DEVICE_ATTR(usb_en , S_IRUGO | S_IWUSR , usb_enable_get , usb_enable_set , USB_EN); +static SENSOR_DEVICE_ATTR(shutdown_set , S_IRUGO | S_IWUSR , NULL , shutdown_set , SHUTDOWN_SET); +static SENSOR_DEVICE_ATTR(reset , S_IRUGO | S_IWUSR , NULL , reset_mac_set , RESET); +static SENSOR_DEVICE_ATTR(bmc_present , S_IRUGO , bmc_enable_get , NULL , BMC_PRESENT); +static SENSOR_DEVICE_ATTR(led_1 , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 4); +static SENSOR_DEVICE_ATTR(led_2 , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 3); +static SENSOR_DEVICE_ATTR(led_flow , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 2); +static SENSOR_DEVICE_ATTR(led_sys , S_IRUGO | S_IWUSR , led_ctrl_get , led_ctrl_set , 1); +static SENSOR_DEVICE_ATTR(led_fiber , S_IRUGO | S_IWUSR , led_fiber_get , led_fiber_set , LED_FIBER); +static SENSOR_DEVICE_ATTR(temp_th0_int , S_IRUGO , themal_int_get , NULL , TEMP_TH0_INT); +static SENSOR_DEVICE_ATTR(temp_th1_int , S_IRUGO , themal_int_get , NULL , TEMP_TH1_INT); +static SENSOR_DEVICE_ATTR(temp_th3_int , S_IRUGO , themal_int_get , NULL , TEMP_TH3_INT); +static SENSOR_DEVICE_ATTR(temp_th2_int , S_IRUGO , themal_int_get , NULL , TEMP_TH2_INT); +static SENSOR_DEVICE_ATTR(temp_th0_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_TH0_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_th1_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_TH1_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_th3_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_TH3_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_th2_int_mask , S_IRUGO | S_IWUSR , themal_int_mask_get , themal_int_mask_set , TEMP_TH2_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_fp_int , S_IRUGO , sys_int_get , NULL , CPLD_FP_INT); +static SENSOR_DEVICE_ATTR(cpld_rp_int , S_IRUGO , sys_int_get , NULL , CPLD_RP_INT); +static SENSOR_DEVICE_ATTR(cpld_fan_int , S_IRUGO , sys_int_get , NULL , CPLD_FAN_INT); +static SENSOR_DEVICE_ATTR(cpld_psu_int , S_IRUGO , sys_int_get , NULL , CPLD_PSU_INT); +static SENSOR_DEVICE_ATTR(thermal_int , S_IRUGO , sys_int_get , NULL , THERMAL_INT); +static SENSOR_DEVICE_ATTR(usb_int , S_IRUGO , sys_int_get , NULL , USB_INT); +static SENSOR_DEVICE_ATTR(cpld_fp_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_FP_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_rp_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_RP_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_fan_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_FAN_INT_MASK); +static SENSOR_DEVICE_ATTR(cpld_psu_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , CPLD_PSU_INT_MASK); +static SENSOR_DEVICE_ATTR(thermal_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , THERMAL_INT_MASK); +static SENSOR_DEVICE_ATTR(usb_int_mask , S_IRUGO | S_IWUSR , sys_int_mask_get , sys_int_mask_set , USB_INT_MASK); +static SENSOR_DEVICE_ATTR(temp_th0_t , S_IRUGO , themal_temp_get , NULL , TEMP_TH0_T); +static SENSOR_DEVICE_ATTR(temp_th0_b , S_IRUGO , themal_temp_get , NULL , TEMP_TH0_B); +static SENSOR_DEVICE_ATTR(temp_th0_r , S_IRUGO , themal_temp_get , NULL , TEMP_TH0_R); +static SENSOR_DEVICE_ATTR(temp_th1_t , S_IRUGO , themal_temp_get , NULL , TEMP_TH1_T); +static SENSOR_DEVICE_ATTR(temp_th1_b , S_IRUGO , themal_temp_get , NULL , TEMP_TH1_B); +static SENSOR_DEVICE_ATTR(temp_th3_t , S_IRUGO , themal_temp_get , NULL , TEMP_TH3_T); +static SENSOR_DEVICE_ATTR(temp_th3_b , S_IRUGO , themal_temp_get , NULL , TEMP_TH3_B); +static SENSOR_DEVICE_ATTR(temp_th2_t , S_IRUGO , themal_temp_get , NULL , TEMP_TH2_T); +static SENSOR_DEVICE_ATTR(temp_th2_b , S_IRUGO , themal_temp_get , NULL , TEMP_TH2_B); +static SENSOR_DEVICE_ATTR(temp_th0_t_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH0_T_MAX); +static SENSOR_DEVICE_ATTR(temp_th1_t_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH1_T_MAX); +static SENSOR_DEVICE_ATTR(temp_th3_t_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH3_T_MAX); +static SENSOR_DEVICE_ATTR(temp_th2_t_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH2_T_MAX); +static SENSOR_DEVICE_ATTR(temp_th0_r_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH0_R_MAX); +static SENSOR_DEVICE_ATTR(temp_th0_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH0_B_MAX); +static SENSOR_DEVICE_ATTR(temp_th1_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH1_B_MAX); +static SENSOR_DEVICE_ATTR(temp_th3_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH3_B_MAX); +static SENSOR_DEVICE_ATTR(temp_th2_b_max , S_IRUGO , themal_temp_max_get , NULL , TEMP_TH2_B_MAX); +static SENSOR_DEVICE_ATTR(temp_th0_t_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH0_T_MIN); +static SENSOR_DEVICE_ATTR(temp_th1_t_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH1_T_MIN); +static SENSOR_DEVICE_ATTR(temp_th3_t_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH3_T_MIN); +static SENSOR_DEVICE_ATTR(temp_th2_t_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH2_T_MIN); +static SENSOR_DEVICE_ATTR(temp_th0_r_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH0_R_MIN); +static SENSOR_DEVICE_ATTR(temp_th0_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH0_B_MIN); +static SENSOR_DEVICE_ATTR(temp_th1_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH1_B_MIN); +static SENSOR_DEVICE_ATTR(temp_th3_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH3_B_MIN); +static SENSOR_DEVICE_ATTR(temp_th2_b_min , S_IRUGO , themal_temp_min_get , NULL , TEMP_TH2_B_MIN); +static SENSOR_DEVICE_ATTR(temp_th0_t_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH0_T_CRIT); +static SENSOR_DEVICE_ATTR(temp_th1_t_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH1_T_CRIT); +static SENSOR_DEVICE_ATTR(temp_th3_t_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH3_T_CRIT); +static SENSOR_DEVICE_ATTR(temp_th2_t_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH2_T_CRIT); +static SENSOR_DEVICE_ATTR(temp_th0_r_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH0_R_CRIT); +static SENSOR_DEVICE_ATTR(temp_th0_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH0_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_th1_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH1_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_th3_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH3_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_th2_b_crit , S_IRUGO , themal_temp_crit_get , NULL , TEMP_TH2_B_CRIT); +static SENSOR_DEVICE_ATTR(temp_th0_t_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH0_T_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th1_t_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH1_T_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th3_t_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH3_T_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th2_t_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH2_T_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th0_r_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH0_R_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th0_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH0_B_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th1_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH1_B_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th3_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH3_B_LCRIT); +static SENSOR_DEVICE_ATTR(temp_th2_b_lcrit , S_IRUGO , themal_temp_lcrit_get , NULL , TEMP_TH2_B_LCRIT); +static SENSOR_DEVICE_ATTR(fanctrl_rpm , S_IRUGO , fan_ctrl_rpm_get , NULL , FANCTRL_RPM); +static SENSOR_DEVICE_ATTR(fanctrl_mode , S_IRUGO , fan_ctrl_mode_get , NULL , FANCTRL_MODE); +static SENSOR_DEVICE_ATTR(fan1_stat , S_IRUGO , fan_status_get , NULL , 1); +static SENSOR_DEVICE_ATTR(fan2_stat , S_IRUGO , fan_status_get , NULL , 2); +static SENSOR_DEVICE_ATTR(fan3_stat , S_IRUGO , fan_status_get , NULL , 3); +static SENSOR_DEVICE_ATTR(fan4_stat , S_IRUGO , fan_status_get , NULL , 4); +static SENSOR_DEVICE_ATTR(fan1_present , S_IRUGO , fan_present_get , NULL , 1); +static SENSOR_DEVICE_ATTR(fan2_present , S_IRUGO , fan_present_get , NULL , 2); +static SENSOR_DEVICE_ATTR(fan3_present , S_IRUGO , fan_present_get , NULL , 3); +static SENSOR_DEVICE_ATTR(fan4_present , S_IRUGO , fan_present_get , NULL , 4); +static SENSOR_DEVICE_ATTR(fan1_power , S_IRUGO , fan_power_get , NULL , 1); +static SENSOR_DEVICE_ATTR(fan2_power , S_IRUGO , fan_power_get , NULL , 2); +static SENSOR_DEVICE_ATTR(fan3_power , S_IRUGO , fan_power_get , NULL , 3); +static SENSOR_DEVICE_ATTR(fan4_power , S_IRUGO , fan_power_get , NULL , 4); +static SENSOR_DEVICE_ATTR(fan1_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN1_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan2_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN2_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan3_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN3_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan4_front_rpm , S_IRUGO , fan_rpm_get , NULL , FAN4_FRONT_RPM); +static SENSOR_DEVICE_ATTR(fan1_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN1_REAR_RPM); +static SENSOR_DEVICE_ATTR(fan2_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN2_REAR_RPM); +static SENSOR_DEVICE_ATTR(fan3_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN3_REAR_RPM); +static SENSOR_DEVICE_ATTR(fan4_rear_rpm , S_IRUGO , fan_rpm_get , NULL , FAN4_REAR_RPM); +static SENSOR_DEVICE_ATTR(psu1_good , S_IRUGO , psu_status_get , NULL , 1); +static SENSOR_DEVICE_ATTR(psu2_good , S_IRUGO , psu_status_get , NULL , 2); +static SENSOR_DEVICE_ATTR(psu1_prnt , S_IRUGO , psu_present_get , NULL , 1); +static SENSOR_DEVICE_ATTR(psu2_prnt , S_IRUGO , psu_present_get , NULL , 2); +static SENSOR_DEVICE_ATTR(psu1_vin , S_IRUGO , psu_vin_get , NULL , PSU1_VIN); +static SENSOR_DEVICE_ATTR(psu1_iin , S_IRUGO , psu_iin_get , NULL , PSU1_IIN); +static SENSOR_DEVICE_ATTR(psu1_vout , S_IRUGO , psu_vout_get , NULL , PSU1_VOUT); +static SENSOR_DEVICE_ATTR(psu1_iout , S_IRUGO , psu_iout_get , NULL , PSU1_IOUT); +static SENSOR_DEVICE_ATTR(psu1_temp , S_IRUGO , psu_temp_get , NULL , PSU1_TEMP); +static SENSOR_DEVICE_ATTR(psu1_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU1_FAN_SPEED); +static SENSOR_DEVICE_ATTR(psu1_pout , S_IRUGO , psu_pout_get , NULL , PSU1_POUT); +static SENSOR_DEVICE_ATTR(psu1_pin , S_IRUGO , psu_pin_get , NULL , PSU1_PIN); +static SENSOR_DEVICE_ATTR(psu1_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU1_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu1_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU1_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu1_vmode , S_IRUGO , psu_vmode_get , NULL , PSU1_VMODE); +static SENSOR_DEVICE_ATTR(psu2_vin , S_IRUGO , psu_vin_get , NULL , PSU2_VIN); +static SENSOR_DEVICE_ATTR(psu2_iin , S_IRUGO , psu_iin_get , NULL , PSU2_IIN); +static SENSOR_DEVICE_ATTR(psu2_vout , S_IRUGO , psu_vout_get , NULL , PSU2_VOUT); +static SENSOR_DEVICE_ATTR(psu2_iout , S_IRUGO , psu_iout_get , NULL , PSU2_IOUT); +static SENSOR_DEVICE_ATTR(psu2_temp , S_IRUGO , psu_temp_get , NULL , PSU2_TEMP); +static SENSOR_DEVICE_ATTR(psu2_fan_speed , S_IRUGO , psu_fan_get , NULL , PSU2_FAN_SPEED); +static SENSOR_DEVICE_ATTR(psu2_pout , S_IRUGO , psu_pout_get , NULL , PSU2_POUT); +static SENSOR_DEVICE_ATTR(psu2_pin , S_IRUGO , psu_pin_get , NULL , PSU2_PIN); +static SENSOR_DEVICE_ATTR(psu2_mfr_model , S_IRUGO , psu_mfr_model_get , NULL , PSU2_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu2_mfr_iout_max , S_IRUGO , psu_iout_max_get , NULL , PSU2_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu2_vmode , S_IRUGO , psu_vmode_get , NULL , PSU2_VMODE); +static SENSOR_DEVICE_ATTR(dc6e_p0_vout , S_IRUGO , dc_vout_get , NULL , DC6E_P0_VOUT); +static SENSOR_DEVICE_ATTR(dc6e_p0_iout , S_IRUGO , dc_iout_get , NULL , DC6E_P0_IOUT); +static SENSOR_DEVICE_ATTR(dc6e_p0_pout , S_IRUGO , dc_pout_get , NULL , DC6E_P0_POUT); +static SENSOR_DEVICE_ATTR(dc6e_p1_vout , S_IRUGO , dc_vout_get , NULL , DC6E_P1_VOUT); +static SENSOR_DEVICE_ATTR(dc6e_p1_iout , S_IRUGO , dc_iout_get , NULL , DC6E_P1_IOUT); +static SENSOR_DEVICE_ATTR(dc6e_p1_pout , S_IRUGO , dc_pout_get , NULL , DC6E_P1_POUT); +static SENSOR_DEVICE_ATTR(dc70_p0_vout , S_IRUGO , dc_vout_get , NULL , DC70_P0_VOUT); +static SENSOR_DEVICE_ATTR(dc70_p0_iout , S_IRUGO , dc_iout_get , NULL , DC70_P0_IOUT); +static SENSOR_DEVICE_ATTR(dc70_p0_pout , S_IRUGO , dc_pout_get , NULL , DC70_P0_POUT); +static SENSOR_DEVICE_ATTR(dc70_p1_vout , S_IRUGO , dc_vout_get , NULL , DC70_P1_VOUT); +static SENSOR_DEVICE_ATTR(dc70_p1_iout , S_IRUGO , dc_iout_get , NULL , DC70_P1_IOUT); +static SENSOR_DEVICE_ATTR(dc70_p1_pout , S_IRUGO , dc_pout_get , NULL , DC70_P1_POUT); +static SENSOR_DEVICE_ATTR(sfp_tx_enable_all , S_IRUGO | S_IWUSR , sfp_tx_enable_all_get , sfp_tx_enable_all_set , SFP_TX_ENABLE_ALL); +static SENSOR_DEVICE_ATTR(sfp1_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 1); +static SENSOR_DEVICE_ATTR(sfp2_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 2); +static SENSOR_DEVICE_ATTR(sfp3_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 3); +static SENSOR_DEVICE_ATTR(sfp4_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 4); +static SENSOR_DEVICE_ATTR(sfp5_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 5); +static SENSOR_DEVICE_ATTR(sfp6_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 6); +static SENSOR_DEVICE_ATTR(sfp7_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 7); +static SENSOR_DEVICE_ATTR(sfp8_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 8); +static SENSOR_DEVICE_ATTR(sfp9_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 9); +static SENSOR_DEVICE_ATTR(sfp10_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 10); +static SENSOR_DEVICE_ATTR(sfp11_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 11); +static SENSOR_DEVICE_ATTR(sfp12_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 12); +static SENSOR_DEVICE_ATTR(sfp13_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 13); +static SENSOR_DEVICE_ATTR(sfp14_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 14); +static SENSOR_DEVICE_ATTR(sfp15_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 15); +static SENSOR_DEVICE_ATTR(sfp16_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 16); +static SENSOR_DEVICE_ATTR(sfp17_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 17); +static SENSOR_DEVICE_ATTR(sfp18_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 18); +static SENSOR_DEVICE_ATTR(sfp19_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 19); +static SENSOR_DEVICE_ATTR(sfp20_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 20); +static SENSOR_DEVICE_ATTR(sfp21_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 21); +static SENSOR_DEVICE_ATTR(sfp22_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 22); +static SENSOR_DEVICE_ATTR(sfp23_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 23); +static SENSOR_DEVICE_ATTR(sfp24_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 24); +static SENSOR_DEVICE_ATTR(sfp25_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 25); +static SENSOR_DEVICE_ATTR(sfp26_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 26); +static SENSOR_DEVICE_ATTR(sfp27_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 27); +static SENSOR_DEVICE_ATTR(sfp28_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 28); +static SENSOR_DEVICE_ATTR(sfp29_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 29); +static SENSOR_DEVICE_ATTR(sfp30_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 30); +static SENSOR_DEVICE_ATTR(sfp31_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 31); +static SENSOR_DEVICE_ATTR(sfp32_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 32); +static SENSOR_DEVICE_ATTR(sfp33_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 33); +static SENSOR_DEVICE_ATTR(sfp34_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 34); +static SENSOR_DEVICE_ATTR(sfp35_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 35); +static SENSOR_DEVICE_ATTR(sfp36_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 36); +static SENSOR_DEVICE_ATTR(sfp37_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 37); +static SENSOR_DEVICE_ATTR(sfp38_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 38); +static SENSOR_DEVICE_ATTR(sfp39_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 39); +static SENSOR_DEVICE_ATTR(sfp40_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 40); +static SENSOR_DEVICE_ATTR(sfp41_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 41); +static SENSOR_DEVICE_ATTR(sfp42_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 42); +static SENSOR_DEVICE_ATTR(sfp43_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 43); +static SENSOR_DEVICE_ATTR(sfp44_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 44); +static SENSOR_DEVICE_ATTR(sfp45_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 45); +static SENSOR_DEVICE_ATTR(sfp46_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 46); +static SENSOR_DEVICE_ATTR(sfp47_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 47); +static SENSOR_DEVICE_ATTR(sfp48_tx_enable , S_IRUGO | S_IWUSR , sfp_tx_enable_get , sfp_tx_enable_set , 48); +static SENSOR_DEVICE_ATTR(sfp_rx_loss_all , S_IRUGO , sfp_rx_loss_all_get , NULL , SFP_RX_LOSS_ALL); +static SENSOR_DEVICE_ATTR(sfp1_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 1); +static SENSOR_DEVICE_ATTR(sfp2_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 2); +static SENSOR_DEVICE_ATTR(sfp3_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 3); +static SENSOR_DEVICE_ATTR(sfp4_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 4); +static SENSOR_DEVICE_ATTR(sfp5_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 5); +static SENSOR_DEVICE_ATTR(sfp6_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 6); +static SENSOR_DEVICE_ATTR(sfp7_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 7); +static SENSOR_DEVICE_ATTR(sfp8_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 8); +static SENSOR_DEVICE_ATTR(sfp9_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 9); +static SENSOR_DEVICE_ATTR(sfp10_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 10); +static SENSOR_DEVICE_ATTR(sfp11_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 11); +static SENSOR_DEVICE_ATTR(sfp12_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 12); +static SENSOR_DEVICE_ATTR(sfp13_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 13); +static SENSOR_DEVICE_ATTR(sfp14_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 14); +static SENSOR_DEVICE_ATTR(sfp15_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 15); +static SENSOR_DEVICE_ATTR(sfp16_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 16); +static SENSOR_DEVICE_ATTR(sfp17_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 17); +static SENSOR_DEVICE_ATTR(sfp18_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 18); +static SENSOR_DEVICE_ATTR(sfp19_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 19); +static SENSOR_DEVICE_ATTR(sfp20_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 20); +static SENSOR_DEVICE_ATTR(sfp21_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 21); +static SENSOR_DEVICE_ATTR(sfp22_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 22); +static SENSOR_DEVICE_ATTR(sfp23_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 23); +static SENSOR_DEVICE_ATTR(sfp24_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 24); +static SENSOR_DEVICE_ATTR(sfp25_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 25); +static SENSOR_DEVICE_ATTR(sfp26_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 26); +static SENSOR_DEVICE_ATTR(sfp27_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 27); +static SENSOR_DEVICE_ATTR(sfp28_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 28); +static SENSOR_DEVICE_ATTR(sfp29_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 29); +static SENSOR_DEVICE_ATTR(sfp30_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 30); +static SENSOR_DEVICE_ATTR(sfp31_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 31); +static SENSOR_DEVICE_ATTR(sfp32_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 32); +static SENSOR_DEVICE_ATTR(sfp33_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 33); +static SENSOR_DEVICE_ATTR(sfp34_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 34); +static SENSOR_DEVICE_ATTR(sfp35_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 35); +static SENSOR_DEVICE_ATTR(sfp36_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 36); +static SENSOR_DEVICE_ATTR(sfp37_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 37); +static SENSOR_DEVICE_ATTR(sfp38_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 38); +static SENSOR_DEVICE_ATTR(sfp39_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 39); +static SENSOR_DEVICE_ATTR(sfp40_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 40); +static SENSOR_DEVICE_ATTR(sfp41_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 41); +static SENSOR_DEVICE_ATTR(sfp42_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 42); +static SENSOR_DEVICE_ATTR(sfp43_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 43); +static SENSOR_DEVICE_ATTR(sfp44_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 44); +static SENSOR_DEVICE_ATTR(sfp45_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 45); +static SENSOR_DEVICE_ATTR(sfp46_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 46); +static SENSOR_DEVICE_ATTR(sfp47_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 47); +static SENSOR_DEVICE_ATTR(sfp48_rx_loss , S_IRUGO , sfp_rx_loss_get , NULL , 48); +static SENSOR_DEVICE_ATTR(sfp_1_6_rx_loss_int , S_IRUGO , sfp_rx_loss_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(sfp_2_6_rx_loss_int , S_IRUGO , sfp_rx_loss_int_get , NULL , 2); +static SENSOR_DEVICE_ATTR(sfp_3_6_rx_loss_int , S_IRUGO , sfp_rx_loss_int_get , NULL , 3); +static SENSOR_DEVICE_ATTR(sfp_4_6_rx_loss_int , S_IRUGO , sfp_rx_loss_int_get , NULL , 4); +static SENSOR_DEVICE_ATTR(sfp_5_6_rx_loss_int , S_IRUGO , sfp_rx_loss_int_get , NULL , 5); +static SENSOR_DEVICE_ATTR(sfp_6_6_rx_loss_int , S_IRUGO , sfp_rx_loss_int_get , NULL , 6); +static SENSOR_DEVICE_ATTR(sfp_1_6_rx_loss_int_mask, S_IRUGO | S_IWUSR , sfp_rx_loss_int_mask_get , sfp_rx_loss_int_mask_set , 1); +static SENSOR_DEVICE_ATTR(sfp_2_6_rx_loss_int_mask, S_IRUGO | S_IWUSR , sfp_rx_loss_int_mask_get , sfp_rx_loss_int_mask_set , 2); +static SENSOR_DEVICE_ATTR(sfp_3_6_rx_loss_int_mask, S_IRUGO | S_IWUSR , sfp_rx_loss_int_mask_get , sfp_rx_loss_int_mask_set , 3); +static SENSOR_DEVICE_ATTR(sfp_4_6_rx_loss_int_mask, S_IRUGO | S_IWUSR , sfp_rx_loss_int_mask_get , sfp_rx_loss_int_mask_set , 4); +static SENSOR_DEVICE_ATTR(sfp_5_6_rx_loss_int_mask, S_IRUGO | S_IWUSR , sfp_rx_loss_int_mask_get , sfp_rx_loss_int_mask_set , 5); +static SENSOR_DEVICE_ATTR(sfp_6_6_rx_loss_int_mask, S_IRUGO | S_IWUSR , sfp_rx_loss_int_mask_get , sfp_rx_loss_int_mask_set , 6); +static SENSOR_DEVICE_ATTR(sfp_present_all , S_IRUGO , sfp_present_all_get , NULL , SFP_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp1_present , S_IRUGO , sfp_present_get , NULL , 1); +static SENSOR_DEVICE_ATTR(sfp2_present , S_IRUGO , sfp_present_get , NULL , 2); +static SENSOR_DEVICE_ATTR(sfp3_present , S_IRUGO , sfp_present_get , NULL , 3); +static SENSOR_DEVICE_ATTR(sfp4_present , S_IRUGO , sfp_present_get , NULL , 4); +static SENSOR_DEVICE_ATTR(sfp5_present , S_IRUGO , sfp_present_get , NULL , 5); +static SENSOR_DEVICE_ATTR(sfp6_present , S_IRUGO , sfp_present_get , NULL , 6); +static SENSOR_DEVICE_ATTR(sfp7_present , S_IRUGO , sfp_present_get , NULL , 7); +static SENSOR_DEVICE_ATTR(sfp8_present , S_IRUGO , sfp_present_get , NULL , 8); +static SENSOR_DEVICE_ATTR(sfp9_present , S_IRUGO , sfp_present_get , NULL , 9); +static SENSOR_DEVICE_ATTR(sfp10_present , S_IRUGO , sfp_present_get , NULL , 10); +static SENSOR_DEVICE_ATTR(sfp11_present , S_IRUGO , sfp_present_get , NULL , 11); +static SENSOR_DEVICE_ATTR(sfp12_present , S_IRUGO , sfp_present_get , NULL , 12); +static SENSOR_DEVICE_ATTR(sfp13_present , S_IRUGO , sfp_present_get , NULL , 13); +static SENSOR_DEVICE_ATTR(sfp14_present , S_IRUGO , sfp_present_get , NULL , 14); +static SENSOR_DEVICE_ATTR(sfp15_present , S_IRUGO , sfp_present_get , NULL , 15); +static SENSOR_DEVICE_ATTR(sfp16_present , S_IRUGO , sfp_present_get , NULL , 16); +static SENSOR_DEVICE_ATTR(sfp17_present , S_IRUGO , sfp_present_get , NULL , 17); +static SENSOR_DEVICE_ATTR(sfp18_present , S_IRUGO , sfp_present_get , NULL , 18); +static SENSOR_DEVICE_ATTR(sfp19_present , S_IRUGO , sfp_present_get , NULL , 19); +static SENSOR_DEVICE_ATTR(sfp20_present , S_IRUGO , sfp_present_get , NULL , 20); +static SENSOR_DEVICE_ATTR(sfp21_present , S_IRUGO , sfp_present_get , NULL , 21); +static SENSOR_DEVICE_ATTR(sfp22_present , S_IRUGO , sfp_present_get , NULL , 22); +static SENSOR_DEVICE_ATTR(sfp23_present , S_IRUGO , sfp_present_get , NULL , 23); +static SENSOR_DEVICE_ATTR(sfp24_present , S_IRUGO , sfp_present_get , NULL , 24); +static SENSOR_DEVICE_ATTR(sfp25_present , S_IRUGO , sfp_present_get , NULL , 25); +static SENSOR_DEVICE_ATTR(sfp26_present , S_IRUGO , sfp_present_get , NULL , 26); +static SENSOR_DEVICE_ATTR(sfp27_present , S_IRUGO , sfp_present_get , NULL , 27); +static SENSOR_DEVICE_ATTR(sfp28_present , S_IRUGO , sfp_present_get , NULL , 28); +static SENSOR_DEVICE_ATTR(sfp29_present , S_IRUGO , sfp_present_get , NULL , 29); +static SENSOR_DEVICE_ATTR(sfp30_present , S_IRUGO , sfp_present_get , NULL , 30); +static SENSOR_DEVICE_ATTR(sfp31_present , S_IRUGO , sfp_present_get , NULL , 31); +static SENSOR_DEVICE_ATTR(sfp32_present , S_IRUGO , sfp_present_get , NULL , 32); +static SENSOR_DEVICE_ATTR(sfp33_present , S_IRUGO , sfp_present_get , NULL , 33); +static SENSOR_DEVICE_ATTR(sfp34_present , S_IRUGO , sfp_present_get , NULL , 34); +static SENSOR_DEVICE_ATTR(sfp35_present , S_IRUGO , sfp_present_get , NULL , 35); +static SENSOR_DEVICE_ATTR(sfp36_present , S_IRUGO , sfp_present_get , NULL , 36); +static SENSOR_DEVICE_ATTR(sfp37_present , S_IRUGO , sfp_present_get , NULL , 37); +static SENSOR_DEVICE_ATTR(sfp38_present , S_IRUGO , sfp_present_get , NULL , 38); +static SENSOR_DEVICE_ATTR(sfp39_present , S_IRUGO , sfp_present_get , NULL , 39); +static SENSOR_DEVICE_ATTR(sfp40_present , S_IRUGO , sfp_present_get , NULL , 40); +static SENSOR_DEVICE_ATTR(sfp41_present , S_IRUGO , sfp_present_get , NULL , 41); +static SENSOR_DEVICE_ATTR(sfp42_present , S_IRUGO , sfp_present_get , NULL , 42); +static SENSOR_DEVICE_ATTR(sfp43_present , S_IRUGO , sfp_present_get , NULL , 43); +static SENSOR_DEVICE_ATTR(sfp44_present , S_IRUGO , sfp_present_get , NULL , 44); +static SENSOR_DEVICE_ATTR(sfp45_present , S_IRUGO , sfp_present_get , NULL , 45); +static SENSOR_DEVICE_ATTR(sfp46_present , S_IRUGO , sfp_present_get , NULL , 46); +static SENSOR_DEVICE_ATTR(sfp47_present , S_IRUGO , sfp_present_get , NULL , 47); +static SENSOR_DEVICE_ATTR(sfp48_present , S_IRUGO , sfp_present_get , NULL , 48); +static SENSOR_DEVICE_ATTR(sfp_1_6_present_int , S_IRUGO , sfp_present_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(sfp_2_6_present_int , S_IRUGO , sfp_present_int_get , NULL , 2); +static SENSOR_DEVICE_ATTR(sfp_3_6_present_int , S_IRUGO , sfp_present_int_get , NULL , 3); +static SENSOR_DEVICE_ATTR(sfp_4_6_present_int , S_IRUGO , sfp_present_int_get , NULL , 4); +static SENSOR_DEVICE_ATTR(sfp_5_6_present_int , S_IRUGO , sfp_present_int_get , NULL , 5); +static SENSOR_DEVICE_ATTR(sfp_6_6_present_int , S_IRUGO , sfp_present_int_get , NULL , 6); +static SENSOR_DEVICE_ATTR(sfp_1_6_present_int_mask, S_IRUGO | S_IWUSR , sfp_present_int_mask_get , sfp_present_int_mask_set , 1); +static SENSOR_DEVICE_ATTR(sfp_2_6_present_int_mask, S_IRUGO | S_IWUSR , sfp_present_int_mask_get , sfp_present_int_mask_set , 2); +static SENSOR_DEVICE_ATTR(sfp_3_6_present_int_mask, S_IRUGO | S_IWUSR , sfp_present_int_mask_get , sfp_present_int_mask_set , 3); +static SENSOR_DEVICE_ATTR(sfp_4_6_present_int_mask, S_IRUGO | S_IWUSR , sfp_present_int_mask_get , sfp_present_int_mask_set , 4); +static SENSOR_DEVICE_ATTR(sfp_5_6_present_int_mask, S_IRUGO | S_IWUSR , sfp_present_int_mask_get , sfp_present_int_mask_set , 5); +static SENSOR_DEVICE_ATTR(sfp_6_6_present_int_mask, S_IRUGO | S_IWUSR , sfp_present_int_mask_get , sfp_present_int_mask_set , 6); +static SENSOR_DEVICE_ATTR(qsfp_low_power_all , S_IRUGO | S_IWUSR , qsfp_low_power_all_get , qsfp_low_power_all_set , QSFP_LOW_POWER_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 1); +static SENSOR_DEVICE_ATTR(qsfp2_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 2); +static SENSOR_DEVICE_ATTR(qsfp3_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 3); +static SENSOR_DEVICE_ATTR(qsfp4_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 4); +static SENSOR_DEVICE_ATTR(qsfp5_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 5); +static SENSOR_DEVICE_ATTR(qsfp6_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 6); +static SENSOR_DEVICE_ATTR(qsfp7_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 7); +static SENSOR_DEVICE_ATTR(qsfp8_low_power , S_IRUGO | S_IWUSR , qsfp_low_power_get , qsfp_low_power_set , 8); +static SENSOR_DEVICE_ATTR(qsfp_reset_all , S_IRUGO | S_IWUSR , NULL , qsfp_reset_all_set , QSFP_RESET_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 1); +static SENSOR_DEVICE_ATTR(qsfp2_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 2); +static SENSOR_DEVICE_ATTR(qsfp3_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 3); +static SENSOR_DEVICE_ATTR(qsfp4_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 4); +static SENSOR_DEVICE_ATTR(qsfp5_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 5); +static SENSOR_DEVICE_ATTR(qsfp6_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 6); +static SENSOR_DEVICE_ATTR(qsfp7_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 7); +static SENSOR_DEVICE_ATTR(qsfp8_reset , S_IRUGO | S_IWUSR , NULL , qsfp_reset_set , 8); +static SENSOR_DEVICE_ATTR(qsfp_present_all , S_IRUGO , qsfp_present_all_get , NULL , QSFP_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_present , S_IRUGO , qsfp_present_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp2_present , S_IRUGO , qsfp_present_get , NULL , 2); +static SENSOR_DEVICE_ATTR(qsfp3_present , S_IRUGO , qsfp_present_get , NULL , 3); +static SENSOR_DEVICE_ATTR(qsfp4_present , S_IRUGO , qsfp_present_get , NULL , 4); +static SENSOR_DEVICE_ATTR(qsfp5_present , S_IRUGO , qsfp_present_get , NULL , 5); +static SENSOR_DEVICE_ATTR(qsfp6_present , S_IRUGO , qsfp_present_get , NULL , 6); +static SENSOR_DEVICE_ATTR(qsfp7_present , S_IRUGO , qsfp_present_get , NULL , 7); +static SENSOR_DEVICE_ATTR(qsfp8_present , S_IRUGO , qsfp_present_get , NULL , 8); +static SENSOR_DEVICE_ATTR(qsfp_int_all , S_IRUGO , qsfp_int_all_get , NULL , QSFP_INT_ALL); +static SENSOR_DEVICE_ATTR(qsfp1_int , S_IRUGO , qsfp_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp2_int , S_IRUGO , qsfp_int_get , NULL , 2); +static SENSOR_DEVICE_ATTR(qsfp3_int , S_IRUGO , qsfp_int_get , NULL , 3); +static SENSOR_DEVICE_ATTR(qsfp4_int , S_IRUGO , qsfp_int_get , NULL , 4); +static SENSOR_DEVICE_ATTR(qsfp5_int , S_IRUGO , qsfp_int_get , NULL , 5); +static SENSOR_DEVICE_ATTR(qsfp6_int , S_IRUGO , qsfp_int_get , NULL , 6); +static SENSOR_DEVICE_ATTR(qsfp7_int , S_IRUGO , qsfp_int_get , NULL , 7); +static SENSOR_DEVICE_ATTR(qsfp8_int , S_IRUGO , qsfp_int_get , NULL , 8); +static SENSOR_DEVICE_ATTR(qsfp_int , S_IRUGO , qsfp_quter_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp_modprs_int , S_IRUGO , qsfp_modprs_int_get , NULL , 1); +static SENSOR_DEVICE_ATTR(qsfp_int_mask , S_IRUGO | S_IWUSR , qsfp_quter_int_mask_get , qsfp_quter_int_mask_set , 1); +static SENSOR_DEVICE_ATTR(qsfp_modprs_mask , S_IRUGO | S_IWUSR , qsfp_modprs_int_mask_get , qsfp_modprs_int_mask_set , 1); /* end of sysfs attributes for SENSOR_DEVICE_ATTR */ /* sysfs attributes for hwmon */ /* i2c-0 */ static struct attribute *ESQC610_SYS_attributes[] = { - &sensor_dev_attr_hw_version.dev_attr.attr, -#ifdef WDT_CTRL_WANTED - &sensor_dev_attr_wdt_ctrl.dev_attr.attr, -#endif -#ifdef EEPROM_WP_WANTED - &sensor_dev_attr_eeprom_wp_ctrl.dev_attr.attr, -#endif + &sensor_dev_attr_cpld_23_ver.dev_attr.attr, + &sensor_dev_attr_cpld_30_ver.dev_attr.attr, + &sensor_dev_attr_cpld_31_ver.dev_attr.attr, + &sensor_dev_attr_cpld_32_ver.dev_attr.attr, + &sensor_dev_attr_wdt_en.dev_attr.attr, + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_usb_en.dev_attr.attr, + &sensor_dev_attr_shutdown_set.dev_attr.attr, + &sensor_dev_attr_reset.dev_attr.attr, + &sensor_dev_attr_bmc_present.dev_attr.attr, + &sensor_dev_attr_cpld_fp_int.dev_attr.attr, + &sensor_dev_attr_cpld_rp_int.dev_attr.attr, + &sensor_dev_attr_cpld_fan_int.dev_attr.attr, + &sensor_dev_attr_cpld_psu_int.dev_attr.attr, + &sensor_dev_attr_thermal_int.dev_attr.attr, + &sensor_dev_attr_usb_int.dev_attr.attr, + &sensor_dev_attr_cpld_fp_int_mask.dev_attr.attr, + &sensor_dev_attr_cpld_rp_int_mask.dev_attr.attr, + &sensor_dev_attr_cpld_fan_int_mask.dev_attr.attr, + &sensor_dev_attr_cpld_psu_int_mask.dev_attr.attr, + &sensor_dev_attr_thermal_int_mask.dev_attr.attr, + &sensor_dev_attr_usb_int_mask.dev_attr.attr, NULL }; - -static struct attribute *ESQC610_PSU_attributes[] = -{ - &sensor_dev_attr_psu_present.dev_attr.attr, - &sensor_dev_attr_psu_status.dev_attr.attr, -#ifdef PSU_STAT_WANTED - &sensor_dev_attr_psu_module_1.dev_attr.attr, - &sensor_dev_attr_psu_module_2.dev_attr.attr, - &sensor_dev_attr_dc_chip_switch.dev_attr.attr, -#endif - NULL -}; -#ifdef USB_CTRL_WANTED -static struct attribute *ESQC610_USB_attributes[] = -{ - &sensor_dev_attr_usb_power.dev_attr.attr, - NULL -}; -#endif static struct attribute *ESQC610_LED_attributes[] = { -#ifdef LED_CTRL_WANTED - &sensor_dev_attr_led_ctrl.dev_attr.attr, -#endif - &sensor_dev_attr_led_sys.dev_attr.attr, + &sensor_dev_attr_led_1.dev_attr.attr, + &sensor_dev_attr_led_2.dev_attr.attr, &sensor_dev_attr_led_flow.dev_attr.attr, - &sensor_dev_attr_led_sw1.dev_attr.attr, - &sensor_dev_attr_led_sw2.dev_attr.attr, + &sensor_dev_attr_led_sys.dev_attr.attr, + &sensor_dev_attr_led_fiber.dev_attr.attr, NULL }; - -static struct attribute *ESQC610_Reset_attributes[] = +static struct attribute *ESQC610_THERMAL_attributes[] = { - &sensor_dev_attr_reset_mac.dev_attr.attr, - &sensor_dev_attr_shutdown_set.dev_attr.attr, + &sensor_dev_attr_temp_th0_t.dev_attr.attr, + &sensor_dev_attr_temp_th0_b.dev_attr.attr, + &sensor_dev_attr_temp_th0_r.dev_attr.attr, + &sensor_dev_attr_temp_th1_t.dev_attr.attr, + &sensor_dev_attr_temp_th1_b.dev_attr.attr, + &sensor_dev_attr_temp_th3_t.dev_attr.attr, + &sensor_dev_attr_temp_th3_b.dev_attr.attr, + &sensor_dev_attr_temp_th2_t.dev_attr.attr, + &sensor_dev_attr_temp_th2_b.dev_attr.attr, + &sensor_dev_attr_temp_th0_int.dev_attr.attr, + &sensor_dev_attr_temp_th1_int.dev_attr.attr, + &sensor_dev_attr_temp_th3_int.dev_attr.attr, + &sensor_dev_attr_temp_th2_int.dev_attr.attr, + &sensor_dev_attr_temp_th0_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_th1_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_th3_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_th2_int_mask.dev_attr.attr, + &sensor_dev_attr_temp_th0_t_max.dev_attr.attr, + &sensor_dev_attr_temp_th0_t_min.dev_attr.attr, + &sensor_dev_attr_temp_th0_t_crit.dev_attr.attr, + &sensor_dev_attr_temp_th0_t_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th0_b_max.dev_attr.attr, + &sensor_dev_attr_temp_th0_b_min.dev_attr.attr, + &sensor_dev_attr_temp_th0_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_th0_b_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th0_r_max.dev_attr.attr, + &sensor_dev_attr_temp_th0_r_min.dev_attr.attr, + &sensor_dev_attr_temp_th0_r_crit.dev_attr.attr, + &sensor_dev_attr_temp_th0_r_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th1_t_max.dev_attr.attr, + &sensor_dev_attr_temp_th1_t_min.dev_attr.attr, + &sensor_dev_attr_temp_th1_t_crit.dev_attr.attr, + &sensor_dev_attr_temp_th1_t_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th1_b_max.dev_attr.attr, + &sensor_dev_attr_temp_th1_b_min.dev_attr.attr, + &sensor_dev_attr_temp_th1_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_th1_b_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th3_t_max.dev_attr.attr, + &sensor_dev_attr_temp_th3_t_min.dev_attr.attr, + &sensor_dev_attr_temp_th3_t_crit.dev_attr.attr, + &sensor_dev_attr_temp_th3_t_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th3_b_max.dev_attr.attr, + &sensor_dev_attr_temp_th3_b_min.dev_attr.attr, + &sensor_dev_attr_temp_th3_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_th3_b_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th2_t_max.dev_attr.attr, + &sensor_dev_attr_temp_th2_t_min.dev_attr.attr, + &sensor_dev_attr_temp_th2_t_crit.dev_attr.attr, + &sensor_dev_attr_temp_th2_t_lcrit.dev_attr.attr, + &sensor_dev_attr_temp_th2_b_max.dev_attr.attr, + &sensor_dev_attr_temp_th2_b_min.dev_attr.attr, + &sensor_dev_attr_temp_th2_b_crit.dev_attr.attr, + &sensor_dev_attr_temp_th2_b_lcrit.dev_attr.attr, NULL }; - -static struct attribute *ESQC610_Sensor_attributes[] = +static struct attribute *ESQC610_FAN_attributes[] = { - &sensor_dev_attr_sensor_status.dev_attr.attr, -#ifdef THEMAL_WANTED - &sensor_dev_attr_sensor_temp.dev_attr.attr, -#endif + &sensor_dev_attr_fanctrl_rpm.dev_attr.attr, + &sensor_dev_attr_fanctrl_mode.dev_attr.attr, + &sensor_dev_attr_fan1_stat.dev_attr.attr, + &sensor_dev_attr_fan2_stat.dev_attr.attr, + &sensor_dev_attr_fan3_stat.dev_attr.attr, + &sensor_dev_attr_fan4_stat.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan1_power.dev_attr.attr, + &sensor_dev_attr_fan2_power.dev_attr.attr, + &sensor_dev_attr_fan3_power.dev_attr.attr, + &sensor_dev_attr_fan4_power.dev_attr.attr, + &sensor_dev_attr_fan1_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_front_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_rear_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rear_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rear_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rear_rpm.dev_attr.attr, NULL }; - -static struct attribute *ESQC610_INT_attributes[] = +static struct attribute *ESQC610_POWER_attributes[] = { - &sensor_dev_attr_int_status.dev_attr.attr, - &sensor_dev_attr_QSFP_int.dev_attr.attr, - &sensor_dev_attr_sensor_int_mask.dev_attr.attr, - &sensor_dev_attr_sensor_int_mask_1.dev_attr.attr, - &sensor_dev_attr_sensor_int_mask_2.dev_attr.attr, - &sensor_dev_attr_sensor_int_mask_3.dev_attr.attr, - &sensor_dev_attr_sensor_int_mask_4.dev_attr.attr, + &sensor_dev_attr_psu1_good.dev_attr.attr, + &sensor_dev_attr_psu2_good.dev_attr.attr, + &sensor_dev_attr_psu1_prnt.dev_attr.attr, + &sensor_dev_attr_psu2_prnt.dev_attr.attr, + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu1_temp.dev_attr.attr, + &sensor_dev_attr_psu1_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu1_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu1_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu1_vmode.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu2_temp.dev_attr.attr, + &sensor_dev_attr_psu2_fan_speed.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu2_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu2_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu2_vmode.dev_attr.attr, + &sensor_dev_attr_dc6e_p0_vout.dev_attr.attr, + &sensor_dev_attr_dc6e_p0_iout.dev_attr.attr, + &sensor_dev_attr_dc6e_p0_pout.dev_attr.attr, + &sensor_dev_attr_dc6e_p1_vout.dev_attr.attr, + &sensor_dev_attr_dc6e_p1_iout.dev_attr.attr, + &sensor_dev_attr_dc6e_p1_pout.dev_attr.attr, + &sensor_dev_attr_dc70_p0_vout.dev_attr.attr, + &sensor_dev_attr_dc70_p0_iout.dev_attr.attr, + &sensor_dev_attr_dc70_p0_pout.dev_attr.attr, + &sensor_dev_attr_dc70_p1_vout.dev_attr.attr, + &sensor_dev_attr_dc70_p1_iout.dev_attr.attr, + &sensor_dev_attr_dc70_p1_pout.dev_attr.attr, NULL }; - static struct attribute *ESQC610_SFP_attributes[] = { - &sensor_dev_attr_SFP_present.dev_attr.attr, - &sensor_dev_attr_SFP_rx_loss.dev_attr.attr, - &sensor_dev_attr_SFP_tx_stat.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_1.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_2.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_3.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_4.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_5.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_6.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_7.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_8.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_9.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_10.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_11.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_12.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_13.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_14.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_15.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_16.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_17.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_18.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_19.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_20.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_21.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_22.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_23.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_24.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_25.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_26.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_27.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_28.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_29.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_30.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_31.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_32.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_33.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_34.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_35.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_36.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_37.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_38.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_39.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_40.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_41.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_42.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_43.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_44.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_45.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_46.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_47.dev_attr.attr, - &sensor_dev_attr_SFP_tx_ctrl_48.dev_attr.attr, + &sensor_dev_attr_sfp_tx_enable_all.dev_attr.attr, + &sensor_dev_attr_sfp1_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp2_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp3_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp4_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp5_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp6_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp7_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp8_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp9_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp10_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp11_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp12_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp13_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp14_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp15_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp16_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp17_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp18_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp19_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp20_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp21_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp22_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp23_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp24_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp25_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp26_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp27_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp28_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp29_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp30_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp31_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp32_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp33_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp34_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp35_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp36_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp37_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp38_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp39_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp40_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp41_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp42_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp43_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp44_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp45_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp46_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp47_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp48_tx_enable.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss_all.dev_attr.attr, + &sensor_dev_attr_sfp1_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp2_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp3_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp4_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp5_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp6_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp7_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp8_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp9_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp10_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp11_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp12_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp13_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp14_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp15_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp16_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp17_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp18_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp19_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp20_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp21_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp22_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp23_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp24_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp25_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp26_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp27_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp28_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp29_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp30_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp31_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp32_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp33_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp34_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp35_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp36_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp37_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp38_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp39_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp40_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp41_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp42_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp43_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp44_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp45_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp46_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp47_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp48_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp_present_all.dev_attr.attr, + &sensor_dev_attr_sfp1_present.dev_attr.attr, + &sensor_dev_attr_sfp2_present.dev_attr.attr, + &sensor_dev_attr_sfp3_present.dev_attr.attr, + &sensor_dev_attr_sfp4_present.dev_attr.attr, + &sensor_dev_attr_sfp5_present.dev_attr.attr, + &sensor_dev_attr_sfp6_present.dev_attr.attr, + &sensor_dev_attr_sfp7_present.dev_attr.attr, + &sensor_dev_attr_sfp8_present.dev_attr.attr, + &sensor_dev_attr_sfp9_present.dev_attr.attr, + &sensor_dev_attr_sfp10_present.dev_attr.attr, + &sensor_dev_attr_sfp11_present.dev_attr.attr, + &sensor_dev_attr_sfp12_present.dev_attr.attr, + &sensor_dev_attr_sfp13_present.dev_attr.attr, + &sensor_dev_attr_sfp14_present.dev_attr.attr, + &sensor_dev_attr_sfp15_present.dev_attr.attr, + &sensor_dev_attr_sfp16_present.dev_attr.attr, + &sensor_dev_attr_sfp17_present.dev_attr.attr, + &sensor_dev_attr_sfp18_present.dev_attr.attr, + &sensor_dev_attr_sfp19_present.dev_attr.attr, + &sensor_dev_attr_sfp20_present.dev_attr.attr, + &sensor_dev_attr_sfp21_present.dev_attr.attr, + &sensor_dev_attr_sfp22_present.dev_attr.attr, + &sensor_dev_attr_sfp23_present.dev_attr.attr, + &sensor_dev_attr_sfp24_present.dev_attr.attr, + &sensor_dev_attr_sfp25_present.dev_attr.attr, + &sensor_dev_attr_sfp26_present.dev_attr.attr, + &sensor_dev_attr_sfp27_present.dev_attr.attr, + &sensor_dev_attr_sfp28_present.dev_attr.attr, + &sensor_dev_attr_sfp29_present.dev_attr.attr, + &sensor_dev_attr_sfp30_present.dev_attr.attr, + &sensor_dev_attr_sfp31_present.dev_attr.attr, + &sensor_dev_attr_sfp32_present.dev_attr.attr, + &sensor_dev_attr_sfp33_present.dev_attr.attr, + &sensor_dev_attr_sfp34_present.dev_attr.attr, + &sensor_dev_attr_sfp35_present.dev_attr.attr, + &sensor_dev_attr_sfp36_present.dev_attr.attr, + &sensor_dev_attr_sfp37_present.dev_attr.attr, + &sensor_dev_attr_sfp38_present.dev_attr.attr, + &sensor_dev_attr_sfp39_present.dev_attr.attr, + &sensor_dev_attr_sfp40_present.dev_attr.attr, + &sensor_dev_attr_sfp41_present.dev_attr.attr, + &sensor_dev_attr_sfp42_present.dev_attr.attr, + &sensor_dev_attr_sfp43_present.dev_attr.attr, + &sensor_dev_attr_sfp44_present.dev_attr.attr, + &sensor_dev_attr_sfp45_present.dev_attr.attr, + &sensor_dev_attr_sfp46_present.dev_attr.attr, + &sensor_dev_attr_sfp47_present.dev_attr.attr, + &sensor_dev_attr_sfp48_present.dev_attr.attr, + &sensor_dev_attr_sfp_1_6_rx_loss_int.dev_attr.attr, + &sensor_dev_attr_sfp_2_6_rx_loss_int.dev_attr.attr, + &sensor_dev_attr_sfp_3_6_rx_loss_int.dev_attr.attr, + &sensor_dev_attr_sfp_4_6_rx_loss_int.dev_attr.attr, + &sensor_dev_attr_sfp_5_6_rx_loss_int.dev_attr.attr, + &sensor_dev_attr_sfp_6_6_rx_loss_int.dev_attr.attr, + &sensor_dev_attr_sfp_1_6_rx_loss_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_2_6_rx_loss_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_3_6_rx_loss_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_4_6_rx_loss_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_5_6_rx_loss_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_6_6_rx_loss_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_1_6_present_int.dev_attr.attr, + &sensor_dev_attr_sfp_2_6_present_int.dev_attr.attr, + &sensor_dev_attr_sfp_3_6_present_int.dev_attr.attr, + &sensor_dev_attr_sfp_4_6_present_int.dev_attr.attr, + &sensor_dev_attr_sfp_5_6_present_int.dev_attr.attr, + &sensor_dev_attr_sfp_6_6_present_int.dev_attr.attr, + &sensor_dev_attr_sfp_1_6_present_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_2_6_present_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_3_6_present_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_4_6_present_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_5_6_present_int_mask.dev_attr.attr, + &sensor_dev_attr_sfp_6_6_present_int_mask.dev_attr.attr, NULL }; - static struct attribute *ESQC610_QSFP_attributes[] = { - &sensor_dev_attr_QSFP_present.dev_attr.attr, - &sensor_dev_attr_QSFP_reset.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_all.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_1.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_2.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_3.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_4.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_5.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_6.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_7.dev_attr.attr, - &sensor_dev_attr_QSFP_low_power_8.dev_attr.attr, + &sensor_dev_attr_qsfp_low_power_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp2_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp3_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp4_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp5_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp6_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp7_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp8_low_power.dev_attr.attr, + &sensor_dev_attr_qsfp_reset_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_reset.dev_attr.attr, + &sensor_dev_attr_qsfp2_reset.dev_attr.attr, + &sensor_dev_attr_qsfp3_reset.dev_attr.attr, + &sensor_dev_attr_qsfp4_reset.dev_attr.attr, + &sensor_dev_attr_qsfp5_reset.dev_attr.attr, + &sensor_dev_attr_qsfp6_reset.dev_attr.attr, + &sensor_dev_attr_qsfp7_reset.dev_attr.attr, + &sensor_dev_attr_qsfp8_reset.dev_attr.attr, + &sensor_dev_attr_qsfp_present_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_present.dev_attr.attr, + &sensor_dev_attr_qsfp2_present.dev_attr.attr, + &sensor_dev_attr_qsfp3_present.dev_attr.attr, + &sensor_dev_attr_qsfp4_present.dev_attr.attr, + &sensor_dev_attr_qsfp5_present.dev_attr.attr, + &sensor_dev_attr_qsfp6_present.dev_attr.attr, + &sensor_dev_attr_qsfp7_present.dev_attr.attr, + &sensor_dev_attr_qsfp8_present.dev_attr.attr, + &sensor_dev_attr_qsfp_int_all.dev_attr.attr, + &sensor_dev_attr_qsfp1_int.dev_attr.attr, + &sensor_dev_attr_qsfp2_int.dev_attr.attr, + &sensor_dev_attr_qsfp3_int.dev_attr.attr, + &sensor_dev_attr_qsfp4_int.dev_attr.attr, + &sensor_dev_attr_qsfp5_int.dev_attr.attr, + &sensor_dev_attr_qsfp6_int.dev_attr.attr, + &sensor_dev_attr_qsfp7_int.dev_attr.attr, + &sensor_dev_attr_qsfp8_int.dev_attr.attr, + &sensor_dev_attr_qsfp_int.dev_attr.attr, + &sensor_dev_attr_qsfp_modprs_int.dev_attr.attr, + &sensor_dev_attr_qsfp_int_mask.dev_attr.attr, + &sensor_dev_attr_qsfp_modprs_mask.dev_attr.attr, NULL }; - -static struct attribute *ESQC610_FAN_attributes[] = { - &sensor_dev_attr_fan_status.dev_attr.attr, - &sensor_dev_attr_fan_present.dev_attr.attr, - &sensor_dev_attr_fan_power.dev_attr.attr, - &sensor_dev_attr_fan_speed_rpm.dev_attr.attr, -#ifdef FAN_CTRL_WANTED - &sensor_dev_attr_fan_mode.dev_attr.attr, - &sensor_dev_attr_fan_rpm.dev_attr.attr, -#endif - NULL -}; - -#ifdef ASPEED_BMC_WANTED -static struct attribute *ESQC610_BMC_attributes[] = { - &sensor_dev_attr_bmc_sersor_1.dev_attr.attr, - &sensor_dev_attr_bmc_sersor_2.dev_attr.attr, - &sensor_dev_attr_bmc_sersor_3.dev_attr.attr, - &sensor_dev_attr_bmc_sersor_4.dev_attr.attr, - &sensor_dev_attr_bmc_present.dev_attr.attr, - NULL -}; -#endif /* end of sysfs attributes for hwmon */ /* struct attribute_group */ @@ -525,42 +1219,28 @@ static const struct attribute_group ESQC610_SYS_group = .attrs = ESQC610_SYS_attributes, }; -static const struct attribute_group ESQC610_PSU_group = -{ - .name = "ESQC610_PSU", - .attrs = ESQC610_PSU_attributes, -}; - -#ifdef USB_CTRL_WANTED -static const struct attribute_group ESQC610_USB_group = -{ - .name = "ESQC610_USB", - .attrs = ESQC610_USB_attributes, -}; -#endif - static const struct attribute_group ESQC610_LED_group = { .name = "ESQC610_LED", .attrs = ESQC610_LED_attributes, }; -static const struct attribute_group ESQC610_Reset_group = +static const struct attribute_group ESQC610_THERMAL_group = { - .name = "ESQC610_Reset", - .attrs = ESQC610_Reset_attributes, + .name = "ESQC610_THERMAL", + .attrs = ESQC610_THERMAL_attributes, }; -static const struct attribute_group ESQC610_Sensor_group = +static const struct attribute_group ESQC610_FAN_group = { - .name = "ESQC610_Sensor", - .attrs = ESQC610_Sensor_attributes, + .name = "ESQC610_FAN", + .attrs = ESQC610_FAN_attributes, }; -static const struct attribute_group ESQC610_INT_group = +static const struct attribute_group ESQC610_POWER_group = { - .name = "ESQC610_INT", - .attrs = ESQC610_INT_attributes, + .name = "ESQC610_POWER", + .attrs = ESQC610_POWER_attributes, }; static const struct attribute_group ESQC610_SFP_group = @@ -574,18 +1254,4 @@ static const struct attribute_group ESQC610_QSFP_group = .name = "ESQC610_QSFP", .attrs = ESQC610_QSFP_attributes, }; - -static const struct attribute_group ESQC610_FAN_group = -{ - .name = "ESQC610_FAN", - .attrs = ESQC610_FAN_attributes, -}; - -#ifdef ASPEED_BMC_WANTED -static const struct attribute_group ESQC610_BMC_group = -{ - .name = "ESQC610_BMC", - .attrs = ESQC610_BMC_attributes, -}; -#endif /* end of struct attribute_group */ diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/zrh2800k2.mod.c b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/zrh2800k2.mod.c deleted file mode 100644 index 867ad83530..0000000000 --- a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/modules/zrh2800k2.mod.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include - -MODULE_INFO(vermagic, VERMAGIC_STRING); - -__visible struct module __this_module -__attribute__((section(".gnu.linkonce.this_module"))) = { - .name = KBUILD_MODNAME, - .init = init_module, -#ifdef CONFIG_MODULE_UNLOAD - .exit = cleanup_module, -#endif - .arch = MODULE_ARCH_INIT, -}; - -#ifdef RETPOLINE -MODULE_INFO(retpoline, "Y"); -#endif - -static const struct modversion_info ____versions[] -__used -__attribute__((section("__versions"))) = { - { 0xd1a11d1c, __VMLINUX_SYMBOL_STR(module_layout) }, - { 0x8308dcad, __VMLINUX_SYMBOL_STR(i2c_del_driver) }, - { 0x851c3bfc, __VMLINUX_SYMBOL_STR(i2c_register_driver) }, - { 0xdb7305a1, __VMLINUX_SYMBOL_STR(__stack_chk_fail) }, - { 0x91715312, __VMLINUX_SYMBOL_STR(sprintf) }, - { 0x14c72286, __VMLINUX_SYMBOL_STR(i2c_smbus_read_byte_data) }, - { 0x4f6e1ac4, __VMLINUX_SYMBOL_STR(i2c_smbus_read_word_data) }, - { 0xfa119060, __VMLINUX_SYMBOL_STR(hwmon_device_register) }, - { 0xae59a99, __VMLINUX_SYMBOL_STR(sysfs_create_group) }, - { 0x4b82759, __VMLINUX_SYMBOL_STR(_dev_info) }, - { 0x888680a0, __VMLINUX_SYMBOL_STR(__mutex_init) }, - { 0xe52cb2e9, __VMLINUX_SYMBOL_STR(kmem_cache_alloc_trace) }, - { 0x660b9bcf, __VMLINUX_SYMBOL_STR(kmalloc_caches) }, - { 0x2ea2c95c, __VMLINUX_SYMBOL_STR(__x86_indirect_thunk_rax) }, - { 0x27e1a049, __VMLINUX_SYMBOL_STR(printk) }, - { 0x50eb70fa, __VMLINUX_SYMBOL_STR(i2c_smbus_write_byte_data) }, - { 0xb742fd7, __VMLINUX_SYMBOL_STR(simple_strtol) }, - { 0x94218140, __VMLINUX_SYMBOL_STR(mutex_unlock) }, - { 0xd0b0d91b, __VMLINUX_SYMBOL_STR(i2c_smbus_read_i2c_block_data) }, - { 0x86b8d7be, __VMLINUX_SYMBOL_STR(mutex_lock) }, - { 0x37a0cba, __VMLINUX_SYMBOL_STR(kfree) }, - { 0x9b242c96, __VMLINUX_SYMBOL_STR(sysfs_remove_group) }, - { 0x81e2daa3, __VMLINUX_SYMBOL_STR(hwmon_device_unregister) }, - { 0xbdfb6dbb, __VMLINUX_SYMBOL_STR(__fentry__) }, -}; - -static const char __module_depends[] -__used -__attribute__((section(".modinfo"))) = -"depends="; - diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/setup.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/setup.py new file mode 100755 index 0000000000..af31b18fd8 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='ESQC610-56SQ sonic platform API', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'esqc610-56sq/sonic_platform'}, +) \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/__init__.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/__init__.py new file mode 100755 index 0000000000..0b887c8c6b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/__init__.py @@ -0,0 +1 @@ +__all__ = ["platform", "chassis", "fan", "psu"] diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/chassis.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/chassis.py new file mode 100755 index 0000000000..1fb378b51b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/chassis.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + import os + import time + import subprocess + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.platDev import PlatDev + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" + + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + _global_port_pres_dict = {} + + def __init__(self): + super(Chassis, self).__init__() + + # Initialize SKU name and Platform name + self.sku_name = self._get_sku_name() + self.platform_name = self._get_platform_name() + self.name = self.sku_name + + # get the device infomation of platform + self.platdev = PlatDev() + + #self._component_list = [] + #self._module_list = [] + #self._fan_drawer_list = [] + + self._eeprom = Eeprom() + # init component + for i in range(self.platdev.get_component_count()): + component = Component(i, self.platdev.get_component_name(i), self.platdev.get_component_descript(i)) + self._component_list.append(component) + # init fan list + if self.platdev.get_fan_support(): + fanlist = self.platdev.get_fan_list() + for index in range(0,len(fanlist)): + fan_name = fanlist[index] + for pos in range(0, self.platdev.get_fan_num_by_name(fan_name)): + fan = Fan( index, pos, [self.platdev.get_fan_sysfile_path_by_name(fan_name),'']) + self._fan_list.append(fan) + + # init psu list + psulist = self.platdev.get_psu_list() + for index in range(0, len(psulist)): + psu_name = psulist[index] + psu = Psu(index, [ self.platdev.get_psu_attr_path_by_name(psu_name), \ + self.platdev.get_psu_status_path_by_name(psu_name) ], \ + self.platdev.bmc_is_exist()) + self._psu_list.append(psu) + + # init thermal list + thermal_info_list = self.platdev.get_thermal_dev_info_all() + for index in range(0, len(thermal_info_list)): + if len(self.platdev.get_thermal_dev_tempidx_by_idx(index)) > 1: + for idx in self.platdev.get_thermal_dev_tempidx_by_idx(index): + thermal = Thermal(idx, self.platdev.get_thermal_dev_name_by_idx(index)+"-{}".format(idx), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(),\ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + else: + thermal = Thermal(1, self.platdev.get_thermal_dev_name_by_idx(index), \ + self.platdev.get_thermal_dev_sysfile_path_by_idx(index), \ + self.platdev.bmc_is_exist(), \ + self.platdev.get_thermal_dev_support_mask_by_idx(index), \ + self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(index)) + self._thermal_list.append(thermal) + + # init sfp list + port_num = 1 + for sfpg_name in self.platdev.get_sfp_group_list(): + if self.platdev.get_sfp_group_type_by_name(sfpg_name) == 'QSFP28': + sfp_type = QSFP_TYPE + else: + sfp_type = SFP_TYPE + + for x in range(0,self.platdev.get_sfp_group_number_by_name(sfpg_name)): + eeprom_path_list = ['n/a','n/a'] + if self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] != 'n/a': + eeprom_path_list[0] = self.platdev.get_sfp_group_path_by_name(sfpg_name)[x] + '/eeprom' + if os.path.exists(eeprom_path_list[0].replace("0050", "0051")): + eeprom_path_list[1] = eeprom_path_list[0].replace("0050", "0051") + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + sfp = Sfp(port_num, eeprom_path_list, sfp_type, self.platdev.get_sfp_ext_sysfile_list()) + port_num += 1 + self._sfp_list.append(sfp) + + self.init_global_port_presence() + + def _get_sku_name(self): + p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + + def _get_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.decode().rstrip('\n') + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.name + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr('') + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + # not support any hardware reboot, just return REBOOT_CAUSE_NON_HARDWARE + # to keep reboot cause as software reboot + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + ############################################## + # System LED methods + ############################################## + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + return False + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + raise NotImplementedError + + ############################################## + # Other methods + ############################################## + + def init_global_port_presence(self): + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + port_dict = {} + while True: + for port_num in range(0, self.platdev.get_sfp_num()): + presence = self._sfp_list[port_num].get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, {'sfp':port_dict} + + time.sleep(1) + + + def sfp_debugger(self): + """ + Try to show all parameters read from eeprom with sfp methods + """ + print("SFP EEPROM data:") + for n in range(0, len(self._sfp_list)): + print("======SFP{}==TYPE {}====".format(n, self._sfp_list[n].sfp_type)) + print("get_transceiver_info:") + print(self._sfp_list[n].get_transceiver_info()) + print(" ") + + print("get_transceiver_threshold_info:") + print(self._sfp_list[n].get_transceiver_threshold_info()) + print(" ") + + print("get_transceiver_bulk_status:") + print(self._sfp_list[n].get_transceiver_bulk_status()) + print(" ") + + print("get_lpmode:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_lpmode())) + # set_lpmode + + print("get_power_override:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_power_override())) + + print("get_temperature:") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_temperature())) + + print("get_voltage") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_voltage())) + + print("get_tx_bias") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_bias())) + + print("get_rx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_rx_power())) + + print("get_tx_power") + for n in range(0, len(self._sfp_list)): + print("\tsfp{}: {}".format( n, self._sfp_list[n].get_tx_power())) + + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/component.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/component.py new file mode 100755 index 0000000000..d2b5b969fe --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/component.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +######################################################################## +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + def __init__(self, idx,name,descript): + self.index = idx + self.name = name + self.description = descript + + def _get_cpld_register(self, syspath): + rv = 'ERR' + if (not os.path.isfile(syspath)): + return rv + # noinspection PyBroadException + try: + with open(syspath, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def _get_cpld_version(self, cpld_number): + cpld_version_reg = { + 1: "/sys/class/hwmon/hwmon2/device/ESQC610_SYS/cpld_30_ver", + 2: "master_cpld_ver", + 3: "slave_cpld_ver" + } + + cpld_version = self._get_cpld_register(cpld_version_reg[cpld_number]) + + if cpld_version != 'ERR': + return cpld_version[-4:] + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + bios_ver = self._get_bios_version() + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index <= 3: + return self._get_cpld_version(self.index) + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/eeprom.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/eeprom.py new file mode 100755 index 0000000000..8740c4c11a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/eeprom.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +try: + import os + import sys + import re + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + # noinspection PyBroadException + try: + match = re.search( + '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) + if match is not None: + idx = match.group(1) + value = match.group(3).rstrip('\0') + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + err = self.read_eeprom_db() + if err: + # Failed to read EEPROM information from database. Read from cache file + pass + else: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + return self.__parse_output(decode_output) + + status = self.check_status() + if status < 'ok': + return {} + + if not os.path.exists(CACHE_ROOT): + # noinspection PyBroadException + try: + os.makedirs(CACHE_ROOT) + except Exception: + pass + + # + # only the eeprom classes that inherit from eeprom_base + # support caching. Others will work normally + # + # noinspection PyBroadException + try: + self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE)) + except Exception: + pass + + data = self.read_eeprom() + if data is None: + return 0 + # noinspection PyBroadException + try: + self.update_cache(data) + except Exception: + pass + + self.decode_eeprom(data) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(data) + if not is_valid: + return {} + + return self.__parse_output(decode_output) + + def get_eeprom(self): + return self._eeprom + + + def serial_number_str(self): + """ + Returns the serial number + """ + return self._eeprom.get('0x23', "Undefined.") + + def base_mac_addr(self, e): + """ + Returns the base mac address found in the system EEPROM + """ + return self._eeprom.get('0x24', "Undefined.") + + def modelstr(self): + """ + Returns the Model name + """ + return self._eeprom.get('0x28', "Undefined.") + + def part_number_str(self): + """ + Returns the part number + """ + return self._eeprom.get('0x22', "Undefined.") + + def revision_str(self): + """ + Returns the device revision + """ + return self._eeprom.get('0x26', "Undefined.") + + def serial_str(self): + return self._eeprom.get('0x2F', "Undefined.") + + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self._eeprom \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/fan.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/fan.py new file mode 100755 index 0000000000..278b5cb998 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/fan.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +FAN_POSITION_NAME = ["Front","Rear"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_index, position_index, attr_path, psu_fan = False): + # fan_index: the index of a fan module belongs to + # position_index : position of the fan in a fan module, 0 -> front, 1 -> rear, + # position_index : index of PSU belongs to if psu_fan is True, start from 0 + super(Fan, self).__init__() + self.index = fan_index + 1 + self.position = position_index + self.is_psu_fan = psu_fan + self.attr_path = attr_path[0] + + if psu_fan is True: + self.fan_name = "PSU{}_FAN{}".format(self.index, self.position+1) + self.speed_file = attr_path[1] + else: + self.fan_name = "FAN{}-{}".format(self.index, FAN_POSITION_NAME[self.position]) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_presence(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_prnt'.format(self.index)) + if data == '1': + return True + else: + return False + ret = self.__read_attr_file(self.attr_path + 'fan{}_present'.format(self.index)) + if ret == '1': + return True + elif ret == '0': + return False + else: + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.fan_name + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + return self.FAN_DIRECTION_NOT_APPLICABLE + + def get_status(self): + if self.is_psu_fan is True: + data = self.__read_attr_file(self.attr_path + 'psu{}_good'.format(self.index)) + if data == '1': + return True + else: + return False + data = self.__read_attr_file(self.attr_path + 'fan{}_stat'.format(self.index)) + if data == '1': + return True + elif data == '0': + return False + else: + return False + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan is True and self.get_presence(): + speed = self.__read_attr_file( self.speed_file, 0) + if speed is not None: + return (int(speed)*100)//16000 + else: + return 0 + + if self.get_presence(): + if self.position ==0: + speed_file =self.attr_path + 'fan{}_front_rpm'.format(self.index) + else: + speed_file =self.attr_path + 'fan{}_rear_rpm'.format(self.index) + data = self.__read_attr_file(speed_file) + if data is not None: + for sdata in data.split(' '): + if sdata.isdigit(): + return (int(sdata)*100)//18000 + return 0 + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + return self.get_speed() + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + """ + raise NotImplementedError + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platDev.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platDev.py new file mode 100755 index 0000000000..c67ab6bc7e --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platDev.py @@ -0,0 +1,381 @@ +#!/usr/bin/env python + +try: + import os + import copy + import json + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("paltDev") +PLATFORM_INSTALL_INFO_FILE = "/etc/sonic/platform_install.json" +PLATFORM_NAME = "esqc610_56sq" +MAX_FAN_MODULE = 5 +MAX_FAN = 2 + +# THERMAL_SENSOR_LIST +# index is used to indicate the default temp{}_* under sysfile_path +# support_mask: 1:support 0:not support +# bit 0 : temperature (always 1) +# bit 1 : high threshold +# bit 2 : low threshold +# bit 3 : high critical threshold +# bit 4 : low critical threshold +# bit 7 : cpu internal sensor +# ext_sysfile_list: each specified path of each supported function, +# which not follows the (default) genernal naming rule +# [0] ext_temp_file : temperature +# [1] ext_high_thr : high threshold +# [2] ext_low_thr : low threshold +# [3] ext_high_cri_thr : high critical threshold +# [4] ext_low_cri_thr : low critical threshold + +# ['Sensor 1 Top', 'temp_th0_t', 'temp_th0_t_max', 'temp_th0_t_min', 'temp_th0_t_crit', 'temp_th0_t_lcrit'], +# ['Sensor 1 Bottom', 'temp_th0_b', 'temp_th0_b_max', 'temp_th0_b_min', 'temp_th0_b_crit', 'temp_th0_b_lcrit'], +# ['Sensor 1 Remote', 'temp_th0_r', 'temp_th0_r_max', 'temp_th0_r_min', 'temp_th0_r_crit', 'temp_th0_r_lcrit'], +# ['Sensor 2 Top', 'temp_th1_t', 'temp_th1_t_max', 'temp_th1_t_min', 'temp_th1_t_crit', 'temp_th1_t_lcrit'], +# ['Sensor 2 Bottom', 'temp_th1_b', 'temp_th1_b_max', 'temp_th1_b_min', 'temp_th1_b_crit', 'temp_th1_b_lcrit'], +# ['Sensor 3 Top', 'temp_th2_t', 'temp_th2_t_max', 'temp_th2_t_min', 'temp_th2_t_crit', 'temp_th2_t_lcrit'], +# ['Sensor 3 Bottom', 'temp_th2_b', 'temp_th2_b_max', 'temp_th2_b_min', 'temp_th2_b_crit', 'temp_th2_b_lcrit'], +# ['Sensor 4 Top', 'temp_th3_t', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit'], +# ['Sensor 4 Bottom', 'temp_th3_b', 'temp_th3_b_max', 'temp_th3_b_min', 'temp_th3_b_crit', 'temp_th3_b_lcrit'], + +THERMAL_SENSOR_LIST = [ + { + 'name': "pch_haswell", + 'temp_index': [1], + 'sysfile_path': "/sys/class/hwmon/hwmon0/", + 'support_mask': 0x81, + 'ext_sysfile_list': None + }, + { + 'name': "CPU core temp", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon1/", + 'support_mask': 0x8B, + 'ext_sysfile_list': None + }, + { + 'name': "NCT7511Y(U48)", + 'temp_index': [1, 2, 4], + 'sysfile_path': "/sys/class/hwmon/hwmon6/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_th0_t', 'temp_th0_t_max', 'temp_th0_t_min', 'temp_th0_t_crit', 'temp_th0_t_lcrit'], + 2:['temp_th0_b', 'temp_th0_b_max', 'temp_th0_b_min', 'temp_th0_b_crit', 'temp_th0_b_lcrit'], + 4:['temp_th0_r', 'temp_th0_r_max', 'temp_th0_r_min', 'temp_th0_r_crit', 'temp_th0_r_lcrit']} + }, + { + 'name': "G781(U44)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon3/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_th1_t', 'temp_th1_t_max', 'temp_th1_t_min', 'temp_th1_t_crit', 'temp_th1_t_lcrit'], + 2:['temp_th1_b', 'temp_th1_b_max', 'temp_th1_b_min', 'temp_th1_b_crit', 'temp_th1_b_lcrit']} + }, + { + 'name': "G781(U45)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon4/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_th2_t', 'temp_th2_t_max', 'temp_th2_t_min', 'temp_th2_t_crit', 'temp_th2_t_lcrit'], + 2:['temp_th2_b', 'temp_th2_b_max', 'temp_th2_b_min', 'temp_th2_b_crit', 'temp_th2_b_lcrit']} + }, + { + 'name': "G781(U47)", + 'temp_index': [1, 2], + 'sysfile_path': "/sys/class/hwmon/hwmon5/", + 'support_mask': 0x0F, + 'ext_sysfile_list': {1:['temp_th3_t', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit'], + 2:['temp_th3_b', 'temp_th3_b_max', 'temp_th3_b_min', 'temp_th3_b_crit', 'temp_th3_b_lcrit']} + } +] + +# PSU LIST +# ext_sysfile_list +# [0] : sysfile path for present +# [1] : sysfile path for status +# +PSU_LIST = ['PSU1', 'PSU2'] + +PSU_INFO = { + 'PSU1': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESQC610_POWER/" + }, + 'PSU2': { + 'attr_path': "WILL BE RE-INIT", + 'status_path': "/sys/class/hwmon/hwmon2/device/ESQC610_POWER/" + } +} + +# SFP LIST +# +# +FAN_LIST = ['FAN1', 'FAN2', 'FAN3', 'FAN4'] + +FAN_INFO = { + 'FAN1': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESQC610_FAN/' + }, + 'FAN2': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESQC610_FAN/' + }, + 'FAN3': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESQC610_FAN/' + }, + 'FAN4': { + 'isdraw': True, + 'fan_num': 2, + 'attr_path': '/sys/class/hwmon/hwmon2/device/ESQC610_FAN/' + }, +} + + +# SFP LIST +# +# +SFP_EXT_SYSFILE_LIST = ["/sys/class/hwmon/hwmon2/device/ESQC610_QSFP/", + "/sys/class/hwmon/hwmon2/device/ESQC610_SFP/"] + +SFP_GROUP_LIST = ['SFP-G01', 'SFP-G02', 'SFP-G03', 'SFP-G04', 'SFP-G05', 'SFP-G06', 'SFP-G07'] + +PORT_NUM = 56 + +# SFP-eeprom paths /sys/bus/i2c/devices/XX-0050 +SFP_GROUP_INFO = { + "SFP-G01": { + "type": "SFP+", + "paths": [ + + ], + "number": 8, + }, + "SFP-G02": { + "type": "SFP+", + "paths": [ + + ], + "number": 8, + }, + "SFP-G03": { + "type": "SFP+", + "paths": [ + + ], + "number": 8, + }, + "SFP-G04": { + "type": "SFP+", + "paths": [ + + ], + "number": 8, + }, + "SFP-G05": { + "type": "SFP+", + "paths": [ + + ], + "number": 8, + }, + "SFP-G06": { + "type": "SFP+", + "paths": [ + + ], + "number": 8, + }, + "SFP-G07": { + "type": "QSFP28", + "paths": [ + + ], + "number": 8, + } +} + +# +#Component +# ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " +# "modules (1-16)")], +# ["Slave-CPLD", "Used for managing QSFP modules (17-32)"] + +CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["System-CPLD", "Used for managing CPU board devices and power"] +] + +class PlatDev(): + def __init__(self): + self.plat_name = PLATFORM_NAME + self.psu_info = copy.deepcopy(PSU_INFO) + self.thermal_info = [] + self.fan_info = copy.deepcopy(FAN_INFO) + self.sfp_info = copy.deepcopy(SFP_GROUP_INFO) + self.device_install_info = dict() + self.sfp_install_info = dict() + + # get install info + self.get_dev_install_info() + # update path info with install info + # Item 1/2 not changed, append directly + self.thermal_info.append(THERMAL_SENSOR_LIST[0]) + self.thermal_info.append(THERMAL_SENSOR_LIST[1]) + + for i in range(2, len(THERMAL_SENSOR_LIST)): + install_info = self.device_install_info.get(THERMAL_SENSOR_LIST[i]['name']) + if install_info : + if self.bmc_is_exist(): + THERMAL_SENSOR_LIST[i]['sysfile_path'] = '/sys/class/hwmon/hwmon2/device/ESQC610_THERMAL/' + else: + THERMAL_SENSOR_LIST[i]['sysfile_path'] = install_info.get('hwmon_path') + self.thermal_info.append(THERMAL_SENSOR_LIST[i]) + + for psu_name in PSU_LIST: + install_info = self.device_install_info.get(psu_name) + if install_info: + if self.bmc_is_exist(): + self.psu_info[psu_name]['attr_path']= '/sys/class/hwmon/hwmon2/device/ESQC610_POWER/' + else: + self.psu_info[psu_name]['attr_path'] = install_info.get('hwmon_path')+ '/device/' + + for sfp_group_name in SFP_GROUP_LIST: + install_info = self.sfp_install_info.get(sfp_group_name) + if install_info: + self.sfp_info[sfp_group_name]['paths'] = install_info.get('paths') + + def get_dev_install_info(self): + with open(PLATFORM_INSTALL_INFO_FILE) as fd: + install_info = json.load(fd) + self.sfp_install_info = install_info[2] + self.device_install_info = install_info[1] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def bmc_is_exist(self): + bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESQC610_SYS/bmc_present' + if os.path.exists(bmc_filePath): + value = self.__read_attr_file(bmc_filePath) + if int(value) == 1: + return True + else: + return False + else: + return False + ######Componet method ##### + def get_component_count(self): + return len(CHASSIS_COMPONENTS) + + def get_component_name(self,idx): + return CHASSIS_COMPONENTS[idx][0] + + def get_component_descript(self,idx): + return CHASSIS_COMPONENTS[idx][1] + + ###### PSU method ###### + def get_psu_list(self): + return PSU_LIST + + def get_psu_info_all(self): + return self.psu_info + + def get_psu_info_by_name(self, name): + return self.psu_info.get(name) + + def get_psu_attr_path_by_name(self, name): + return self.psu_info[name].get('attr_path') + + def get_psu_status_path_by_name(self, name): + return self.psu_info[name].get('status_path') + + ###### Thermal method ###### + def get_thermal_dev_info_all(self): + return self.thermal_info + + def get_thermal_dev_name_by_idx(self, index): + return self.thermal_info[index].get('name') + + def get_thermal_dev_tempidx_by_idx(self, index): + return self.thermal_info[index].get('temp_index') + + def get_thermal_dev_sysfile_path_by_idx(self, index): + return self.thermal_info[index].get('sysfile_path') + + def get_thermal_dev_support_mask_by_idx(self, index): + return self.thermal_info[index].get('support_mask') + + def get_thermal_dev_ext_sysfile_list_by_idx(self, index): + return self.thermal_info[index].get('ext_sysfile_list') + + ###### Fan method ###### + def get_fan_support(self): + return True + + def get_fan_list(self): + return FAN_LIST + + def get_fan_info_all(self): + return self.fan_info + + def get_fan_info_by_name(self, name): + return self.fan_info.get(name) + + def get_fan_sysfile_path_by_name(self, name): + return self.fan_info[name].get('attr_path') + + def get_fan_is_draw_by_name(self, name): + return self.fan_info[name].get('isdraw') + + def get_fan_num_by_name(self, name): + return self.fan_info[name].get('fan_num') + + ###### SFP method ###### + def get_sfp_num(self): + return PORT_NUM + + def get_sfp_group_list(self): + return SFP_GROUP_LIST + + def get_sfp_group_info(self): + return self.sfp_info + + def get_sfp_group_info_by_name(self, name): + return self.sfp_info.get(name) + + def get_sfp_group_type_by_name(self, name): + return self.sfp_info[name].get('type') + + def get_sfp_group_path_by_name(self, name): + return self.sfp_info[name].get('paths') + + def get_sfp_group_number_by_name(self, name): + return self.sfp_info[name].get('number') + + def get_sfp_ext_sysfile_list(self): + return SFP_EXT_SYSFILE_LIST + + + + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platform.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platform.py new file mode 100755 index 0000000000..2456a6f2e7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/platform.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/psu.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/psu.py new file mode 100755 index 0000000000..20e365e73d --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/psu.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common.logger import Logger + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = 'thermalctld' +logger = Logger(SYSLOG_IDENTIFIER) + +# To do: should be defined in platDev +PSU_MAX_VOUT = 12.0 # voltage +PSU_MIN_VOUT = 3.3 # voltage +PSU_MAX_TEMP = 50.0 # C + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, index, info_list,is_bmc): + PsuBase.__init__(self) + self.index = index + self.is_bmc = is_bmc + self.attr_path = info_list[0] + self.status_path = info_list[1] + if is_bmc: + speed_file = self.attr_path + 'psu{}_fan_speed'.format(index+1) + else: + speed_file = self.attr_path + 'psu_fan_speed_1' + + fan = Fan( index, 0, [self.status_path, speed_file ],True) + self._fan_list.append(fan) + self.psu_name = "PSU{}".format(self.index+1) + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.psu_name + + def get_presence(self): + """ + Retrieves the presence status of power supply unit (PSU) defined + Returns: + bool: True if PSU is present, False if not + """ + data = self.__read_attr_file(self.status_path + 'psu{}_prnt'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + data = self.__read_attr_file(self.status_path + 'psu{}_good'.format(self.index+1)) + if data == '1': + return True + else: + return False + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_vout'.format(self.index+1) + else: + path = self.attr_path + "/psu_vout" + vout = self.__read_attr_file( path, 0) + if vout is not None: + return float(vout) / 1000 + + return False + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_iout'.format(self.index+1) + else: + path = self.attr_path + "/psu_iout" + iout = self.__read_attr_file( path, 0) + if iout is not None: + return float(iout) / 1000 + return False + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + if self.is_bmc: + path = self.attr_path + 'psu{}_pout'.format(self.index+1) + else: + path = self.attr_path + "/psu_pout" + pout = self.__read_attr_file( path, 0) + if pout is not None: + return float(pout) / 1000000 + return False + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + raise NotImplementedError + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.is_bmc: + path = self.attr_path+'psu{}_temp'.format(self.index+1) + else: + path = self.attr_path + "/psu_temp_1" + temperature = self.__read_attr_file( path, 0) + if temperature is not None: + return float(temperature) / 1000 + + return False + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return PSU_MAX_TEMP + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MAX_VOUT + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return PSU_MIN_VOUT diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/sfp.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/sfp.py new file mode 100755 index 0000000000..b177b52476 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/sfp.py @@ -0,0 +1,1176 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common.logger import Logger + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +logger = Logger("sfp") + +############################################################################# +# +# SFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# ------------------------------------------------ 0 +# | Serial ID Defined by SFP MSA (96 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 95 +# | Vendor Specific (32 bytes) | +# |----------------------------------------------| 127 +# | Reserved, SFF-8079 (128 byte) | +# ------------------------------------------------ 255 +# +# 2 wire address 1010001x (A2h) (i2c 0x51) +# ------------------------------------------------ 0 +# | Alarm and Warning Threshold (56 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 55 +# | Cal Constants (40 bytes) | +# |----------------------------------------------| 95 +# | Real Time Diagnostic Interface(24 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 119 +# | Vendor Specific (7 bytes) | +# |----------------------------------------------| 126 +# | Page Select Byte (Optional) | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# Page 00h/01h +# |----------------------------------------------| 128 +# | User Writeable EEPROM (120 bytes) | +# |----------------------------------------------| 247 +# | Vendor Specific (8 bytes) | +# ------------------------------------------------ 255 +# Page 02h +# |----------------------------------------------| 128 +# | Control Function (128 bytes) | +# ------------------------------------------------ 255 +# Page 03h-7Fh +# |----------------------------------------------| 128 +# | Reserved (128 bytes) | +# ------------------------------------------------ 255 +# Page 80h-FFh +# |----------------------------------------------| 128 +# | Vendor Specific (128 bytes) | +# ------------------------------------------------ 255 +# +# ========================================================== +# QSFP : +# 2 wire address 1010000x (A0h) (i2c 0x50) +# +# ------------------------------------------------ 0 +# | ID and status (3 bytes) | +# |----------------------------------------------| 2 +# | Interrupt Flags (19 bytes) | +# |----------------------------------------------| 21 +# | Module Monitors (12 bytes) | <-- get_transceiver_bulk_status +# |----------------------------------------------| 33 +# | Channel Monitors (12 bytes) | +# |----------------------------------------------| 81 +# | Reserved (4 bytes) | +# |----------------------------------------------| 85 +# | Control (12 bytes) | <- get_power_override +# |----------------------------------------------| 97 +# | ~~~ | +# |----------------------------------------------| 126 +# | Page Select Byte | -> select one of the below pages as +# ------------------------------------------------ 127 address 128-255 +# +# +# Page 00h +# |----------------------------------------------| 128 +# | Base ID Filed (64 bytes) | <-- get_transceiver_info +# |----------------------------------------------| 191 +# | Extended ID (32 bytes) | +# |----------------------------------------------| 223 +# | Vendor Specific ID (8 bytes) | +# ------------------------------------------------ 255 +# Page 01h (optional) +# |----------------------------------------------| 128 +# | ~~~~ (128 bytes) | +# ------------------------------------------------ 255 +# Page 02h (optional) +# |----------------------------------------------| 128 +# | User EEPROM Data (128 bytes) | +# ------------------------------------------------ 255 + +# Page 03h (optional on QSFP28) +# |----------------------------------------------| 128 +# | Module Threshold (48 bytes) | <-- get_transceiver_threshold_info +# |----------------------------------------------| 175 +# | Channel Threshold (48 bytes) | +# |----------------------------------------------| 223 +# | Reserved (2 bytes) | +# |----------------------------------------------| 225 +# | Vendor Specific Channel Controls (16 bytes) | +# |----------------------------------------------| 241 +# | Channel Monitor Masks (12 bytes) | +# |----------------------------------------------| 253 +# | Reserved (2 bytes) | +# ------------------------------------------------ 255 +# +# +# +# +# +# +# +# +############################################################################# + +# function eunm +SFP_GET_PRESENCE=0 +SFP_RESET =1 +SFP_GET_LOW_POWER_MODE=2 +SFP_SET_LOW_POWER_MODE=3 + +# XCVR type definition +SFP_TYPE = 0 +QSFP_TYPE = 1 + +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] + +# index for A0H, A2H sysfs file path +INDEX_A0H = 0 +INDEX_A2H = 1 + +# offset/width definition +OFFSET = 0 +WIDTH = 1 + +QSFP_UPPER_MEMORY_PAGE00_OFFSET = 128 +QSFP_UPPER_MEMORY_PAGE03_OFFSET = 512 + +SFP_A0H_OFFSET = 0 +SFP_A2H_OFFSET = 0 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 +ID_FIELD_WIDTH = 92 + +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 1 +QSFP_INTERFACE_BULK_WIDTH = 20 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 5], + 'DEVICE_TECH': [19, 1], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 2], + 'WAVELENGTH': [58, 2], + 'WAVELENGTH_TOLERANCE': [60, 2], + 'MAX_CASE_TEMP': [62, 1], + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 4], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [22, 2], + 'VOLTAGE': [26, 2], + 'CHANNEL_MON': [34, 24], + 'CONTROL': [86, 12], + # PAGE03 + 'MODULE_THRESHOLD': [0, 24], + 'CHANNEL_THRESHOLD': [50, 24] +} +SFP_INTERFACE_BULK_WIDTH = 21 +SFP_ID_FIELDS = { + # NAME : [OFFSET:WIDTH] + 'TYPE': [0, 1], + 'EXTID': [1, 1], + 'CONNECTOR': [2 , 1], + 'XCVR_COMPLIANCE': [3, 8], + 'ENCODING': [11,1], + 'NORMAL_BITRATE': [12, 1], + 'EXT_RATE_SEL_COMPLIANCE': [13, 1], + 'CABLE_LEN': [14, 6], + 'VENDOR_NAME': [20, 16], + 'EXT_XCVR_CODE': [36, 1], + 'VENDOR_OUI': [37, 3], + 'VENDOR_PN': [40, 16], + 'VENDOR_REV': [56, 4], + 'WAVELENGTH': [60, 2], + # UNALLOCATED WIDDTH: 1 + 'CC_BASE': [63, 1], + 'OPTIONS': [64, 2], + 'BITRATE_MAX': [66, 1], + # BITRATE_MAX ?? + 'BITRATE_MAX_1': [67, 1], + 'VENDOR_SN': [68, 16], + 'VENDOR_DATE': [84, 8], + # DOM + 'TEMPERATURE': [96, 2], + 'VOLTAGE': [98, 2], + 'CHANNEL_MON': [100, 6], + 'MODULE_THRESHOLD': [0, 40] +} + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes','FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia','FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') +#base 0 +_qsfp_port_start = 48 +class Sfp(SfpBase): + """Platform-specific Sfp class""" + def __init__(self, index, eeprom_path_list, sfp_type, ext_sysfile_list=None): + # index: port index, start from 0 + # eeprom_path_list : a list of path to eeprom sysfile + # [0]: for 0x50 + # [1]: for 0x51 + # ext_sysfile_list: used to get other function of sfp + # [0]: present + # [1]: reset + # [2]: get lowpower mode + # [3]: set lowpower mode + # ext_sysfile_list[0]: QSFP path + # ext_sysfile_list[1]: SFP path + self.index = index + self.eeprom_path_list = eeprom_path_list + #self._get_sfp_type(sfp_type) + self.sfp_type = sfp_type + if self.sfp_type == QSFP_TYPE: + self.present_file = ext_sysfile_list[0]+ 'qsfp{}_present'.format(self.index- _qsfp_port_start) + self.reset_file = ext_sysfile_list[0]+ 'qsfp{}_reset'.format(self.index- _qsfp_port_start) + self.lp_file = ext_sysfile_list[0]+ 'qsfp{}_low_power'.format(self.index- _qsfp_port_start) + else: + self.present_file = ext_sysfile_list[1]+ 'sfp{}_present'.format(self.index) + self.reset_file = None + self.lp_file = None + + def _get_sfp_type(self, sfp_type): + ty = self._read_eeprom_bytes(SFP_ID_FIELDS['TYPE'][OFFSET], SFP_ID_FIELDS['TYPE'][WIDTH], INDEX_A0H) + if ty is not None: + if ty[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + if ty[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + else: + self.sfp_type = sfp_type + logger.log_warning("Unreganized sfp type of module {} . unsupported, treated as specified type {}".format(self.index, sfp_type)) + else: + self.sfp_type = sfp_type + + + def _read_eeprom_bytes(self, offset, num_bytes, path_idx): + eeprom_raw = [] + + eeprom = None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom = open(self.eeprom_path_list[path_idx], mode="rb", buffering=0) + eeprom.seek(offset) + raw_data = eeprom.read(num_bytes) + for nb in range(0, len(raw_data)): + eeprom_raw[nb] = hex(ord(raw_data[nb]))[2:].zfill(2) + except Exception as ex: + logger.log_error("Fail to read eeprom {}".format(self.eeprom_path_list[path_idx])) + logger.log_error(" {}".format(ex)) + if eeprom is not None: + eeprom.close() + return None + + return eeprom_raw + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def __write_attr_file(self, filepath, data): + try: + with open(filepath,'w') as fd: + return fd.write(data) + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + return 0 + + def get_presence(self): + if self.present_file is not None: + data = self.__read_attr_file(self.present_file) + if data is not None: + if int(data) == 1: + return True + return False + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return '-inf' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == QSFP_TYPE: + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self._read_eeprom_bytes((offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self._read_eeprom_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH,INDEX_A0H) + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + qspf_dom_capability = int(qsfp_dom_capability_raw[0], 16) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qspf_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qspf_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qspf_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + qsfp_option_value_raw = self._read_eeprom_bytes(QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH,INDEX_A0H) + if qsfp_option_value_raw is not None: + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + self.optional_capability = sfpd_obj.parse_option_params(qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = self.optional_capability['data']['TxDisable']['value'] == 'On' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + elif self.sfp_type == SFP_TYPE: + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self._read_eeprom_bytes(XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH,INDEX_A0H) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = (int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + transceiver_info_dict_keys = [ + 'type', 'hardware_rev', + 'serial', 'manufacturer', + 'model', 'connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui','application_advertisement'] + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE00_OFFSET # upper memory map: Page 00h + Id_field = QSFP_ID_FIELDS + info_bulk_width = QSFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8436InterfaceId() + + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A0H_OFFSET # lower memory map: A0h (SFP i2c 0x50) + Id_field = SFP_ID_FIELDS + info_bulk_width = SFP_INTERFACE_BULK_WIDTH + sfpi_obj = sff8472InterfaceId() + else: + logger.log_error("Unsupported sfp type") + return None + + if sfpi_obj is None: + logger.log_error("sfpi_obj create fail") + return None + + # read Base ID field + sfp_interface_bulk_raw = self._read_eeprom_bytes(field_offset, ID_FIELD_WIDTH, INDEX_A0H) + if sfp_interface_bulk_raw is None: + logger.log_error(" Fail to read BaseID field of module {}".format(self.index+1)) + return None + + start = 0 + end = start + info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_NAME'][OFFSET] + end = start + Id_field['VENDOR_NAME'][WIDTH] + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_PN'][OFFSET] + end = start + Id_field['VENDOR_PN'][WIDTH] + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_REV'][OFFSET] + end = start + Id_field['VENDOR_REV'][WIDTH] + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_SN'][OFFSET] + end = start + Id_field['VENDOR_SN'][WIDTH] + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_OUI'][OFFSET] + end = start + Id_field['VENDOR_OUI'][WIDTH] + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = Id_field['VENDOR_DATE'][OFFSET] + end = start + Id_field['VENDOR_DATE'][WIDTH] + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + + compliance_code_dict = {} + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = [ + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] + transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] + transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] + transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] + transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] + transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] + transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num(transceiver_dom_info_dict[key]) + + return transceiver_dom_info_dict + + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + dom_info_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + + transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + path_idx = INDEX_A0H + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + field_offset = QSFP_UPPER_MEMORY_PAGE03_OFFSET # uppper memory map: Page 03h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + if self.eeprom_path_list[INDEX_A2H] is not 'n/a': + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + path_idx = INDEX_A2H + else: + field_offset =256 + Id_field = SFP_ID_FIELDS + sfpd_obj = sff8472Dom() + else: + return transceiver_dom_threshold_info_dict + + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['MODULE_THRESHOLD'][OFFSET], Id_field['MODULE_THRESHOLD'][WIDTH], path_idx) + + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == QSFP_TYPE: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_THRESHOLD'][OFFSET], Id_field['CHANNEL_THRESHOLD'][WIDTH], path_idx) + + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + else: # SFP_TYPE + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + raise NotImplementedError + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + raise NotImplementedError + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + raise NotImplementedError + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + raise NotImplementedError + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + raise NotImplementedError + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.lp_file is not None: + data = self.__read_attr_file(self.lp_file, 0) + if data is not None: + if int(data) == 1: + return True + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + + if self.sfp_type == QSFP_TYPE: + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_bytes(Id_field['CONTROL'][OFFSET], Id_field['CONTROL'][WIDTH], INDEX_A0H) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + + return False + else: + return NotImplementedError + + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + path_idx = INDEX_A0H + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_bytes(field_offset + Id_field['TEMPERATURE'][OFFSET], Id_field['TEMPERATURE'][WIDTH], path_idx) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + + return None + + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + path_idx = INDEX_A0H + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_voltage_raw = self._read_eeprom_bytes(field_offset + Id_field['VOLTAGE'][OFFSET], Id_field['VOLTAGE'][WIDTH], path_idx) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + volt = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return volt + + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + path_idx = INDEX_A0H + tx_bias_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value'])) + + return tx_bias_list + + return None + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + path_idx = INDEX_A0H + rx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value'])) + + return rx_power_list + + return None + + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + path_idx = INDEX_A0H + tx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + field_offset = 0 # lower memory map: A0h + Id_field = QSFP_ID_FIELDS + sfpd_obj = sff8436Dom() + elif self.sfp_type == SFP_TYPE: + field_offset = SFP_A2H_OFFSET # lower memory map: A2h (SFP i2c 0x51) + Id_field = SFP_ID_FIELDS + path_idx = INDEX_A2H + sfpd_obj = sff8472Dom() + else: + return None + + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_bytes(field_offset + Id_field['CHANNEL_MON'][OFFSET], Id_field['CHANNEL_MON'][WIDTH], path_idx) + if dom_channel_monitor_raw is not None: + if self.sfp_type == QSFP_TYPE: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + + else: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value'])) + + return tx_power_list + + return None + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + if self.reset_file is not None: + ret = self.__write_attr_file(self.reset_file, '1') + if ret != 0: + return True + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.lp_file is not None: + if lpmode is True: + ret = self.__write_attr_file(self.lp_file, "1") + else: + ret = self.__write_attr_file(self.lp_file, "0") + if ret != 0: + return True + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + return False + + + diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/thermal.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/thermal.py new file mode 100755 index 0000000000..3731edaa7b --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/sonic_platform/thermal.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_py_common.logger import Logger + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +logger = Logger("thermal") +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + def __init__(self, index, name, sysfile_path, is_bmc, support_mask=0x1, ext_sysfile_list=None): + # index is used to indicate the temp{} under sffile_path + # support_mask: 1:support 0:not support + # bit 0 : temperature (always 1) + # bit 1 : high threshold + # bit 2 : low threshold + # bit 3 : high critical threshold + # bit 4 : low critical threshold + # bit 7 : cpu internal sensor + # ext_sysfile_list: each specified path of each supported function, + # which not follows the general naming rule + + self.index = index + self.name = name + self.filepath = sysfile_path + self.support_mask = support_mask + self.is_bmc = is_bmc + + self.temperature_file = None + self.high_thershold_file = None + self.low_threshold_file = None + self.high_critical_file = None + self.low_critical_file = None + + if sysfile_path is None: + return + + if self.is_bmc ==False or support_mask & 0x80 == 0x80: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + "/temp{}_input".format(self.index) + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + "/temp{}_max".format(self.index) + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + "/temp{}_min".format(self.index) + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + "/temp{}_crit".format(self.index) + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + "/temp{}_lcrit".format(self.index) + elif self.is_bmc and ext_sysfile_list is not None: + if support_mask & 0x1: + self.temperature_file = \ + sysfile_path + ext_sysfile_list[self.index][0] + if support_mask & 0x2: + self.high_thershold_file = \ + sysfile_path + ext_sysfile_list[self.index][1] + if support_mask & 0x4: + self.low_threshold_file = \ + sysfile_path + ext_sysfile_list[self.index][2] + if support_mask & 0x8: + self.high_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][3] + if support_mask & 0x10: + self.low_critical_file = \ + sysfile_path + ext_sysfile_list[self.index][4] + + def __read_attr_file(self, filepath, line=0xFF): + try: + with open(filepath,'r') as fd: + if line == 0xFF: + data = fd.read() + return data.rstrip('\r\n') + else: + data = fd.readlines() + return data[line].rstrip('\r\n') + except Exception as ex: + logger.log_error("Unable to open {} due to {}".format(filepath, repr(ex))) + + return None + + def get_name(self): + return self.name + + def get_presence(self): + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.temperature_file is not None: + temp = self.__read_attr_file( self.temperature_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_thershold_file is not None: + temp = self.__read_attr_file( self.high_thershold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_threshold_file is not None: + temp = self.__read_attr_file( self.low_threshold_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_file is not None: + temp = self.__read_attr_file( self.high_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.low_critical_file is not None: + temp = self.__read_attr_file( self.low_critical_file ) + if temp is not None: + return float(temp) / 1000 + + return None + diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/templates/cameo_esqc610_util.py.j2 b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/templates/cameo_esqc610_util.py.j2 index ce4313c133..d5ba5575de 100644 --- a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/templates/cameo_esqc610_util.py.j2 +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/templates/cameo_esqc610_util.py.j2 @@ -155,7 +155,7 @@ I2C_DEVICES = { 'status':'NOTINST' }, # NCT7511Y sensor & fan control - 'NCT7511Y(U73)': { + 'NCT7511Y(U48)': { 'parent':'PCA9548_0x75', 'parent_ch': 0, 'driver':'nct7511', @@ -164,7 +164,7 @@ I2C_DEVICES = { 'status':'NOTINST' }, # G781 sensors - 'G781(U94)': { + 'G781(U44)': { 'parent':'PCA9548_0x75', 'parent_ch': 1, 'driver':'g781', @@ -172,7 +172,7 @@ I2C_DEVICES = { 'path': ' ', 'status':'NOTINST' }, - 'G781(U4)': { + 'G781(U45)': { 'parent':'PCA9548_0x75', 'parent_ch': 2, 'driver':'g781', @@ -180,7 +180,7 @@ I2C_DEVICES = { 'path': ' ', 'status':'NOTINST' }, - 'G781(U34)': { + 'G781(U47)': { 'parent':'PCA9548_0x75', 'parent_ch': 3, 'driver':'g781', @@ -651,7 +651,7 @@ def hw_adjustment(): def set_led_control(): - cmd = "echo 1 > /sys/class/hwmon/hwmon2/device/ESQC610_LED/led_ctrl" + cmd = "echo 1 > /sys/class/hwmon/hwmon2/device/ESQC610_LED/led_fiber" status, output = log_os_system(cmd, 1) if status: print output @@ -710,9 +710,9 @@ def get_attr_value(attr_path): def get_hw_version(): value = '' - filePath = '/sys/class/hwmon/hwmon2/device/ESQC610_SYS/hw_version' + filePath = '/sys/class/hwmon/hwmon2/device/ESQC610_SYS/cpld_30_ver' if os.path.exists(filePath): - value = get_attr_value(filePath).split() + value = get_attr_value(filePath) return value[-1] else: return None @@ -721,10 +721,10 @@ def get_hw_version(): def bmc_is_exist(): value = '' - bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESQC610_BMC/bmc_present' + bmc_filePath = '/sys/class/hwmon/hwmon2/device/ESQC610_SYS/bmc_present' if os.path.exists(bmc_filePath): value = get_attr_value(bmc_filePath) - if value.find('not') < 0: + if int(value) == 1: return True else: return False diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_platform.sh b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_platform.sh new file mode 100755 index 0000000000..c3f9233ad6 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_platform.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Install esqc610-56sq python package +DEVICE="/usr/share/sonic/device" +PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + +if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl ]; then + pip install $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl +fi diff --git a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_sensors.py b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_sensors.py index 9a1e12ed1c..2284fc2793 100755 --- a/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_sensors.py +++ b/platform/innovium/sonic-platform-modules-cameo/esqc610-56sq/utils/cameo_esqc610_sensors.py @@ -1,6 +1,7 @@ #!/usr/bin/python from __future__ import print_function +from tabulate import tabulate import os import sys import logging @@ -10,12 +11,13 @@ MAX_FAN_NUM = 4 MAX_PSU_NUM = 2 PSU_LIST = ['PSU1','PSU2'] #0x58, 0x59 -PLATFORM_INSTALL_INFO_FILE = '/etc/sonic/platform_install.json' +THERMAL_SENSOR_LIST = ['NCT7511Y(U48)', 'G781(U44)', 'G781(U45)', 'G781(U47)'] -FAN_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_FAN/' -THERMAL_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_Sensor/' -POWER_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_PSU/' -BMC_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_BMC/' +PLATFORM_INSTALL_INFO_FILE = '/etc/sonic/platform_install.json' +BMC_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_SYS/' +FAN_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_FAN/' +POWER_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_POWER/' +THERMAL_SYSFILE_PATH = '/sys/class/hwmon/hwmon2/device/ESQC610_THERMAL/' def get_psu_path(): """ @@ -41,7 +43,7 @@ def get_thermal_sensor_path(): install_info = json.load(fd) for sensor_name in THERMAL_SENSOR_LIST: sensor = install_info[1][sensor_name] - sensor_path.append(sensor['path']+'/') + sensor_path.append(sensor['hwmon_path']+'/') return sensor_path except Exception: print("Fail to get sensor sysfsfile path") @@ -66,9 +68,10 @@ def get_attr_value(attr_path): def bmc_is_exist(): value = '' - if os.path.exists(BMC_SYSFILE_PATH+"bmc_present"): - value = get_attr_value(BMC_SYSFILE_PATH+"bmc_present") - if value.find('not') < 0: + bmc_filePath = BMC_SYSFILE_PATH+'bmc_present' + if os.path.exists(bmc_filePath): + value = get_attr_value(bmc_filePath) + if int(value) == 1: return True else: return False @@ -89,169 +92,204 @@ def print_attr_value_lines(sys_path): fo.close() return retval -def sensors_status(): +def show_sensor_table(): + + headers = ['Sensor', 'Temperature(C)', 'High(C)', 'Low(C)', 'Critical High(C)', 'Critical Low(C)'] + table = list() + temp = list() + if bmc_is_exist(): - print ('SENSOR STATUS:') - sys_path = THERMAL_SYSFILE_PATH + 'sensor_status' - print_attr_value_lines(sys_path) + sensor_table = [ + ['Sensor 1 Top' , 'temp_th0_t', 'temp_th0_t_max', 'temp_th0_t_min', 'temp_th0_t_crit', 'temp_th0_t_lcrit'], + ['Sensor 1 Bottom' , 'temp_th0_b', 'temp_th0_b_max', 'temp_th0_b_min', 'temp_th0_b_crit', 'temp_th0_b_lcrit'], + ['Sensor 1 Remote' , 'temp_th0_r', 'temp_th0_r_max', 'temp_th0_r_min', 'temp_th0_r_crit', 'temp_th0_r_lcrit'], + ['Sensor 2 Top' , 'temp_th1_t', 'temp_th1_t_max', 'temp_th1_t_min', 'temp_th1_t_crit', 'temp_th1_t_lcrit'], + ['Sensor 2 Bottom' , 'temp_th1_b', 'temp_th1_b_max', 'temp_th1_b_min', 'temp_th1_b_crit', 'temp_th1_b_lcrit'], + ['Sensor 3 Top' , 'temp_th2_t', 'temp_th2_t_max', 'temp_th2_t_min', 'temp_th2_t_crit', 'temp_th2_t_lcrit'], + ['Sensor 3 Bottom' , 'temp_th2_b', 'temp_th2_b_max', 'temp_th2_b_min', 'temp_th2_b_crit', 'temp_th2_b_lcrit'], + ['Sensor 4 Top' , 'temp_th3_t', 'temp_th3_t_max', 'temp_th3_t_min', 'temp_th3_t_crit', 'temp_th3_t_lcrit'], + ['Sensor 4 Bottom' , 'temp_th3_b', 'temp_th3_b_max', 'temp_th3_b_min', 'temp_th3_b_crit', 'temp_th3_b_lcrit'], + ] + else: + sensor_path = get_thermal_sensor_path() + sensor_table = [ + ['Sensor 1 Top' , sensor_path[0]+'temp4_input', sensor_path[0]+'temp4_max', sensor_path[0]+'temp4_min', sensor_path[0]+'temp4_crit', sensor_path[0]+'temp4_lcrit'], + ['Sensor 1 Bottom' , sensor_path[0]+'temp1_input', sensor_path[0]+'temp1_max', sensor_path[0]+'temp1_min', sensor_path[0]+'temp1_crit', sensor_path[0]+'temp1_lcrit'], + ['Sensor 1 Remote' , sensor_path[0]+'temp2_input', sensor_path[0]+'temp2_max', sensor_path[0]+'temp2_min', sensor_path[0]+'temp2_crit', sensor_path[0]+'temp2_lcrit'], + ['Sensor 2 Top' , sensor_path[1]+'temp1_input', sensor_path[1]+'temp1_max', sensor_path[1]+'temp1_min', sensor_path[1]+'temp1_crit', sensor_path[1]+'temp1_lcrit'], + ['Sensor 2 Bottom' , sensor_path[1]+'temp2_input', sensor_path[1]+'temp2_max', sensor_path[1]+'temp2_min', sensor_path[1]+'temp2_crit', sensor_path[1]+'temp2_lcrit'], + ['Sensor 3 Top' , sensor_path[2]+'temp1_input', sensor_path[2]+'temp1_max', sensor_path[2]+'temp1_min', sensor_path[2]+'temp1_crit', sensor_path[2]+'temp1_lcrit'], + ['Sensor 3 Bottom' , sensor_path[2]+'temp2_input', sensor_path[2]+'temp2_max', sensor_path[2]+'temp2_min', sensor_path[2]+'temp2_crit', sensor_path[2]+'temp2_lcrit'], + ['Sensor 4 Top' , sensor_path[3]+'temp1_input', sensor_path[3]+'temp1_max', sensor_path[3]+'temp1_min', sensor_path[3]+'temp1_crit', sensor_path[3]+'temp1_lcrit'], + ['Sensor 4 Bottom' , sensor_path[3]+'temp2_input', sensor_path[3]+'temp2_max', sensor_path[3]+'temp2_min', sensor_path[3]+'temp2_crit', sensor_path[3]+'temp2_lcrit'], + ] - return + for index in range(len(sensor_table)): + name = sensor_table[index][0] + for x in range(0, 5): + if bmc_is_exist(): + sys_path = THERMAL_SYSFILE_PATH + sensor_table[index][x+1] + else: + sys_path = sensor_table[index][x+1] + t = get_attr_value(sys_path) + if t == 'ERR': + temp.append('N/A') + else: + if t.isdigit(): + t = int(t)/1000.0 + temp.append('{}'.format(t)) -def sensors_temp(): - if bmc_is_exist(): - print ('SENSOR TEMPERATURE:') - sys_path = BMC_SYSFILE_PATH + 'bmc_sersor_1' - print_attr_value_lines(sys_path) - sys_path = BMC_SYSFILE_PATH + 'bmc_sersor_2' - print_attr_value_lines(sys_path) - sys_path = BMC_SYSFILE_PATH + 'bmc_sersor_3' - print_attr_value_lines(sys_path) - sys_path = BMC_SYSFILE_PATH + 'bmc_sersor_4' - print_attr_value_lines(sys_path) - return + table.append([name, temp[0], temp[1], temp[2], temp[3], temp[4]]) + del temp[:] + + print(tabulate(table, headers, tablefmt='simple', stralign='right')) + print('') -def get_voltage(): - return +def show_fan_table(): + headers = ['Fan', 'Speed(RPM)', 'Presence', 'Status', 'Power'] + table = [] + for index in range(1, MAX_FAN_NUM+1): + name_front = "FAN{}-Front".format(index) + name_rear = "FAN{}-Rear".format(index) + speed_front, speed_rear = fan_speed_dual(index) + present = fan_present(index) + status = fan_status(index) + power = fan_power(index) + table.append( [name_front, speed_front, present, status, power] ) + table.append( [name_rear , speed_front, present, status, power] ) + + print(tabulate(table, headers, tablefmt='simple', stralign='right')) + print('') -def fan_status(): - sys_path = FAN_SYSFILE_PATH + 'fan_status' - print ('FAN STATUS:') - print_attr_value_lines(sys_path) - return +def fan_status(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_stat'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'OK' + elif ret == '0': + return 'NG' + else: + return 'N/A' + +def fan_present(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_present'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'Present' + elif ret == '0': + return 'Not Present' + else: + return 'N/A' -def fan_present(): - sys_path = FAN_SYSFILE_PATH + 'fan_present' - print ('FAN PRESENT:') - print_attr_value_lines(sys_path) - return - -def fan_power(): - sys_path = FAN_SYSFILE_PATH + 'fan_power' - print ('FAN POWER:') - print_attr_value_lines(sys_path) - return - -def fan_speed(): - sys_path = FAN_SYSFILE_PATH + 'fan_speed_rpm' - print ('FAN SPEED:') - print_attr_value_lines(sys_path) - return +def fan_power(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_power'.format(index) + ret = get_attr_value(sys_path) + if ret == '1': + return 'OK' + elif ret == '0': + return 'NG' + else: + return 'N/A' +def fan_speed_dual(index): + sys_path = FAN_SYSFILE_PATH + 'fan{}_front_rpm'.format(index) + front_ret = get_attr_value(sys_path) + if front_ret == 'ERR': + front_ret = 'N/A' + + sys_path = FAN_SYSFILE_PATH + 'fan{}_rear_rpm'.format(index) + rear_ret = get_attr_value(sys_path) + if rear_ret == 'ERR': + rear_ret = 'N/A' + + return (front_ret, rear_ret) def is_psu_present(psu_number): - sys_path = POWER_SYSFILE_PATH + 'psu_present' - search_str = "PSU {} is present".format(psu_number) + sys_path = POWER_SYSFILE_PATH + 'psu{}_prnt'.format(psu_number) if os.path.exists(sys_path): value = get_attr_value(sys_path) - if search_str in value: + if value == '1': return True else: return False return False -def show_psu_status(path): - # [model, vin, vout, fan_speed, temperature, pin, pout, iin, iout, max_iout] - result_list = [0]*10 - if bmc_is_exist(): - try: - reg_file = open(path, 'r') - except IOError as e: - print( "Error: unable to open file: %s" % str(e)) - return False - - text_lines = reg_file.readlines() - reg_file.close() - - for line in text_lines: - spline = line.split(' ') - if "MFR_MODEL" in spline: - result_list[0] = spline[-1] - if "VIN" in spline: - result_list[1] = spline[-1] - if "VOUT" in spline: - result_list[2] = spline[-1] - if "FAN_SPEED" in spline: - result_list[3] = spline[-1] - if "TEMP_1" in spline: - result_list[4] = spline[-1] - if "PIN" in spline: - result_list[5] = spline[-1] - if "POUT" in spline: - result_list[6] = spline[-1] - if "IIN" in spline: - result_list[7] = spline[-1] - if "IOUT" in spline: - result_list[8] = spline[-1] - if "MFR_IOUT_MAX" in spline: - result_list[9] = spline[-1] - - else: - result_list[0] = get_attr_value(path+"psu_mfr_model") - result_list[1] = get_attr_value(path+"psu_vin") - result_list[2] = get_attr_value(path+"psu_vout") - result_list[3] = get_attr_value(path+"psu_fan_speed_1") - result_list[4] = get_attr_value(path+"psu_temp_1") - result_list[5] = get_attr_value(path+"psu_pin") - result_list[6] = get_attr_value(path+"psu_pout") - result_list[7] = get_attr_value(path+"psu_iin") - result_list[8] = get_attr_value(path+"psu_iout") - result_list[9] = get_attr_value(path+"psu_iout_max") - if result_list[0] != 'ERR': - print (' model: {}'.format(result_list[0])) +def is_psu_power_up(psu_number): + sys_path = POWER_SYSFILE_PATH + 'psu{}_good'.format(psu_number) + if os.path.exists(sys_path): + value = get_attr_value(sys_path) + if value == '1': + return True + else: + return False - if result_list[1] != 'ERR': - vin = int(result_list[1])/1000.0 - print (' Input Voltage: {:+3.2f} V'.format(vin)) - - if result_list[2] != 'ERR': - vout = int(result_list[2])/1000.0 - print (' Output Voltage: {:+3.2f} V'.format(vout)) + return False + +def show_psu_table(): + headers = ['PSU', 'Presence', 'Power', 'Fan Speed(RPM)', 'Temperature(C)', 'Vin(V)', 'Vout(V)', 'Pin(W)', 'Pout(W)', 'Iin(A)', 'Iout(A)', 'Max Iout(A)'] + table = [] + psu_sysfiles_list = [] + isbmc = bmc_is_exist() + if isbmc is False: + PSU_PATH = get_psu_path() - if result_list[3] != 'ERR': - fan_speed = int(result_list[3]) - print (' Fan Speed: {:3d} RPM'.format(fan_speed)) + for index in range(0, MAX_PSU_NUM): + if isbmc: + psu_sysfiles_list = [ + POWER_SYSFILE_PATH+'psu{}_fan_speed'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_temp'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_vin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_vout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_pin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_pout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_iin'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_iout'.format(index+1), + POWER_SYSFILE_PATH+'psu{}_mfr_iout_max'.format(index+1) + ] + else: + psu_sysfiles_list = [ + PSU_PATH[index]+'psu_fan_speed_1', + PSU_PATH[index]+'psu_temp_1', + PSU_PATH[index]+'psu_vin', + PSU_PATH[index]+'psu_vout', + PSU_PATH[index]+'psu_pin', + PSU_PATH[index]+'psu_pout', + PSU_PATH[index]+'psu_iin', + PSU_PATH[index]+'psu_iout', + PSU_PATH[index]+'psu_iout_max' + ] + status_list = get_psu_status(index+1, psu_sysfiles_list) + table.append(status_list) - if result_list[4] != 'ERR': - temperature = int(result_list[4])/1000.0 - print (' Temperature: {:+3.1f} C'.format(temperature)) - - if result_list[5] != 'ERR': - pin = int(result_list[5])/1000000.0 - print (' Input Power: {:3.2f} W'.format(pin)) - - if result_list[6] != 'ERR': - pout = int(result_list[6])/1000000.0 - print (' Output Power: {:3.2f} W'.format(pout)) - - if result_list[7] != 'ERR': - iin = int(result_list[7])/1000.0 - print (' Input Current: {:+3.2f} A'.format(iin)) - - if result_list[8] != 'ERR': - iout = int(result_list[8])/1000.0 - print (' Output Current: {:+3.2f} A'.format(iout),end='') - - if result_list[9] != 'ERR': - max_iout = int(result_list[9])/1000.0 - print (' (max = {:+3.2f} A)'.format(max_iout)) - + print(tabulate(table, headers, tablefmt='simple', stralign='right')) print('') - return -def psu_status(): - psu_path = [] - for x in range(0,MAX_PSU_NUM): - if is_psu_present(x+1): - print("PSU{} present".format(x+1)) - if bmc_is_exist(): - show_psu_status(POWER_SYSFILE_PATH + 'psu_module_{}'.format(x+1)) - else: - psu_path = get_psu_path() - show_psu_status(psu_path[x]) - - return +def get_psu_status(index, sysfile_list): + # result_list: [name, presence, power, fanSpeed(RPM), temperature(C), vin(V), vout(V), pin(W), pout(W), iin(A), iout(A), maxIout(A)] + name = 'PSU{}'.format(index) + result_list = [name, 'Not Present', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A'] + result_mutipler = [None, None, None, None, 1000.0, 1000.0, 1000.0, 1000000.0, 1000000.0, 1000.0, 1000.0, 1000.0] + + if is_psu_present(index): + result_list[1] = 'Present' + else: + return result_list + + if is_psu_power_up(index): + result_list[2] = 'up' + else: + result_list[2] = 'down' + for x in range(0, 9): + result_list[x+3] = get_attr_value(sysfile_list[x]) + + for x in range(0, 12): + if result_mutipler[x] != None and result_list[x] != 'ERR': + result_list[x] = int(result_list[x]) / result_mutipler[x] + + return result_list + def main(): """ @@ -266,16 +304,11 @@ def main(): for arg in sys.argv[1:]: if arg == 'fan_status': - fan_status() - fan_present() - fan_power() - fan_speed() + show_fan_table() elif arg == 'sensor_status': - sensors_temp() - sensors_status() - psu_status() - - + show_sensor_table() + show_psu_table() + else: print (main.__doc__) diff --git a/platform/innovium/sonic-platform-modules-wistron/debian/changelog b/platform/innovium/sonic-platform-modules-wistron/debian/changelog new file mode 100644 index 0000000000..12d04e4d03 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/debian/changelog @@ -0,0 +1,5 @@ +sonic-wistron-platform-modules (1.1) unstable; urgency=low + + * Initial release + + -- Haowei Chung Fri, 30 Aug 2019 14:48:00 +0800 diff --git a/platform/innovium/sonic-platform-modules-wistron/debian/compat b/platform/innovium/sonic-platform-modules-wistron/debian/compat new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/innovium/sonic-platform-modules-wistron/debian/control b/platform/innovium/sonic-platform-modules-wistron/debian/control new file mode 100644 index 0000000000..77d6cfa3e4 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/debian/control @@ -0,0 +1,11 @@ +Source: sonic-wistron-platform-modules +Section: main +Priority: extra +Maintainer: Wistron +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-wistron-sw-to3200k +Architecture: amd64 +Depends: linux-image-4.9.0-14-2-amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/innovium/sonic-platform-modules-wistron/debian/rules b/platform/innovium/sonic-platform-modules-wistron/debian/rules new file mode 100644 index 0000000000..79125a8aa5 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/debian/rules @@ -0,0 +1,40 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2.7 + +PACKAGE_PRE_NAME := sonic-platform-wistron +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= sw-to3200k +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) diff --git a/platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.install b/platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.install new file mode 100644 index 0000000000..8feb7dc6d5 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.install @@ -0,0 +1,5 @@ +sw-to3200k/utils/* usr/local/bin +sw-to3200k/service/platform_api/platform_api_mgnt.sh usr/local/bin +sw-to3200k/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-wistron_sw_to3200k-r0 +sw-to3200k/cfg/sw-to3200k-modules.conf etc/modules-load.d +sw-to3200k/service/*.service lib/systemd/system diff --git a/platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.postinst b/platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.postinst new file mode 100644 index 0000000000..8dda66c251 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/debian/sonic-platform-wistron-sw-to3200k.postinst @@ -0,0 +1,36 @@ +#!/bin/bash + +kernel_version=$(uname -r) + +for i in $(seq 1 10); +do + if [ -e /lib/modules/${kernel_version}/modules.dep ];then + wisko=$(cat /lib/modules/${kernel_version}/modules.dep | grep wistron) + ipdko=$(cat /lib/modules/${kernel_version}/modules.dep | grep ipd) + if [ "$wisko" == "" ] || [ "$ipdko" == "" ];then + depmod -a + else + if [ ! -e /lib/modules/${kernel_version}/modules.dep.bin ];then + depmod -a + else + break + fi + fi + + echo "depmod -a" + sleep 1 + else + sleep 1 + fi +done + +systemctl enable platform-modules-sw-to3200k.service +systemctl start platform-modules-sw-to3200k.service +systemctl enable to3200k-platform.service +systemctl start to3200k-platform.service +systemctl enable to3200k-led.service +systemctl start to3200k-led.service +systemctl enable to3200k-pld.service +systemctl start to3200k-pld.service + +/usr/local/bin/platform_api_mgnt.sh install diff --git a/platform/innovium/sonic-platform-modules-wistron/sw-to3200k/service/to3200k-pld.service b/platform/innovium/sonic-platform-modules-wistron/sw-to3200k/service/to3200k-pld.service new file mode 100755 index 0000000000..421a9c157d --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/sw-to3200k/service/to3200k-pld.service @@ -0,0 +1,12 @@ +[Unit] +Description=Wistron SW-TO3200K Platform PLD service +After=platform-modules-sw-to3200k.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/platform_pld +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/innovium/sonic-platform-modules-wistron/sw-to3200k/utils/platform_pld b/platform/innovium/sonic-platform-modules-wistron/sw-to3200k/utils/platform_pld new file mode 100755 index 0000000000..ce5a3dd009 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-wistron/sw-to3200k/utils/platform_pld @@ -0,0 +1,4 @@ +#!/bin/bash +sudo ipmitool raw 0x30 0x91 0xff 0xff 0xff 0xff +exit 0 +