From 9e19a9a7cfe214ef8434924290440456fcca90f2 Mon Sep 17 00:00:00 2001 From: LuiSzee Date: Sat, 18 Dec 2021 07:20:27 +0800 Subject: [PATCH] [centec] support v682-48y8c and v682-48x8c (#9349) Why I did it Adding platform support for centec v682-48y8c and v682-48x8c. V682-48y8c switch has 48 SFP+ (1G/10G/25G) ports, 8 QSFP28 (40G/100G) ports on CENTEC TsingMa.MX. V682-48y8c is different from V682-48y8c_d in that: transceiver is managed by cpu smbus rather than TsingMa.MX i2c bus. port led is managed by mcu inside TsingMa.MX. fan, psu, sensors, leds are managed by cpu smbus other than the cpu board vendor's close sourse driver. V682-48x8c switch has 48 SFP+ (1G/10G) ports, 8 QSFP28 (40G/100G) ports on CENTEC TsingMa.MX. CPU used in v682-48y8c and v682-48x8c is Intel(R) Xeon(R) CPU D-1527. How I did it Modify related code in platform and device directory. Upgrade centec sai to v1.9. upgrade python to python3 and kernel version to 5.0 for V682-48y8c_d. How to verify it Build centec amd64 sonic image, verify platform functions (port, sfp, led etc) on centec v682-48y8c and v682-48x8c board. Co-authored-by: shil --- .../V682-48x8c/V682-48x8c-board.json | 597 ++++++ .../V682-48x8c/V682-48x8c-chip-profile.txt | 116 ++ .../V682-48x8c/V682-48x8c-datapath.txt | 1022 +++++++++++ .../V682-48x8c/buffers.json.j2 | 70 + .../V682-48x8c/pg_profile_lookup.ini | 21 + .../V682-48x8c/port_config.ini | 57 + .../V682-48x8c/qos.json.j2 | 1 + .../V682-48x8c/sai.profile | 3 + .../x86_64-centec_v682_48x8c-r0/default_sku | 1 + .../x86_64-centec_v682_48x8c-r0/fancontrol | 10 + .../installer.conf | 1 + .../x86_64-centec_v682_48x8c-r0/pcie.yaml | 5 + .../x86_64-centec_v682_48x8c-r0/platform_asic | 1 + .../platform_components.json | 8 + .../platform_reboot | 15 + .../plugins/eeprom.py | 35 + .../plugins/led_control.py | 214 +++ .../plugins/psuutil.py | 62 + .../pmon_daemon_control.json | 3 + .../V682-48y8c/V682-48y8c-board.json | 597 ++++++ .../V682-48y8c/V682-48y8c-chip-profile.txt | 116 ++ .../V682-48y8c/V682-48y8c-datapath.txt | 1022 +++++++++++ .../V682-48y8c/buffers.json.j2 | 70 + .../V682-48y8c/pg_profile_lookup.ini | 21 + .../V682-48y8c/port_config.ini | 57 + .../V682-48y8c/qos.json.j2 | 1 + .../V682-48y8c/sai.profile | 3 + .../x86_64-centec_v682_48y8c-r0/default_sku | 1 + .../x86_64-centec_v682_48y8c-r0/fancontrol | 10 + .../installer.conf | 1 + .../x86_64-centec_v682_48y8c-r0/pcie.yaml | 5 + .../x86_64-centec_v682_48y8c-r0/platform_asic | 1 + .../platform_components.json | 8 + .../platform_reboot | 15 + .../plugins/eeprom.py | 35 + .../plugins/led_control.py | 214 +++ .../plugins/psuutil.py | 62 + .../pmon_daemon_control.json | 3 + .../installer.conf | 1 + .../platform_reboot | 4 +- platform/centec/one-image.mk | 2 + .../centec/platform-modules-centec-v682.mk | 12 + platform/centec/sdk.mk | 2 +- .../48x8c/modules/Makefile | 1 + .../modules/centec_v682_48x8c_platform.c | 167 ++ .../48x8c/modules/rtc-sd2405.c | 264 +++ .../48x8c/service/48x8c_platform.service | 13 + .../48x8c/service/release.py | 37 + .../48x8c/setup.py | 15 + .../48x8c/sonic_platform/__init__.py | 2 + .../48x8c/sonic_platform/chassis.py | 282 +++ .../48x8c/sonic_platform/eeprom.py | 127 ++ .../48x8c/sonic_platform/fan.py | 186 ++ .../48x8c/sonic_platform/fan_drawer.py | 49 + .../48x8c/sonic_platform/led.py | 45 + .../48x8c/sonic_platform/platform.py | 21 + .../48x8c/sonic_platform/psu.py | 29 + .../48x8c/sonic_platform/sfp.py | 1618 +++++++++++++++++ .../48x8c/sonic_platform/thermal.py | 118 ++ .../48y8c-d/service/release.py | 4 +- .../48y8c/modules/Makefile | 1 + .../modules/centec_v682_48y8c_platform.c | 167 ++ .../48y8c/modules/rtc-sd2405.c | 264 +++ .../48y8c/service/48y8c_platform.service | 13 + .../48y8c/service/release.py | 37 + .../48y8c/setup.py | 15 + .../48y8c/sonic_platform/__init__.py | 2 + .../48y8c/sonic_platform/chassis.py | 282 +++ .../48y8c/sonic_platform/eeprom.py | 127 ++ .../48y8c/sonic_platform/fan.py | 186 ++ .../48y8c/sonic_platform/fan_drawer.py | 49 + .../48y8c/sonic_platform/led.py | 45 + .../48y8c/sonic_platform/platform.py | 21 + .../48y8c/sonic_platform/psu.py | 29 + .../48y8c/sonic_platform/sfp.py | 1618 +++++++++++++++++ .../48y8c/sonic_platform/thermal.py | 118 ++ .../debian/control | 12 +- .../debian/platform-modules-v682-48x8c.init | 200 ++ .../platform-modules-v682-48x8c.install | 2 + .../platform-modules-v682-48x8c.postinst | 2 + .../debian/platform-modules-v682-48y8c-d.init | 27 +- .../platform-modules-v682-48y8c-d.install | 7 +- .../debian/platform-modules-v682-48y8c.init | 200 ++ .../platform-modules-v682-48y8c.install | 2 + .../platform-modules-v682-48y8c.postinst | 2 + .../sonic-platform-modules-v682/debian/rules | 3 +- 86 files changed, 10894 insertions(+), 20 deletions(-) create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-board.json create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-chip-profile.txt create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-datapath.txt create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/buffers.json.j2 create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/pg_profile_lookup.ini create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/port_config.ini create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/qos.json.j2 create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/sai.profile create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/default_sku create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/fancontrol create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/installer.conf create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/pcie.yaml create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/platform_asic create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/platform_components.json create mode 100755 device/centec/x86_64-centec_v682_48x8c-r0/platform_reboot create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/plugins/eeprom.py create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/plugins/led_control.py create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/plugins/psuutil.py create mode 100644 device/centec/x86_64-centec_v682_48x8c-r0/pmon_daemon_control.json create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-board.json create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-chip-profile.txt create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-datapath.txt create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/buffers.json.j2 create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/pg_profile_lookup.ini create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/port_config.ini create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/qos.json.j2 create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/sai.profile create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/default_sku create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/fancontrol create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/installer.conf create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/pcie.yaml create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/platform_asic create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/platform_components.json create mode 100755 device/centec/x86_64-centec_v682_48y8c-r0/platform_reboot create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/plugins/eeprom.py create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/plugins/led_control.py create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/plugins/psuutil.py create mode 100644 device/centec/x86_64-centec_v682_48y8c-r0/pmon_daemon_control.json create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/modules/Makefile create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/modules/centec_v682_48x8c_platform.c create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/modules/rtc-sd2405.c create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/service/48x8c_platform.service create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/service/release.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/setup.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/__init__.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/chassis.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/eeprom.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan_drawer.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/led.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/platform.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/psu.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/sfp.py create mode 100644 platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/thermal.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/modules/Makefile create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/modules/centec_v682_48y8c_platform.c create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/modules/rtc-sd2405.c create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/service/48y8c_platform.service create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/service/release.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/setup.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/__init__.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/chassis.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/eeprom.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan_drawer.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/led.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/platform.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/psu.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/sfp.py create mode 100644 platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/thermal.py create mode 100644 platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.init create mode 100644 platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.install create mode 100644 platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.postinst create mode 100644 platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.init create mode 100644 platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.install create mode 100644 platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.postinst diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-board.json b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-board.json new file mode 100644 index 000000000000..435ab418aaba --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-board.json @@ -0,0 +1,597 @@ +{ + "macleds" : { + "polarity" : 1, + "cpumode" : 1, + "maps" : [ + { + "port_id" : 32, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port0/brightness" + }, + { + "port_id" : 33, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port1/brightness" + }, + { + "port_id" : 34, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port2/brightness" + }, + { + "port_id" : 35, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port3/brightness" + }, + { + "port_id" : 0, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port4/brightness" + }, + { + "port_id" : 4, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port5/brightness" + }, + { + "port_id" : 8, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port6/brightness" + }, + { + "port_id" : 12, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port7/brightness" + }, + { + "port_id" : 16, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port8/brightness" + }, + { + "port_id" : 20, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port9/brightness" + }, + { + "port_id" : 24, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port10/brightness" + }, + { + "port_id" : 28, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port11/brightness" + }, + { + "port_id" : 40, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port12/brightness" + }, + { + "port_id" : 44, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port13/brightness" + }, + { + "port_id" : 48, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port14/brightness" + }, + { + "port_id" : 52, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port15/brightness" + }, + { + "port_id" : 56, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port16/brightness" + }, + { + "port_id" : 60, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port17/brightness" + }, + { + "port_id" : 64, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port18/brightness" + }, + { + "port_id" : 68, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port19/brightness" + }, + { + "port_id" : 72, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port20/brightness" + }, + { + "port_id" : 73, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port21/brightness" + }, + { + "port_id" : 74, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port22/brightness" + }, + { + "port_id" : 75, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port23/brightness" + }, + + { + "port_id" : 120, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port48/brightness" + }, + { + "port_id" : 124, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port49/brightness" + }, + { + "port_id" : 80, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port50/brightness" + }, + { + "port_id" : 84, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port51/brightness" + }, + + { + "port_id" : 232, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port24/brightness" + }, + { + "port_id" : 233, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port25/brightness" + }, + { + "port_id" : 234, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port26/brightness" + }, + { + "port_id" : 235, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port27/brightness" + }, + { + "port_id" : 200, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port28/brightness" + }, + { + "port_id" : 204, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port29/brightness" + }, + { + "port_id" : 208, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port30/brightness" + }, + { + "port_id" : 212, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port31/brightness" + }, + { + "port_id" : 216, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port32/brightness" + }, + { + "port_id" : 220, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port33/brightness" + }, + { + "port_id" : 224, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port34/brightness" + }, + { + "port_id" : 228, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port35/brightness" + }, + { + "port_id" : 160, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port36/brightness" + }, + { + "port_id" : 164, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port37/brightness" + }, + { + "port_id" : 168, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port38/brightness" + }, + { + "port_id" : 172, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port39/brightness" + }, + { + "port_id" : 176, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port40/brightness" + }, + { + "port_id" : 180, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port41/brightness" + }, + { + "port_id" : 184, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port42/brightness" + }, + { + "port_id" : 188, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port43/brightness" + }, + { + "port_id" : 192, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port44/brightness" + }, + { + "port_id" : 193, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port45/brightness" + }, + { + "port_id" : 194, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port46/brightness" + }, + { + "port_id" : 195, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port47/brightness" + }, + + { + "port_id" : 240, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port52/brightness" + }, + { + "port_id" : 244, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 1, + "sysfs_path" : "/sys/class/leds/port53/brightness" + }, + { + "port_id" : 280, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 1, + "sysfs_path" : "/sys/class/leds/port54/brightness" + }, + { + "port_id" : 284, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 1, + "sysfs_path" : "/sys/class/leds/port55/brightness" + }, + + { + "port_id" : 161, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + }, + { + "port_id" : 162, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + }, + { + "port_id" : 165, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + }, + { + "port_id" : 166, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + } + ] + }, + "ffe" : { + "board_material" : "BOARD_MATERIAL_M4", + "config" : [ + { + "serdes_id" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75], + "is_dac" : 1, + "speed" : [10000, 25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, -13, 46, 0, 0] + }, + { + "serdes_id" : [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 50, 52, 53, 54, 55, 56, 57, 58, 59], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 46, -8, 0] + }, + { + "serdes_id" : [0, 1, 16, 17, 18, 19, 20, 21, 22, 23], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -6, 0] + }, + { + "serdes_id" : [24, 25, 26, 27, 72, 74, 75], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -4, 0] + }, + { + "serdes_id" : [48, 49, 51, 64, 65, 66, 67, 68, 69, 70, 71, 73], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -6, 0] + }, + { + "serdes_id" : [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 50, 52, 53, 54, 55, 56, 57, 58, 59], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 44, -14, -1] + }, + { + "serdes_id" : [0, 1, 16, 17, 18, 19, 20, 21, 22, 23], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 38, -10, -2] + }, + { + "serdes_id" : [24, 25, 26, 27, 72, 74, 75], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 36, -6, -2] + }, + { + "serdes_id" : [48, 49, 51, 64, 65, 66, 67, 68, 69, 70, 71, 73], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 38, -10, -2] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 1, + "speed" : [100000, 25000, 40000, 10000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, -13, 46, 0, 0] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 1, + "speed" : [1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -4, 0] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 0, + "speed" : [100000, 25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 36, -6, -2] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 0, + "speed" : [40000, 10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -4, 0] + } + ] + } +} diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-chip-profile.txt b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-chip-profile.txt new file mode 100644 index 000000000000..9fadec5d5f6b --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-chip-profile.txt @@ -0,0 +1,116 @@ +#----------------- SDK Feature Support -------------- +[MPLS_SUPPORT] = 1; +[APS_SUPPORT] = 1; +[OAM_SUPPORT] = 1; +[PTP_SUPPORT] = 0; +[SYNCE_SUPPORT] = 0; +[STACKING_SUPPORT] = 1; +[BPE_SUPPORT] = 0; +[IPFIX_SUPPORT] = 1; +[MONITOR_SUPPORT] = 1; +[OVERLAY_SUPPORT] = 1; +[EFD_SUPPORT] = 1; +[FCOE_SUPPORT] = 0; +[TRILL_SUPPORT] = 0; +[WLAN_SUPPORT] = 0; +[NPM_SUPPORT] = 1; +[DOT1AE_SUPPORT] = 1; +[SRV6_SUPPORT] = 0; +[DTEL_SUPPORT] = 1; +[FLEXE_SUPPORT] = 0; +[FDBTOKEN_SUPPORT] = 1; + +#----------------- Chip Init Parameter -------------- +#Local chip number and global chip id +[Local chip_num] = 1 +[Local chip0] = 0 +[Local chip1] = 1 +[Port_phy_mapping] = 1 + +#Cut through mode 0: Disable; 1:10/40/100G; 2:1/10/100G; 3:1/10/40G; other:Flex, refer to CUT_THROUGH_BITMAP +[CUT_THROUGH_SPEED] = 0 +#Flex cut through mode, speed enable by bitmap, refer to ctc_port_speed_t, Notice: 10M/100M/1G treat as the same speed +[CUT_THROUGH_BITMAP] = 0 + +#Network cpu port +[CPU_NETWORK_PORT_EN] = 0 +[CPU_NETWORK_PORT_ID] = 47 + +#Enable parity error and multi-bit ecc recover +[ECC_RECOVER_EN] = 0 +[TCAM_SCAN_EN] = 0 +[SDB_EN] = 0 + +#----------------- KNET Init Parameter -------------- +[KNET_EN] = 0 + +#----------------- FTM Init Parameter -------------- +#0: not use; 1: default; 2: layer3; 3: ipv6 +[FTM Profile] = 0 + +#----------------- Interrupt Init Parameter -------------- +#0: pin, 1: msi +[Interrupt_mode] = 1 + +#----------------- NextHop Init Parameter -------------- +#0: SDK work in pizzbox (single chip system), 1: SDK work in multi-chip system +[Nexthop Edit Mode] = 0 +[External Nexthop Number] = 16384 +[MPLS Tunnel Number] = 1024 +[H_ECMP_EN] = 0 + +#----------------- L2 Init Parameter -------------- +[FDB Hw Learning] = 0 +[Logic Port Num] = 1024 +#0: 128 instance per port, 1: 64 instance per port, 2: 32 instance per port +[STP MODE] = 0 +[MAX_FID_NUM] = 5120 + +#----------------- Stats Init Parameter -------------- +[STATS_QUEUE_DEQ_EN] = 1 +[STATS_QUEUE_DROP_EN] = 1 +[STATS_FLOW_POLICER_EN] = 1 +[STATS_VLAN_EN] = 0 +[STATS_VRF_EN] = 0 +[STATS_POLICER_NUM] = 1024 +[STATS_PORT_EN] = 0 +[STATS_ECMP_EN] = 0 + +#----------------- BPE Init Parameter -------------- +[BPE_BR_PORT_EXTENDER_EN] = 0 +[BPE_BR_UC_MAX_ECID] = 1024 +[BPE_BR_MC_MAX_ECID] = 4096 +[BPE_BR_PORT_BASE] = 0 + +#----------------- Ipuc Init Parameter -------------- +#0: tcam use prefix 16; 1: tcam use prefix 8 +[IPUC_TCAM_PREFIX_8] = 1 + +#----------------- QoS Init Parameter -------------- +#QoS policer number support 1K/2K/4K/8K, default 4K +[QOS_POLICER_NUM] = 4096 +#qos queue mode 0: 8(basic)+1(cpu) +#qos queue mode 1: 8(basic)+1(span)+1(mcast) +[QOS_QUEUE_MODE] = 0 +#QoS port extend queue number support 0/4, default 0 +[QOS_PORT_EXT_QUEUE_NUM] = 0 +#QoS CPU reason queue number support 128/64/32, default 128 +[QOS_CPU_QUEUE_NUM] = 128 +[QOS_INGRESS_VLAN_POLICER_NUM] = 0 +[QOS_EGRESS_VLAN_POLICER_NUM] = 0 +#QoS the max number of igs/egs reserve macro policer,which ACL entry support micro and macro at the same time +[QOS_INGRESS_MACRO_POLICER_NUM] = 0 +[QOS_EGRESS_MACRO_POLICER_NUM] = 0 +#QOS service queue mode, default 0,0:logic scr port + dstport enq 1:service id + dstport enq +[QOS_SERVICE_QUEUE_MODE] = 0 +#mode 0:svc policer used for service policer +#mode 1:svc policer used for stormctl +[QOS_POLICER_SVC_MODE] = 0 + +#----------------- Stacking Init Parameter -------------- +#0: normal mode; 1: spine-leaf mode +[FABRIC MODE] = 0 +[STACKING VERSION] = 1 +#----------------- LB hash Init Parameter -------------- +#0: support 4 select num; 1: support 8 select num; only TM2 support mode 1 +[LB_HASH_MODE] = 0 diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-datapath.txt b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-datapath.txt new file mode 100644 index 000000000000..c77ae26c389d --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/V682-48x8c-datapath.txt @@ -0,0 +1,1022 @@ +#SERDES_MODE: 0-NONE, 1-XFI, 2-SGMII, 3-Not Support, 4-QSGMII, 7-XLG, 8-100GR4, 9-SGMII2G5 +# 13-XXVG, 14-50GR2, 16-50GR1, 17-100GR2, 18-200G, 19-400G +#SERDES_POLY: 0-No Inverse, 1-Inverse +#SERDES_SWITCH: 0-Not Support Dynamic Switch, 1-Support Dynamic Switch exclude QSGMII, 2-Support Dynamic Switch include QSGMII + +[CORE_PLL] = 1050 +[DP0_FLEXE_CLIENT_NUM] = 0 +[DP1_FLEXE_CLIENT_NUM] = 0 +[DP0_XPIPE_PORT_NUM] = 0 +[DP1_XPIPE_PORT_NUM] = 0 +[DOT1AE_ENABLE] = 1 + +#{ +[SERDES_ITEM] + +[SERDES_ID] = 7 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 0 + +[SERDES_ID] = 6 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 1 + +[SERDES_ID] = 5 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 2 + +[SERDES_ID] = 4 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 3 + +[SERDES_ID] = 3 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 4 + +[SERDES_ID] = 2 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 5 + +[SERDES_ID] = 1 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 6 + +[SERDES_ID] = 0 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 7 + +[SERDES_ID] = 11 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 8 + +[SERDES_ID] = 10 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 9 + +[SERDES_ID] = 9 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 10 + +[SERDES_ID] = 8 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 11 + +[SERDES_ID] = 12 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 12 + +[SERDES_ID] = 13 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 13 + +[SERDES_ID] = 14 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 14 + +[SERDES_ID] = 15 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 15 + +[SERDES_ID] = 16 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 16 + +[SERDES_ID] = 17 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 17 + +[SERDES_ID] = 18 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 18 + +[SERDES_ID] = 19 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 19 + +[SERDES_ID] = 20 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 20 + +[SERDES_ID] = 21 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 21 + +[SERDES_ID] = 22 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 22 + +[SERDES_ID] = 23 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 23 + +[SERDES_ID] = 24 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 24 + +[SERDES_ID] = 25 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 25 + +[SERDES_ID] = 26 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 26 + +[SERDES_ID] = 27 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 27 + +[SERDES_ID] = 28 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 28 + +[SERDES_ID] = 29 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 29 + +[SERDES_ID] = 30 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 30 + +[SERDES_ID] = 31 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 31 + +[SERDES_ID] = 36 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 32 + +[SERDES_ID] = 37 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 33 + +[SERDES_ID] = 38 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 34 + +[SERDES_ID] = 32 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 35 + +[SERDES_ID] = 39 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 36 + +[SERDES_ID] = 34 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 37 + +[SERDES_ID] = 35 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 38 + +[SERDES_ID] = 33 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 39 + +[SERDES_ID] = 40 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 40 + +[SERDES_ID] = 44 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 41 + +[SERDES_ID] = 42 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 42 + +[SERDES_ID] = 41 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 43 + +[SERDES_ID] = 43 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 44 + +[SERDES_ID] = 46 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 45 + +[SERDES_ID] = 47 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 46 + +[SERDES_ID] = 45 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 47 + +[SERDES_ID] = 49 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 48 + +[SERDES_ID] = 48 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 49 + +[SERDES_ID] = 51 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 50 + +[SERDES_ID] = 50 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 51 + +[SERDES_ID] = 53 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 52 + +[SERDES_ID] = 52 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 53 + +[SERDES_ID] = 55 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 54 + +[SERDES_ID] = 54 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 55 + +[SERDES_ID] = 57 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 56 + +[SERDES_ID] = 56 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 57 + +[SERDES_ID] = 59 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 58 + +[SERDES_ID] = 58 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 59 + +[SERDES_ID] = 60 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 60 + +[SERDES_ID] = 61 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 61 + +[SERDES_ID] = 62 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 62 + +[SERDES_ID] = 63 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 63 + +[SERDES_ID] = 70 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 64 + +[SERDES_ID] = 71 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 65 + +[SERDES_ID] = 68 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 66 + +[SERDES_ID] = 69 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 67 + +[SERDES_ID] = 66 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 68 + +[SERDES_ID] = 67 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 69 + +[SERDES_ID] = 64 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 70 + +[SERDES_ID] = 65 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 71 + +[SERDES_ID] = 74 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 72 + +[SERDES_ID] = 75 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 73 + +[SERDES_ID] = 72 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 74 + +[SERDES_ID] = 73 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 75 + +[SERDES_ID] = 76 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 76 + +[SERDES_ID] = 77 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 77 + +[SERDES_ID] = 78 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 78 + +[SERDES_ID] = 79 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 79 + +[SERDES_ID] = 83 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 80 + +[SERDES_ID] = 81 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 81 + +[SERDES_ID] = 87 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 82 + +[SERDES_ID] = 82 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 83 + +[SERDES_ID] = 86 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 84 + +[SERDES_ID] = 80 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 85 + +[SERDES_ID] = 84 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 86 + +[SERDES_ID] = 85 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 87 + +[SERDES_ID] = 95 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 88 + +[SERDES_ID] = 93 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 89 + +[SERDES_ID] = 91 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 90 + +[SERDES_ID] = 94 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 91 + +[SERDES_ID] = 90 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 92 + +[SERDES_ID] = 89 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 93 + +[SERDES_ID] = 88 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 94 + +[SERDES_ID] = 92 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 95 + +[SERDES_ID] = 96 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 96 + +[SERDES_ID] = 97 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 97 + +[SERDES_ID] = 98 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 98 + +[SERDES_ID] = 99 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 99 + +#} +[SERDES_TO_LPORT] +#{ +#index |serdes |QSGMII |SGMII/SGMII2G5/XFI/XXVG |XLG |50GR1 |50GR2 |100GR4 |100GR2 |200G |400G +#----------|----------|------------|------------------------|--------|--------|--------|--------|--------|--------|-------- +#0 |7 |NA |0 |0 |0 |0 |0 |0 |NA |NA +#1 |6 |NA |1 |0 |NA |0 |0 |NA |NA |NA +#2 |5 |NA |2 |0 |2 |2 |0 |0 |NA |NA +#3 |4 |NA |3 |0 |NA |2 |0 |NA |NA |NA +#4 |3 |NA |4 |4 |4 |4 |4 |4 |NA |NA +#5 |2 |NA |5 |4 |NA |4 |4 |NA |NA |NA +#6 |1 |NA |6 |4 |6 |6 |4 |4 |NA |NA +#7 |0 |NA |7 |4 |NA |6 |4 |NA |NA |NA +#8 |11 |NA |8 |8 |8 |8 |8 |8 |NA |NA +#9 |10 |NA |9 |8 |NA |8 |8 |NA |NA |NA +#10 |9 |NA |10 |8 |10 |10 |8 |8 |NA |NA +#11 |8 |NA |11 |8 |NA |10 |8 |NA |NA |NA +#12 |12 |NA |12 |12 |12 |12 |12 |12 |NA |NA +#13 |13 |NA |13 |12 |NA |12 |12 |NA |NA |NA +#14 |14 |NA |14 |12 |14 |14 |12 |12 |NA |NA +#15 |15 |NA |15 |12 |NA |14 |12 |NA |NA |NA +#16 |16 |NA |16 |16 |16 |16 |16 |16 |NA |NA +#17 |17 |NA |17 |16 |NA |16 |16 |NA |NA |NA +#18 |18 |NA |18 |16 |18 |18 |16 |16 |NA |NA +#19 |19 |NA |19 |16 |NA |18 |16 |NA |NA |NA +#20 |20 |NA |20 |20 |20 |20 |20 |20 |NA |NA +#21 |21 |NA |21 |20 |NA |20 |20 |NA |NA |NA +#22 |22 |NA |22 |20 |22 |22 |20 |20 |NA |NA +#23 |23 |NA |23 |20 |NA |22 |20 |NA |NA |NA +#24 |24 |NA |24 |24 |24 |24 |24 |24 |NA |NA +#25 |25 |NA |25 |24 |NA |24 |24 |NA |NA |NA +#26 |26 |NA |26 |24 |26 |26 |24 |24 |NA |NA +#27 |27 |NA |27 |24 |NA |26 |24 |NA |NA |NA +#28 |28 |NA |28 |28 |28 |28 |28 |28 |NA |NA +#29 |29 |NA |29 |28 |NA |28 |28 |NA |NA |NA +#30 |30 |NA |30 |28 |30 |30 |28 |28 |NA |NA +#31 |31 |NA |31 |28 |NA |30 |28 |NA |NA |NA +#32 |36 |NA |32 |32 |32 |32 |32 |32 |32 |32 +#33 |37 |NA |33 |32 |33 |32 |32 |32 |32 |32 +#34 |38 |NA |34 |32 |34 |34 |32 |34 |32 |32 +#35 |32 |NA |35 |32 |35 |34 |32 |34 |32 |32 +#36 |39 |NA |36 |36 |36 |36 |36 |36 |36 |32 +#37 |34 |NA |37 |36 |37 |36 |36 |36 |36 |32 +#38 |35 |NA |38 |36 |38 |38 |36 |38 |36 |32 +#39 |33 |NA |39 |36 |39 |38 |36 |38 |36 |32 +#40 |40 |NA |40 |40 |40 |40 |40 |40 |40 |40 +#41 |44 |NA |41 |40 |41 |40 |40 |40 |40 |40 +#42 |42 |NA |42 |40 |42 |42 |40 |42 |40 |40 +#43 |41 |NA |43 |40 |43 |42 |40 |42 |40 |40 +#44 |43 |NA |44 |44 |44 |44 |44 |44 |44 |40 +#45 |46 |NA |45 |44 |45 |44 |44 |44 |44 |40 +#46 |47 |NA |46 |44 |46 |46 |44 |46 |44 |40 +#47 |45 |NA |47 |44 |47 |46 |44 |46 |44 |40 +#48 |49 |NA |48 |48 |48 |48 |48 |48 |NA |NA +#49 |48 |NA |49 |48 |NA |48 |48 |NA |NA |NA +#50 |51 |NA |50 |48 |50 |50 |48 |48 |NA |NA +#51 |50 |NA |51 |48 |NA |50 |48 |NA |NA |NA +#52 |53 |NA |52 |52 |52 |52 |52 |52 |NA |NA +#53 |52 |NA |53 |52 |NA |52 |52 |NA |NA |NA +#54 |55 |NA |54 |52 |54 |54 |52 |52 |NA |NA +#55 |54 |NA |55 |52 |NA |54 |52 |NA |NA |NA +#56 |57 |NA |56 |56 |56 |56 |56 |56 |NA |NA +#57 |56 |NA |57 |56 |NA |56 |56 |NA |NA |NA +#58 |59 |NA |58 |56 |58 |58 |56 |56 |NA |NA +#59 |58 |NA |59 |56 |NA |58 |56 |NA |NA |NA +#60 |60 |NA |60 |60 |60 |60 |60 |60 |NA |NA +#61 |61 |NA |61 |60 |NA |60 |60 |NA |NA |NA +#62 |62 |NA |62 |60 |62 |62 |60 |60 |NA |NA +#63 |63 |NA |63 |60 |NA |62 |60 |NA |NA |NA +#64 |70 |NA |64 |64 |64 |64 |64 |64 |NA |NA +#65 |71 |NA |65 |64 |NA |64 |64 |NA |NA |NA +#66 |68 |NA |66 |64 |66 |66 |64 |64 |NA |NA +#67 |69 |NA |67 |64 |NA |66 |64 |NA |NA |NA +#68 |66 |NA |68 |68 |68 |68 |68 |68 |NA |NA +#69 |67 |NA |69 |68 |NA |68 |68 |NA |NA |NA +#70 |64 |NA |70 |68 |70 |70 |68 |68 |NA |NA +#71 |65 |NA |71 |68 |NA |70 |68 |NA |NA |NA +#72 |74 |NA |72 |72 |72 |72 |72 |72 |NA |NA +#73 |75 |NA |73 |72 |NA |72 |72 |NA |NA |NA +#74 |72 |NA |74 |72 |74 |74 |72 |72 |NA |NA +#75 |73 |NA |75 |72 |NA |74 |72 |NA |NA |NA +#76 |76 |NA |76 |76 |76 |76 |76 |76 |NA |NA +#77 |77 |NA |77 |76 |NA |76 |76 |NA |NA |NA +#78 |78 |NA |78 |76 |78 |78 |76 |76 |NA |NA +#79 |79 |NA |79 |76 |NA |78 |76 |NA |NA |NA +#80 |83 |NA |80 |80 |80 |80 |80 |80 |80 |80 +#81 |81 |NA |81 |80 |81 |80 |80 |80 |80 |80 +#82 |87 |NA |82 |80 |82 |82 |80 |82 |80 |80 +#83 |82 |NA |83 |80 |83 |82 |80 |82 |80 |80 +#84 |86 |NA |84 |84 |84 |84 |84 |84 |84 |80 +#85 |80 |NA |85 |84 |85 |84 |84 |84 |84 |80 +#86 |84 |NA |86 |84 |86 |86 |84 |86 |84 |80 +#87 |85 |NA |87 |84 |87 |86 |84 |86 |84 |80 +#88 |95 |NA |88 |88 |88 |88 |88 |88 |88 |88 +#89 |93 |NA |89 |88 |89 |88 |88 |88 |88 |88 +#90 |91 |NA |90 |88 |90 |90 |88 |90 |88 |88 +#91 |94 |NA |91 |88 |91 |90 |88 |90 |88 |88 +#92 |90 |NA |92 |92 |92 |92 |92 |92 |92 |88 +#93 |89 |NA |93 |92 |93 |92 |92 |92 |92 |88 +#94 |88 |NA |94 |92 |94 |94 |92 |94 |92 |88 +#95 |92 |NA |95 |92 |95 |94 |92 |94 |92 |88 +#96 |96 |NA |232 |232 |232 |232 |232 |232 |NA |NA +#97 |97 |NA |233 |232 |NA |232 |232 |NA |NA |NA +#98 |98 |NA |243 |232 |243 |243 |232 |232 |NA |NA +#99 |99 |NA |244 |232 |NA |243 |232 |NA |NA |NA +#} + diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/buffers.json.j2 b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/pg_profile_lookup.ini b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/port_config.ini b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/port_config.ini new file mode 100644 index 000000000000..1dca36d97f66 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed fec +Ethernet0 32 eth-0-1 0 10000 none +Ethernet1 33 eth-0-2 1 10000 none +Ethernet2 34 eth-0-3 2 10000 none +Ethernet3 35 eth-0-4 3 10000 none +Ethernet4 0 eth-0-5 4 10000 none +Ethernet5 4 eth-0-6 5 10000 none +Ethernet6 8 eth-0-7 6 10000 none +Ethernet7 12 eth-0-8 7 10000 none +Ethernet8 16 eth-0-9 8 10000 none +Ethernet9 20 eth-0-10 9 10000 none +Ethernet10 24 eth-0-11 10 10000 none +Ethernet11 28 eth-0-12 11 10000 none +Ethernet12 40 eth-0-13 12 10000 none +Ethernet13 44 eth-0-14 13 10000 none +Ethernet14 48 eth-0-15 14 10000 none +Ethernet15 52 eth-0-16 15 10000 none +Ethernet16 56 eth-0-17 16 10000 none +Ethernet17 60 eth-0-18 17 10000 none +Ethernet18 64 eth-0-19 18 10000 none +Ethernet19 68 eth-0-20 19 10000 none +Ethernet20 72 eth-0-21 20 10000 none +Ethernet21 73 eth-0-22 21 10000 none +Ethernet22 74 eth-0-23 22 10000 none +Ethernet23 75 eth-0-24 23 10000 none +Ethernet24 232 eth-0-25 24 10000 none +Ethernet25 233 eth-0-26 25 10000 none +Ethernet26 234 eth-0-27 26 10000 none +Ethernet27 235 eth-0-28 27 10000 none +Ethernet28 200 eth-0-29 28 10000 none +Ethernet29 204 eth-0-30 29 10000 none +Ethernet30 208 eth-0-31 30 10000 none +Ethernet31 212 eth-0-32 31 10000 none +Ethernet32 216 eth-0-33 32 10000 none +Ethernet33 220 eth-0-34 33 10000 none +Ethernet34 224 eth-0-35 34 10000 none +Ethernet35 228 eth-0-36 35 10000 none +Ethernet36 160 eth-0-37 36 10000 none +Ethernet37 164 eth-0-38 37 10000 none +Ethernet38 168 eth-0-39 38 10000 none +Ethernet39 172 eth-0-40 39 10000 none +Ethernet40 176 eth-0-41 40 10000 none +Ethernet41 180 eth-0-42 41 10000 none +Ethernet42 184 eth-0-43 42 10000 none +Ethernet43 188 eth-0-44 43 10000 none +Ethernet44 192 eth-0-45 44 10000 none +Ethernet45 193 eth-0-46 45 10000 none +Ethernet46 194 eth-0-47 46 10000 none +Ethernet47 195 eth-0-48 47 10000 none +Ethernet48 120,121,122,123 eth-0-49 48 100000 none +Ethernet49 124,125,126,127 eth-0-50 49 100000 none +Ethernet50 80,81,82,83 eth-0-51 50 100000 none +Ethernet51 84,85,86,87 eth-0-52 51 100000 none +Ethernet52 240,241,242,243 eth-0-53 52 100000 none +Ethernet53 244,245,246,247 eth-0-54 53 100000 none +Ethernet54 280,281,282,283 eth-0-55 54 100000 none +Ethernet55 284,285,286,287 eth-0-56 55 100000 none diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/qos.json.j2 b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/sai.profile b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/sai.profile new file mode 100644 index 000000000000..314a045bffcc --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/V682-48x8c/sai.profile @@ -0,0 +1,3 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/V682-48x8c-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/usr/share/sonic/hwsku/V682-48x8c-datapath.txt +SAI_PLATFORM_CFG_FILE=/usr/share/sonic/hwsku/V682-48x8c-board.json diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/default_sku b/device/centec/x86_64-centec_v682_48x8c-r0/default_sku new file mode 100644 index 000000000000..a3168b7a0c3c --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/default_sku @@ -0,0 +1 @@ +V682-48x8c l2 diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/fancontrol b/device/centec/x86_64-centec_v682_48x8c-r0/fancontrol new file mode 100644 index 000000000000..07420a6dba06 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-0049 hwmon2=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-9/9-002c hwmon3=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-9/9-002e +DEVNAME=hwmon1=lm77 hwmon2=adt7470 hwmon3=adt7470 +FCTEMPS=hwmon2/pwm1=hwmon1/temp1_input hwmon2/pwm2=hwmon1/temp1_input hwmon2/pwm3=hwmon1/temp1_input hwmon2/pwm4=hwmon1/temp1_input hwmon3/pwm1=hwmon1/temp1_input hwmon3/pwm2=hwmon1/temp1_input hwmon3/pwm3=hwmon1/temp1_input hwmon3/pwm4=hwmon1/temp1_input +FCFANS=hwmon2/pwm1=hwmon2/fan1_input hwmon2/pwm2=hwmon2/fan2_input hwmon2/pwm3=hwmon2/fan3_input hwmon2/pwm4=hwmon2/fan4_input hwmon3/pwm1=hwmon3/fan1_input hwmon3/pwm2=hwmon3/fan2_input hwmon3/pwm3=hwmon3/fan3_input hwmon3/pwm4=hwmon3/fan4_input +MINTEMP=hwmon2/pwm1=20 hwmon2/pwm2=20 hwmon2/pwm3=20 hwmon2/pwm4=20 hwmon3/pwm1=20 hwmon3/pwm2=20 hwmon3/pwm3=20 hwmon3/pwm4=20 +MAXTEMP=hwmon2/pwm1=60 hwmon2/pwm2=60 hwmon2/pwm3=60 hwmon2/pwm4=60 hwmon3/pwm1=60 hwmon3/pwm2=60 hwmon3/pwm3=60 hwmon3/pwm4=60 +MINSTART=hwmon2/pwm1=150 hwmon2/pwm2=150 hwmon2/pwm3=150 hwmon2/pwm4=150 hwmon3/pwm1=150 hwmon3/pwm2=150 hwmon3/pwm3=150 hwmon3/pwm4=150 +MINSTOP=hwmon2/pwm1=0 hwmon2/pwm2=0 hwmon2/pwm3=0 hwmon2/pwm4=0 hwmon3/pwm1=0 hwmon3/pwm2=0 hwmon3/pwm3=0 hwmon3/pwm4=0 diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/installer.conf b/device/centec/x86_64-centec_v682_48x8c-r0/installer.conf new file mode 100644 index 000000000000..3b97b7f99da2 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="iommu=pt" diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/pcie.yaml b/device/centec/x86_64-centec_v682_48x8c-r0/pcie.yaml new file mode 100644 index 000000000000..5e00e24bc079 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/pcie.yaml @@ -0,0 +1,5 @@ +- bus: '05' + dev: '00' + fn: '0' + id: 8180 + name: 'Communication controller: Device cb10:8180' diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/platform_asic b/device/centec/x86_64-centec_v682_48x8c-r0/platform_asic new file mode 100644 index 000000000000..74dac3505ea6 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/platform_asic @@ -0,0 +1 @@ +centec diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/platform_components.json b/device/centec/x86_64-centec_v682_48x8c-r0/platform_components.json new file mode 100644 index 000000000000..4eb9f0277b9b --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "V682-48X8C": { + "component": { + } + } + } +} diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/platform_reboot b/device/centec/x86_64-centec_v682_48x8c-r0/platform_reboot new file mode 100755 index 000000000000..5e49eecb61ca --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/platform_reboot @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import time + +def main(): + os.system('hwclock -w -f /dev/rtc1') + time.sleep(1) + + os.system('i2cset -y 0 0x36 0x23 0') + time.sleep(1) + os.system('i2cset -y 0 0x36 0x23 1') + +if __name__ == '__main__': + main() diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/plugins/eeprom.py b/device/centec/x86_64-centec_v682_48x8c-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7093e4b0f825 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/plugins/eeprom.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +############################################################################# +# Centec V682-48X8C +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os + from sonic_eeprom import eeprom_tlvinfo + from sonic_py_common import device_info +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + self.eeprom_path = platform_path + '/eeprom_file' + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/plugins/led_control.py b/device/centec/x86_64-centec_v682_48x8c-r0/plugins/led_control.py new file mode 100644 index 000000000000..b787320d7840 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/plugins/led_control.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + import os + import re + import syslog + import collections + from sonic_led.led_control_base import LedControlBase + from sonic_py_common import device_info + from subprocess import Popen +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + # Constructor + def __init__(self): + + self.mac_to_led = { + 32 : 0, + 33 : 1, + 34 : 2, + 35 : 3, + 0 : 4, + 4 : 5, + 8 : 6, + 12 : 7, + 16 : 8, + 20 : 9, + 24 : 10, + 28 : 11, + 40 : 12, + 44 : 13, + 48 : 14, + 52 : 15, + 56 : 16, + 60 : 17, + 64 : 18, + 68 : 19, + 72 : 20, + 73 : 21, + 74 : 22, + 75 : 23, + 232: 24, + 233: 25, + 234: 26, + 235: 27, + 200: 28, + 204: 29, + 208: 30, + 212: 31, + 216: 32, + 220: 33, + 224: 34, + 228: 35, + 160: 36, + 164: 37, + 168: 38, + 172: 39, + 176: 40, + 180: 41, + 184: 42, + 188: 43, + 192: 44, + 193: 45, + 194: 46, + 195: 47, + 120: 48, + 121: -1, + 122: -1, + 123: -1, + 124: 49, + 125: -1, + 126: -1, + 127: -1, + 80 : 50, + 81 : -1, + 82 : -1, + 83 : -1, + 84 : 51, + 85 : -1, + 86 : -1, + 87 : -1, + 240: 52, + 241: -1, + 242: -1, + 243: -1, + 244: 53, + 245: -1, + 246: -1, + 247: -1, + 280: 54, + 281: -1, + 282: -1, + 283: -1, + 284: 55, + 285: -1, + 286: -1, + 287: -1, + } + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "V682-48x8c", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + self.LED_MODE_UP = [5, 5] + self.LED_MODE_DOWN = [7, 7] + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + for port_cfg in self._port_cfgs: + if port_name == port_cfg.name: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + return None + return led + return None + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[1] if port_idx >= 48 else self.LED_MODE_UP[0] + else: + return self.LED_MODE_DOWN[1] if port_idx >= 48 else self.LED_MODE_DOWN[0] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + cmd = 'i2cset -y 0 0x36 0x2 0x5' + Popen(cmd, shell=True) + DBG_PRINT("init system led to normal") + cmd = 'i2cset -y 0 0x36 0x3 0x1' + Popen(cmd, shell=True) + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for port_cfg in self._port_cfgs: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + continue + defmode = self._port_state_to_mode(led, "down") + with open(self.f_led.format("port{}".format(led)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(led, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + if port_idx is None: + return + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/plugins/psuutil.py b/device/centec/x86_64-centec_v682_48x8c-r0/plugins/psuutil.py new file mode 100644 index 000000000000..9e311d9b4f5a --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/plugins/psuutil.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +from subprocess import Popen, PIPE, STDOUT + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + 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 + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + powergood = ((status & (1 << (3 * (index - 1) + 2))) != 0) + return powergood + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + presence = ((status & (1 << (3 * (index - 1) + 1))) == 0) + return presence diff --git a/device/centec/x86_64-centec_v682_48x8c-r0/pmon_daemon_control.json b/device/centec/x86_64-centec_v682_48x8c-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..0db3279e44b0 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48x8c-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-board.json b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-board.json new file mode 100644 index 000000000000..435ab418aaba --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-board.json @@ -0,0 +1,597 @@ +{ + "macleds" : { + "polarity" : 1, + "cpumode" : 1, + "maps" : [ + { + "port_id" : 32, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port0/brightness" + }, + { + "port_id" : 33, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port1/brightness" + }, + { + "port_id" : 34, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port2/brightness" + }, + { + "port_id" : 35, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port3/brightness" + }, + { + "port_id" : 0, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port4/brightness" + }, + { + "port_id" : 4, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port5/brightness" + }, + { + "port_id" : 8, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port6/brightness" + }, + { + "port_id" : 12, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port7/brightness" + }, + { + "port_id" : 16, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port8/brightness" + }, + { + "port_id" : 20, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port9/brightness" + }, + { + "port_id" : 24, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port10/brightness" + }, + { + "port_id" : 28, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port11/brightness" + }, + { + "port_id" : 40, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port12/brightness" + }, + { + "port_id" : 44, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port13/brightness" + }, + { + "port_id" : 48, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port14/brightness" + }, + { + "port_id" : 52, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port15/brightness" + }, + { + "port_id" : 56, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port16/brightness" + }, + { + "port_id" : 60, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port17/brightness" + }, + { + "port_id" : 64, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port18/brightness" + }, + { + "port_id" : 68, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port19/brightness" + }, + { + "port_id" : 72, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port20/brightness" + }, + { + "port_id" : 73, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port21/brightness" + }, + { + "port_id" : 74, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port22/brightness" + }, + { + "port_id" : 75, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port23/brightness" + }, + + { + "port_id" : 120, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port48/brightness" + }, + { + "port_id" : 124, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port49/brightness" + }, + { + "port_id" : 80, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port50/brightness" + }, + { + "port_id" : 84, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port51/brightness" + }, + + { + "port_id" : 232, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port24/brightness" + }, + { + "port_id" : 233, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port25/brightness" + }, + { + "port_id" : 234, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port26/brightness" + }, + { + "port_id" : 235, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port27/brightness" + }, + { + "port_id" : 200, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port28/brightness" + }, + { + "port_id" : 204, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port29/brightness" + }, + { + "port_id" : 208, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port30/brightness" + }, + { + "port_id" : 212, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port31/brightness" + }, + { + "port_id" : 216, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port32/brightness" + }, + { + "port_id" : 220, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port33/brightness" + }, + { + "port_id" : 224, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port34/brightness" + }, + { + "port_id" : 228, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port35/brightness" + }, + { + "port_id" : 160, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port36/brightness" + }, + { + "port_id" : 164, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port37/brightness" + }, + { + "port_id" : 168, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port38/brightness" + }, + { + "port_id" : 172, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port39/brightness" + }, + { + "port_id" : 176, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port40/brightness" + }, + { + "port_id" : 180, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port41/brightness" + }, + { + "port_id" : 184, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port42/brightness" + }, + { + "port_id" : 188, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port43/brightness" + }, + { + "port_id" : 192, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port44/brightness" + }, + { + "port_id" : 193, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port45/brightness" + }, + { + "port_id" : 194, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port46/brightness" + }, + { + "port_id" : 195, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port47/brightness" + }, + + { + "port_id" : 240, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port52/brightness" + }, + { + "port_id" : 244, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 1, + "sysfs_path" : "/sys/class/leds/port53/brightness" + }, + { + "port_id" : 280, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 1, + "sysfs_path" : "/sys/class/leds/port54/brightness" + }, + { + "port_id" : 284, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_2_FORCE_OFF", + "fixed" : 1, + "sysfs_path" : "/sys/class/leds/port55/brightness" + }, + + { + "port_id" : 161, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + }, + { + "port_id" : 162, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + }, + { + "port_id" : 165, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + }, + { + "port_id" : 166, + "lchip" : 0, + "ctl_id" : 1, + "mode" : "LED_MODE_1_FORCE_OFF", + "fixed" : 0 + } + ] + }, + "ffe" : { + "board_material" : "BOARD_MATERIAL_M4", + "config" : [ + { + "serdes_id" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75], + "is_dac" : 1, + "speed" : [10000, 25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, -13, 46, 0, 0] + }, + { + "serdes_id" : [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 50, 52, 53, 54, 55, 56, 57, 58, 59], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 46, -8, 0] + }, + { + "serdes_id" : [0, 1, 16, 17, 18, 19, 20, 21, 22, 23], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -6, 0] + }, + { + "serdes_id" : [24, 25, 26, 27, 72, 74, 75], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -4, 0] + }, + { + "serdes_id" : [48, 49, 51, 64, 65, 66, 67, 68, 69, 70, 71, 73], + "is_dac" : 0, + "speed" : [10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -6, 0] + }, + { + "serdes_id" : [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 50, 52, 53, 54, 55, 56, 57, 58, 59], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 44, -14, -1] + }, + { + "serdes_id" : [0, 1, 16, 17, 18, 19, 20, 21, 22, 23], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 38, -10, -2] + }, + { + "serdes_id" : [24, 25, 26, 27, 72, 74, 75], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 36, -6, -2] + }, + { + "serdes_id" : [48, 49, 51, 64, 65, 66, 67, 68, 69, 70, 71, 73], + "is_dac" : 0, + "speed" : [25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 38, -10, -2] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 1, + "speed" : [100000, 25000, 40000, 10000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, -13, 46, 0, 0] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 1, + "speed" : [1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -4, 0] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 0, + "speed" : [100000, 25000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 36, -6, -2] + }, + { + "serdes_id" : [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], + "is_dac" : 0, + "speed" : [40000, 10000, 1000], + + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 0, 42, -4, 0] + } + ] + } +} diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-chip-profile.txt b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-chip-profile.txt new file mode 100644 index 000000000000..9fadec5d5f6b --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-chip-profile.txt @@ -0,0 +1,116 @@ +#----------------- SDK Feature Support -------------- +[MPLS_SUPPORT] = 1; +[APS_SUPPORT] = 1; +[OAM_SUPPORT] = 1; +[PTP_SUPPORT] = 0; +[SYNCE_SUPPORT] = 0; +[STACKING_SUPPORT] = 1; +[BPE_SUPPORT] = 0; +[IPFIX_SUPPORT] = 1; +[MONITOR_SUPPORT] = 1; +[OVERLAY_SUPPORT] = 1; +[EFD_SUPPORT] = 1; +[FCOE_SUPPORT] = 0; +[TRILL_SUPPORT] = 0; +[WLAN_SUPPORT] = 0; +[NPM_SUPPORT] = 1; +[DOT1AE_SUPPORT] = 1; +[SRV6_SUPPORT] = 0; +[DTEL_SUPPORT] = 1; +[FLEXE_SUPPORT] = 0; +[FDBTOKEN_SUPPORT] = 1; + +#----------------- Chip Init Parameter -------------- +#Local chip number and global chip id +[Local chip_num] = 1 +[Local chip0] = 0 +[Local chip1] = 1 +[Port_phy_mapping] = 1 + +#Cut through mode 0: Disable; 1:10/40/100G; 2:1/10/100G; 3:1/10/40G; other:Flex, refer to CUT_THROUGH_BITMAP +[CUT_THROUGH_SPEED] = 0 +#Flex cut through mode, speed enable by bitmap, refer to ctc_port_speed_t, Notice: 10M/100M/1G treat as the same speed +[CUT_THROUGH_BITMAP] = 0 + +#Network cpu port +[CPU_NETWORK_PORT_EN] = 0 +[CPU_NETWORK_PORT_ID] = 47 + +#Enable parity error and multi-bit ecc recover +[ECC_RECOVER_EN] = 0 +[TCAM_SCAN_EN] = 0 +[SDB_EN] = 0 + +#----------------- KNET Init Parameter -------------- +[KNET_EN] = 0 + +#----------------- FTM Init Parameter -------------- +#0: not use; 1: default; 2: layer3; 3: ipv6 +[FTM Profile] = 0 + +#----------------- Interrupt Init Parameter -------------- +#0: pin, 1: msi +[Interrupt_mode] = 1 + +#----------------- NextHop Init Parameter -------------- +#0: SDK work in pizzbox (single chip system), 1: SDK work in multi-chip system +[Nexthop Edit Mode] = 0 +[External Nexthop Number] = 16384 +[MPLS Tunnel Number] = 1024 +[H_ECMP_EN] = 0 + +#----------------- L2 Init Parameter -------------- +[FDB Hw Learning] = 0 +[Logic Port Num] = 1024 +#0: 128 instance per port, 1: 64 instance per port, 2: 32 instance per port +[STP MODE] = 0 +[MAX_FID_NUM] = 5120 + +#----------------- Stats Init Parameter -------------- +[STATS_QUEUE_DEQ_EN] = 1 +[STATS_QUEUE_DROP_EN] = 1 +[STATS_FLOW_POLICER_EN] = 1 +[STATS_VLAN_EN] = 0 +[STATS_VRF_EN] = 0 +[STATS_POLICER_NUM] = 1024 +[STATS_PORT_EN] = 0 +[STATS_ECMP_EN] = 0 + +#----------------- BPE Init Parameter -------------- +[BPE_BR_PORT_EXTENDER_EN] = 0 +[BPE_BR_UC_MAX_ECID] = 1024 +[BPE_BR_MC_MAX_ECID] = 4096 +[BPE_BR_PORT_BASE] = 0 + +#----------------- Ipuc Init Parameter -------------- +#0: tcam use prefix 16; 1: tcam use prefix 8 +[IPUC_TCAM_PREFIX_8] = 1 + +#----------------- QoS Init Parameter -------------- +#QoS policer number support 1K/2K/4K/8K, default 4K +[QOS_POLICER_NUM] = 4096 +#qos queue mode 0: 8(basic)+1(cpu) +#qos queue mode 1: 8(basic)+1(span)+1(mcast) +[QOS_QUEUE_MODE] = 0 +#QoS port extend queue number support 0/4, default 0 +[QOS_PORT_EXT_QUEUE_NUM] = 0 +#QoS CPU reason queue number support 128/64/32, default 128 +[QOS_CPU_QUEUE_NUM] = 128 +[QOS_INGRESS_VLAN_POLICER_NUM] = 0 +[QOS_EGRESS_VLAN_POLICER_NUM] = 0 +#QoS the max number of igs/egs reserve macro policer,which ACL entry support micro and macro at the same time +[QOS_INGRESS_MACRO_POLICER_NUM] = 0 +[QOS_EGRESS_MACRO_POLICER_NUM] = 0 +#QOS service queue mode, default 0,0:logic scr port + dstport enq 1:service id + dstport enq +[QOS_SERVICE_QUEUE_MODE] = 0 +#mode 0:svc policer used for service policer +#mode 1:svc policer used for stormctl +[QOS_POLICER_SVC_MODE] = 0 + +#----------------- Stacking Init Parameter -------------- +#0: normal mode; 1: spine-leaf mode +[FABRIC MODE] = 0 +[STACKING VERSION] = 1 +#----------------- LB hash Init Parameter -------------- +#0: support 4 select num; 1: support 8 select num; only TM2 support mode 1 +[LB_HASH_MODE] = 0 diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-datapath.txt b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-datapath.txt new file mode 100644 index 000000000000..c3bf7e2d4abf --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/V682-48y8c-datapath.txt @@ -0,0 +1,1022 @@ +#SERDES_MODE: 0-NONE, 1-XFI, 2-SGMII, 3-Not Support, 4-QSGMII, 7-XLG, 8-100GR4, 9-SGMII2G5 +# 13-XXVG, 14-50GR2, 16-50GR1, 17-100GR2, 18-200G, 19-400G +#SERDES_POLY: 0-No Inverse, 1-Inverse +#SERDES_SWITCH: 0-Not Support Dynamic Switch, 1-Support Dynamic Switch exclude QSGMII, 2-Support Dynamic Switch include QSGMII + +[CORE_PLL] = 1050 +[DP0_FLEXE_CLIENT_NUM] = 0 +[DP1_FLEXE_CLIENT_NUM] = 0 +[DP0_XPIPE_PORT_NUM] = 0 +[DP1_XPIPE_PORT_NUM] = 0 +[DOT1AE_ENABLE] = 1 + +#{ +[SERDES_ITEM] + +[SERDES_ID] = 7 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 0 + +[SERDES_ID] = 6 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 1 + +[SERDES_ID] = 5 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 2 + +[SERDES_ID] = 4 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 3 + +[SERDES_ID] = 3 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 4 + +[SERDES_ID] = 2 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 5 + +[SERDES_ID] = 1 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 6 + +[SERDES_ID] = 0 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 7 + +[SERDES_ID] = 11 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 8 + +[SERDES_ID] = 10 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 9 + +[SERDES_ID] = 9 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 10 + +[SERDES_ID] = 8 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 11 + +[SERDES_ID] = 12 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 12 + +[SERDES_ID] = 13 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 13 + +[SERDES_ID] = 14 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 14 + +[SERDES_ID] = 15 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 15 + +[SERDES_ID] = 16 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 16 + +[SERDES_ID] = 17 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 17 + +[SERDES_ID] = 18 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 18 + +[SERDES_ID] = 19 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 19 + +[SERDES_ID] = 20 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 20 + +[SERDES_ID] = 21 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 21 + +[SERDES_ID] = 22 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 22 + +[SERDES_ID] = 23 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 23 + +[SERDES_ID] = 24 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 24 + +[SERDES_ID] = 25 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 25 + +[SERDES_ID] = 26 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 26 + +[SERDES_ID] = 27 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 27 + +[SERDES_ID] = 28 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 28 + +[SERDES_ID] = 29 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 29 + +[SERDES_ID] = 30 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 30 + +[SERDES_ID] = 31 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 31 + +[SERDES_ID] = 36 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 32 + +[SERDES_ID] = 37 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 33 + +[SERDES_ID] = 38 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 34 + +[SERDES_ID] = 32 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 35 + +[SERDES_ID] = 39 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 36 + +[SERDES_ID] = 34 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 37 + +[SERDES_ID] = 35 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 38 + +[SERDES_ID] = 33 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 39 + +[SERDES_ID] = 40 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 40 + +[SERDES_ID] = 44 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 41 + +[SERDES_ID] = 42 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 42 + +[SERDES_ID] = 41 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 43 + +[SERDES_ID] = 43 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 44 + +[SERDES_ID] = 46 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 45 + +[SERDES_ID] = 47 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 46 + +[SERDES_ID] = 45 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 47 + +[SERDES_ID] = 49 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 48 + +[SERDES_ID] = 48 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 49 + +[SERDES_ID] = 51 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 50 + +[SERDES_ID] = 50 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 51 + +[SERDES_ID] = 53 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 52 + +[SERDES_ID] = 52 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 53 + +[SERDES_ID] = 55 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 54 + +[SERDES_ID] = 54 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 55 + +[SERDES_ID] = 57 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 56 + +[SERDES_ID] = 56 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 57 + +[SERDES_ID] = 59 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 58 + +[SERDES_ID] = 58 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 59 + +[SERDES_ID] = 60 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 60 + +[SERDES_ID] = 61 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 61 + +[SERDES_ID] = 62 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 62 + +[SERDES_ID] = 63 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 63 + +[SERDES_ID] = 70 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 64 + +[SERDES_ID] = 71 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 65 + +[SERDES_ID] = 68 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 66 + +[SERDES_ID] = 69 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 67 + +[SERDES_ID] = 66 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 68 + +[SERDES_ID] = 67 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 69 + +[SERDES_ID] = 64 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 70 + +[SERDES_ID] = 65 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 71 + +[SERDES_ID] = 74 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 72 + +[SERDES_ID] = 75 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 73 + +[SERDES_ID] = 72 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 74 + +[SERDES_ID] = 73 +[SERDES_MODE] = 13 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 75 + +[SERDES_ID] = 76 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 76 + +[SERDES_ID] = 77 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 77 + +[SERDES_ID] = 78 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 78 + +[SERDES_ID] = 79 +[SERDES_MODE] = 0 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 79 + +[SERDES_ID] = 83 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 80 + +[SERDES_ID] = 81 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 81 + +[SERDES_ID] = 87 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 82 + +[SERDES_ID] = 82 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 83 + +[SERDES_ID] = 86 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 84 + +[SERDES_ID] = 80 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 85 + +[SERDES_ID] = 84 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 86 + +[SERDES_ID] = 85 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 87 + +[SERDES_ID] = 95 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 88 + +[SERDES_ID] = 93 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 89 + +[SERDES_ID] = 91 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 90 + +[SERDES_ID] = 94 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 91 + +[SERDES_ID] = 90 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 92 + +[SERDES_ID] = 89 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 93 + +[SERDES_ID] = 88 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 94 + +[SERDES_ID] = 92 +[SERDES_MODE] = 8 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 95 + +[SERDES_ID] = 96 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 96 + +[SERDES_ID] = 97 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 97 + +[SERDES_ID] = 98 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 98 + +[SERDES_ID] = 99 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 +[SERDES_XPIPE] = 0 +[INDEX] = 99 + +#} +[SERDES_TO_LPORT] +#{ +#index |serdes |QSGMII |SGMII/SGMII2G5/XFI/XXVG |XLG |50GR1 |50GR2 |100GR4 |100GR2 |200G |400G +#----------|----------|------------|------------------------|--------|--------|--------|--------|--------|--------|-------- +#0 |7 |NA |0 |0 |0 |0 |0 |0 |NA |NA +#1 |6 |NA |1 |0 |NA |0 |0 |NA |NA |NA +#2 |5 |NA |2 |0 |2 |2 |0 |0 |NA |NA +#3 |4 |NA |3 |0 |NA |2 |0 |NA |NA |NA +#4 |3 |NA |4 |4 |4 |4 |4 |4 |NA |NA +#5 |2 |NA |5 |4 |NA |4 |4 |NA |NA |NA +#6 |1 |NA |6 |4 |6 |6 |4 |4 |NA |NA +#7 |0 |NA |7 |4 |NA |6 |4 |NA |NA |NA +#8 |11 |NA |8 |8 |8 |8 |8 |8 |NA |NA +#9 |10 |NA |9 |8 |NA |8 |8 |NA |NA |NA +#10 |9 |NA |10 |8 |10 |10 |8 |8 |NA |NA +#11 |8 |NA |11 |8 |NA |10 |8 |NA |NA |NA +#12 |12 |NA |12 |12 |12 |12 |12 |12 |NA |NA +#13 |13 |NA |13 |12 |NA |12 |12 |NA |NA |NA +#14 |14 |NA |14 |12 |14 |14 |12 |12 |NA |NA +#15 |15 |NA |15 |12 |NA |14 |12 |NA |NA |NA +#16 |16 |NA |16 |16 |16 |16 |16 |16 |NA |NA +#17 |17 |NA |17 |16 |NA |16 |16 |NA |NA |NA +#18 |18 |NA |18 |16 |18 |18 |16 |16 |NA |NA +#19 |19 |NA |19 |16 |NA |18 |16 |NA |NA |NA +#20 |20 |NA |20 |20 |20 |20 |20 |20 |NA |NA +#21 |21 |NA |21 |20 |NA |20 |20 |NA |NA |NA +#22 |22 |NA |22 |20 |22 |22 |20 |20 |NA |NA +#23 |23 |NA |23 |20 |NA |22 |20 |NA |NA |NA +#24 |24 |NA |24 |24 |24 |24 |24 |24 |NA |NA +#25 |25 |NA |25 |24 |NA |24 |24 |NA |NA |NA +#26 |26 |NA |26 |24 |26 |26 |24 |24 |NA |NA +#27 |27 |NA |27 |24 |NA |26 |24 |NA |NA |NA +#28 |28 |NA |28 |28 |28 |28 |28 |28 |NA |NA +#29 |29 |NA |29 |28 |NA |28 |28 |NA |NA |NA +#30 |30 |NA |30 |28 |30 |30 |28 |28 |NA |NA +#31 |31 |NA |31 |28 |NA |30 |28 |NA |NA |NA +#32 |36 |NA |32 |32 |32 |32 |32 |32 |32 |32 +#33 |37 |NA |33 |32 |33 |32 |32 |32 |32 |32 +#34 |38 |NA |34 |32 |34 |34 |32 |34 |32 |32 +#35 |32 |NA |35 |32 |35 |34 |32 |34 |32 |32 +#36 |39 |NA |36 |36 |36 |36 |36 |36 |36 |32 +#37 |34 |NA |37 |36 |37 |36 |36 |36 |36 |32 +#38 |35 |NA |38 |36 |38 |38 |36 |38 |36 |32 +#39 |33 |NA |39 |36 |39 |38 |36 |38 |36 |32 +#40 |40 |NA |40 |40 |40 |40 |40 |40 |40 |40 +#41 |44 |NA |41 |40 |41 |40 |40 |40 |40 |40 +#42 |42 |NA |42 |40 |42 |42 |40 |42 |40 |40 +#43 |41 |NA |43 |40 |43 |42 |40 |42 |40 |40 +#44 |43 |NA |44 |44 |44 |44 |44 |44 |44 |40 +#45 |46 |NA |45 |44 |45 |44 |44 |44 |44 |40 +#46 |47 |NA |46 |44 |46 |46 |44 |46 |44 |40 +#47 |45 |NA |47 |44 |47 |46 |44 |46 |44 |40 +#48 |49 |NA |48 |48 |48 |48 |48 |48 |NA |NA +#49 |48 |NA |49 |48 |NA |48 |48 |NA |NA |NA +#50 |51 |NA |50 |48 |50 |50 |48 |48 |NA |NA +#51 |50 |NA |51 |48 |NA |50 |48 |NA |NA |NA +#52 |53 |NA |52 |52 |52 |52 |52 |52 |NA |NA +#53 |52 |NA |53 |52 |NA |52 |52 |NA |NA |NA +#54 |55 |NA |54 |52 |54 |54 |52 |52 |NA |NA +#55 |54 |NA |55 |52 |NA |54 |52 |NA |NA |NA +#56 |57 |NA |56 |56 |56 |56 |56 |56 |NA |NA +#57 |56 |NA |57 |56 |NA |56 |56 |NA |NA |NA +#58 |59 |NA |58 |56 |58 |58 |56 |56 |NA |NA +#59 |58 |NA |59 |56 |NA |58 |56 |NA |NA |NA +#60 |60 |NA |60 |60 |60 |60 |60 |60 |NA |NA +#61 |61 |NA |61 |60 |NA |60 |60 |NA |NA |NA +#62 |62 |NA |62 |60 |62 |62 |60 |60 |NA |NA +#63 |63 |NA |63 |60 |NA |62 |60 |NA |NA |NA +#64 |70 |NA |64 |64 |64 |64 |64 |64 |NA |NA +#65 |71 |NA |65 |64 |NA |64 |64 |NA |NA |NA +#66 |68 |NA |66 |64 |66 |66 |64 |64 |NA |NA +#67 |69 |NA |67 |64 |NA |66 |64 |NA |NA |NA +#68 |66 |NA |68 |68 |68 |68 |68 |68 |NA |NA +#69 |67 |NA |69 |68 |NA |68 |68 |NA |NA |NA +#70 |64 |NA |70 |68 |70 |70 |68 |68 |NA |NA +#71 |65 |NA |71 |68 |NA |70 |68 |NA |NA |NA +#72 |74 |NA |72 |72 |72 |72 |72 |72 |NA |NA +#73 |75 |NA |73 |72 |NA |72 |72 |NA |NA |NA +#74 |72 |NA |74 |72 |74 |74 |72 |72 |NA |NA +#75 |73 |NA |75 |72 |NA |74 |72 |NA |NA |NA +#76 |76 |NA |76 |76 |76 |76 |76 |76 |NA |NA +#77 |77 |NA |77 |76 |NA |76 |76 |NA |NA |NA +#78 |78 |NA |78 |76 |78 |78 |76 |76 |NA |NA +#79 |79 |NA |79 |76 |NA |78 |76 |NA |NA |NA +#80 |83 |NA |80 |80 |80 |80 |80 |80 |80 |80 +#81 |81 |NA |81 |80 |81 |80 |80 |80 |80 |80 +#82 |87 |NA |82 |80 |82 |82 |80 |82 |80 |80 +#83 |82 |NA |83 |80 |83 |82 |80 |82 |80 |80 +#84 |86 |NA |84 |84 |84 |84 |84 |84 |84 |80 +#85 |80 |NA |85 |84 |85 |84 |84 |84 |84 |80 +#86 |84 |NA |86 |84 |86 |86 |84 |86 |84 |80 +#87 |85 |NA |87 |84 |87 |86 |84 |86 |84 |80 +#88 |95 |NA |88 |88 |88 |88 |88 |88 |88 |88 +#89 |93 |NA |89 |88 |89 |88 |88 |88 |88 |88 +#90 |91 |NA |90 |88 |90 |90 |88 |90 |88 |88 +#91 |94 |NA |91 |88 |91 |90 |88 |90 |88 |88 +#92 |90 |NA |92 |92 |92 |92 |92 |92 |92 |88 +#93 |89 |NA |93 |92 |93 |92 |92 |92 |92 |88 +#94 |88 |NA |94 |92 |94 |94 |92 |94 |92 |88 +#95 |92 |NA |95 |92 |95 |94 |92 |94 |92 |88 +#96 |96 |NA |232 |232 |232 |232 |232 |232 |NA |NA +#97 |97 |NA |233 |232 |NA |232 |232 |NA |NA |NA +#98 |98 |NA |243 |232 |243 |243 |232 |232 |NA |NA +#99 |99 |NA |244 |232 |NA |243 |232 |NA |NA |NA +#} + diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/buffers.json.j2 b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/pg_profile_lookup.ini b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/port_config.ini b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/port_config.ini new file mode 100644 index 000000000000..45206015c94e --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed fec +Ethernet0 32 eth-0-1 0 25000 none +Ethernet1 33 eth-0-2 1 25000 none +Ethernet2 34 eth-0-3 2 25000 none +Ethernet3 35 eth-0-4 3 25000 none +Ethernet4 0 eth-0-5 4 25000 none +Ethernet5 4 eth-0-6 5 25000 none +Ethernet6 8 eth-0-7 6 25000 none +Ethernet7 12 eth-0-8 7 25000 none +Ethernet8 16 eth-0-9 8 25000 none +Ethernet9 20 eth-0-10 9 25000 none +Ethernet10 24 eth-0-11 10 25000 none +Ethernet11 28 eth-0-12 11 25000 none +Ethernet12 40 eth-0-13 12 25000 none +Ethernet13 44 eth-0-14 13 25000 none +Ethernet14 48 eth-0-15 14 25000 none +Ethernet15 52 eth-0-16 15 25000 none +Ethernet16 56 eth-0-17 16 25000 none +Ethernet17 60 eth-0-18 17 25000 none +Ethernet18 64 eth-0-19 18 25000 none +Ethernet19 68 eth-0-20 19 25000 none +Ethernet20 72 eth-0-21 20 25000 none +Ethernet21 73 eth-0-22 21 25000 none +Ethernet22 74 eth-0-23 22 25000 none +Ethernet23 75 eth-0-24 23 25000 none +Ethernet24 232 eth-0-25 24 25000 none +Ethernet25 233 eth-0-26 25 25000 none +Ethernet26 234 eth-0-27 26 25000 none +Ethernet27 235 eth-0-28 27 25000 none +Ethernet28 200 eth-0-29 28 25000 none +Ethernet29 204 eth-0-30 29 25000 none +Ethernet30 208 eth-0-31 30 25000 none +Ethernet31 212 eth-0-32 31 25000 none +Ethernet32 216 eth-0-33 32 25000 none +Ethernet33 220 eth-0-34 33 25000 none +Ethernet34 224 eth-0-35 34 25000 none +Ethernet35 228 eth-0-36 35 25000 none +Ethernet36 160 eth-0-37 36 25000 none +Ethernet37 164 eth-0-38 37 25000 none +Ethernet38 168 eth-0-39 38 25000 none +Ethernet39 172 eth-0-40 39 25000 none +Ethernet40 176 eth-0-41 40 25000 none +Ethernet41 180 eth-0-42 41 25000 none +Ethernet42 184 eth-0-43 42 25000 none +Ethernet43 188 eth-0-44 43 25000 none +Ethernet44 192 eth-0-45 44 25000 none +Ethernet45 193 eth-0-46 45 25000 none +Ethernet46 194 eth-0-47 46 25000 none +Ethernet47 195 eth-0-48 47 25000 none +Ethernet48 120,121,122,123 eth-0-49 48 100000 none +Ethernet49 124,125,126,127 eth-0-50 49 100000 none +Ethernet50 80,81,82,83 eth-0-51 50 100000 none +Ethernet51 84,85,86,87 eth-0-52 51 100000 none +Ethernet52 240,241,242,243 eth-0-53 52 100000 none +Ethernet53 244,245,246,247 eth-0-54 53 100000 none +Ethernet54 280,281,282,283 eth-0-55 54 100000 none +Ethernet55 284,285,286,287 eth-0-56 55 100000 none diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/qos.json.j2 b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/sai.profile b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/sai.profile new file mode 100644 index 000000000000..9a3643c35b20 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/V682-48y8c/sai.profile @@ -0,0 +1,3 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/V682-48y8c-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/usr/share/sonic/hwsku/V682-48y8c-datapath.txt +SAI_PLATFORM_CFG_FILE=/usr/share/sonic/hwsku/V682-48y8c-board.json diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/default_sku b/device/centec/x86_64-centec_v682_48y8c-r0/default_sku new file mode 100644 index 000000000000..d169d9636002 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/default_sku @@ -0,0 +1 @@ +V682-48y8c l2 diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/fancontrol b/device/centec/x86_64-centec_v682_48y8c-r0/fancontrol new file mode 100644 index 000000000000..07420a6dba06 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-0049 hwmon2=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-9/9-002c hwmon3=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-9/9-002e +DEVNAME=hwmon1=lm77 hwmon2=adt7470 hwmon3=adt7470 +FCTEMPS=hwmon2/pwm1=hwmon1/temp1_input hwmon2/pwm2=hwmon1/temp1_input hwmon2/pwm3=hwmon1/temp1_input hwmon2/pwm4=hwmon1/temp1_input hwmon3/pwm1=hwmon1/temp1_input hwmon3/pwm2=hwmon1/temp1_input hwmon3/pwm3=hwmon1/temp1_input hwmon3/pwm4=hwmon1/temp1_input +FCFANS=hwmon2/pwm1=hwmon2/fan1_input hwmon2/pwm2=hwmon2/fan2_input hwmon2/pwm3=hwmon2/fan3_input hwmon2/pwm4=hwmon2/fan4_input hwmon3/pwm1=hwmon3/fan1_input hwmon3/pwm2=hwmon3/fan2_input hwmon3/pwm3=hwmon3/fan3_input hwmon3/pwm4=hwmon3/fan4_input +MINTEMP=hwmon2/pwm1=20 hwmon2/pwm2=20 hwmon2/pwm3=20 hwmon2/pwm4=20 hwmon3/pwm1=20 hwmon3/pwm2=20 hwmon3/pwm3=20 hwmon3/pwm4=20 +MAXTEMP=hwmon2/pwm1=60 hwmon2/pwm2=60 hwmon2/pwm3=60 hwmon2/pwm4=60 hwmon3/pwm1=60 hwmon3/pwm2=60 hwmon3/pwm3=60 hwmon3/pwm4=60 +MINSTART=hwmon2/pwm1=150 hwmon2/pwm2=150 hwmon2/pwm3=150 hwmon2/pwm4=150 hwmon3/pwm1=150 hwmon3/pwm2=150 hwmon3/pwm3=150 hwmon3/pwm4=150 +MINSTOP=hwmon2/pwm1=0 hwmon2/pwm2=0 hwmon2/pwm3=0 hwmon2/pwm4=0 hwmon3/pwm1=0 hwmon3/pwm2=0 hwmon3/pwm3=0 hwmon3/pwm4=0 diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/installer.conf b/device/centec/x86_64-centec_v682_48y8c-r0/installer.conf new file mode 100644 index 000000000000..3b97b7f99da2 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="iommu=pt" diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/pcie.yaml b/device/centec/x86_64-centec_v682_48y8c-r0/pcie.yaml new file mode 100644 index 000000000000..5e00e24bc079 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/pcie.yaml @@ -0,0 +1,5 @@ +- bus: '05' + dev: '00' + fn: '0' + id: 8180 + name: 'Communication controller: Device cb10:8180' diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/platform_asic b/device/centec/x86_64-centec_v682_48y8c-r0/platform_asic new file mode 100644 index 000000000000..74dac3505ea6 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/platform_asic @@ -0,0 +1 @@ +centec diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/platform_components.json b/device/centec/x86_64-centec_v682_48y8c-r0/platform_components.json new file mode 100644 index 000000000000..15c644f6b461 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "V682-48Y8C": { + "component": { + } + } + } +} diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/platform_reboot b/device/centec/x86_64-centec_v682_48y8c-r0/platform_reboot new file mode 100755 index 000000000000..5e49eecb61ca --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/platform_reboot @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import time + +def main(): + os.system('hwclock -w -f /dev/rtc1') + time.sleep(1) + + os.system('i2cset -y 0 0x36 0x23 0') + time.sleep(1) + os.system('i2cset -y 0 0x36 0x23 1') + +if __name__ == '__main__': + main() diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/plugins/eeprom.py b/device/centec/x86_64-centec_v682_48y8c-r0/plugins/eeprom.py new file mode 100644 index 000000000000..1651279722ee --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/plugins/eeprom.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +############################################################################# +# Centec V682-48Y8C +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os + from sonic_eeprom import eeprom_tlvinfo + from sonic_py_common import device_info +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + self.eeprom_path = platform_path + '/eeprom_file' + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/plugins/led_control.py b/device/centec/x86_64-centec_v682_48y8c-r0/plugins/led_control.py new file mode 100644 index 000000000000..973a9354fbc6 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/plugins/led_control.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + import os + import re + import syslog + import collections + from sonic_led.led_control_base import LedControlBase + from sonic_py_common import device_info + from subprocess import Popen +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + # Constructor + def __init__(self): + + self.mac_to_led = { + 32 : 0, + 33 : 1, + 34 : 2, + 35 : 3, + 0 : 4, + 4 : 5, + 8 : 6, + 12 : 7, + 16 : 8, + 20 : 9, + 24 : 10, + 28 : 11, + 40 : 12, + 44 : 13, + 48 : 14, + 52 : 15, + 56 : 16, + 60 : 17, + 64 : 18, + 68 : 19, + 72 : 20, + 73 : 21, + 74 : 22, + 75 : 23, + 232: 24, + 233: 25, + 234: 26, + 235: 27, + 200: 28, + 204: 29, + 208: 30, + 212: 31, + 216: 32, + 220: 33, + 224: 34, + 228: 35, + 160: 36, + 164: 37, + 168: 38, + 172: 39, + 176: 40, + 180: 41, + 184: 42, + 188: 43, + 192: 44, + 193: 45, + 194: 46, + 195: 47, + 120: 48, + 121: -1, + 122: -1, + 123: -1, + 124: 49, + 125: -1, + 126: -1, + 127: -1, + 80 : 50, + 81 : -1, + 82 : -1, + 83 : -1, + 84 : 51, + 85 : -1, + 86 : -1, + 87 : -1, + 240: 52, + 241: -1, + 242: -1, + 243: -1, + 244: 53, + 245: -1, + 246: -1, + 247: -1, + 280: 54, + 281: -1, + 282: -1, + 283: -1, + 284: 55, + 285: -1, + 286: -1, + 287: -1, + } + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "V682-48y8c", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + self.LED_MODE_UP = [5, 5] + self.LED_MODE_DOWN = [7, 7] + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + for port_cfg in self._port_cfgs: + if port_name == port_cfg.name: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + return None + return led + return None + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[1] if port_idx >= 48 else self.LED_MODE_UP[0] + else: + return self.LED_MODE_DOWN[1] if port_idx >= 48 else self.LED_MODE_DOWN[0] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + cmd = 'i2cset -y 0 0x36 0x2 0x5' + Popen(cmd, shell=True) + DBG_PRINT("init system led to normal") + cmd = 'i2cset -y 0 0x36 0x3 0x1' + Popen(cmd, shell=True) + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for port_cfg in self._port_cfgs: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + continue + defmode = self._port_state_to_mode(led, "down") + with open(self.f_led.format("port{}".format(led)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(led, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + if port_idx is None: + return + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/plugins/psuutil.py b/device/centec/x86_64-centec_v682_48y8c-r0/plugins/psuutil.py new file mode 100644 index 000000000000..9e311d9b4f5a --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/plugins/psuutil.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +from subprocess import Popen, PIPE, STDOUT + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + 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 + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + powergood = ((status & (1 << (3 * (index - 1) + 2))) != 0) + return powergood + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + presence = ((status & (1 << (3 * (index - 1) + 1))) == 0) + return presence diff --git a/device/centec/x86_64-centec_v682_48y8c-r0/pmon_daemon_control.json b/device/centec/x86_64-centec_v682_48y8c-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..0db3279e44b0 --- /dev/null +++ b/device/centec/x86_64-centec_v682_48y8c-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/device/centec/x86_64-centec_v682_48y8c_d-r0/installer.conf b/device/centec/x86_64-centec_v682_48y8c_d-r0/installer.conf index e69de29bb2d1..3b97b7f99da2 100644 --- a/device/centec/x86_64-centec_v682_48y8c_d-r0/installer.conf +++ b/device/centec/x86_64-centec_v682_48y8c_d-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="iommu=pt" diff --git a/device/centec/x86_64-centec_v682_48y8c_d-r0/platform_reboot b/device/centec/x86_64-centec_v682_48y8c_d-r0/platform_reboot index 89e521978cba..a1dff65154bf 100755 --- a/device/centec/x86_64-centec_v682_48y8c_d-r0/platform_reboot +++ b/device/centec/x86_64-centec_v682_48y8c_d-r0/platform_reboot @@ -1,9 +1,9 @@ -#!/usr/bin/python2 +#!/usr/bin/env python import os import sys -susi4_lib = '/usr/local/lib/python2.7/dist-packages' +susi4_lib = '/usr/local/lib/python3.9/dist-packages' if not susi4_lib in os.environ.setdefault('LD_LIBRARY_PATH', ''): os.environ['LD_LIBRARY_PATH'] += (':' + susi4_lib) try: diff --git a/platform/centec/one-image.mk b/platform/centec/one-image.mk index da129addb247..84b993bb5986 100644 --- a/platform/centec/one-image.mk +++ b/platform/centec/one-image.mk @@ -9,6 +9,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E582_48X6Q_PLATFORM_MODULE) \ $(EMBEDWAY_ES6220_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_V682_48Y8C_D_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_V682_48Y8C_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_V682_48X8C_PLATFORM_MODULE) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) diff --git a/platform/centec/platform-modules-centec-v682.mk b/platform/centec/platform-modules-centec-v682.mk index 1736279fdcef..46b64c3e6d72 100644 --- a/platform/centec/platform-modules-centec-v682.mk +++ b/platform/centec/platform-modules-centec-v682.mk @@ -2,8 +2,12 @@ CENTEC_V682_48Y8C_D_PLATFORM_MODULE_VERSION =1.0 +CENTEC_V682_48Y8C_PLATFORM_MODULE_VERSION =1.0 +CENTEC_V682_48X8C_PLATFORM_MODULE_VERSION =1.0 export CENTEC_V682_48Y8C_D_PLATFORM_MODULE_VERSION +export CENTEC_V682_48Y8C_PLATFORM_MODULE_VERSION +export CENTEC_V682_48X8C_PLATFORM_MODULE_VERSION CENTEC_V682_48Y8C_D_PLATFORM_MODULE = platform-modules-v682-48y8c-d_$(CENTEC_V682_48Y8C_D_PLATFORM_MODULE_VERSION)_amd64.deb @@ -12,3 +16,11 @@ $(CENTEC_V682_48Y8C_D_PLATFORM_MODULE)_PLATFORM = x86_64-centec_v682_48y8c_d-r0 $(CENTEC_V682_48Y8C_D_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) SONIC_STRETCH_DEBS += $(CENTEC_V682_48Y8C_D_PLATFORM_MODULE) SONIC_DPKG_DEBS += $(CENTEC_V682_48Y8C_D_PLATFORM_MODULE) + +CENTEC_V682_48Y8C_PLATFORM_MODULE = platform-modules-v682-48y8c_$(CENTEC_V682_48Y8C_PLATFORM_MODULE_VERSION)_amd64.deb +$(CENTEC_V682_48Y8C_PLATFORM_MODULE)_PLATFORM = x86_64-centec_v682_48y8c-r0 +$(eval $(call add_extra_package,$(CENTEC_V682_48Y8C_D_PLATFORM_MODULE),$(CENTEC_V682_48Y8C_PLATFORM_MODULE))) + +CENTEC_V682_48X8C_PLATFORM_MODULE = platform-modules-v682-48x8c_$(CENTEC_V682_48X8C_PLATFORM_MODULE_VERSION)_amd64.deb +$(CENTEC_V682_48X8C_PLATFORM_MODULE)_PLATFORM = x86_64-centec_v682_48x8c-r0 +$(eval $(call add_extra_package,$(CENTEC_V682_48Y8C_D_PLATFORM_MODULE),$(CENTEC_V682_48X8C_PLATFORM_MODULE))) diff --git a/platform/centec/sdk.mk b/platform/centec/sdk.mk index ead6de87dd65..2f56265b4890 100644 --- a/platform/centec/sdk.mk +++ b/platform/centec/sdk.mk @@ -1,5 +1,5 @@ # Centec SAI -CENTEC_SAI = libsai_1.8.1-0_amd64.deb +CENTEC_SAI = libsai_1.9.1-0_amd64.deb $(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/amd64/sai/$(CENTEC_SAI) $(eval $(call add_conflict_package,$(CENTEC_SAI),$(LIBSAIVS_DEV))) diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/modules/Makefile b/platform/centec/sonic-platform-modules-v682/48x8c/modules/Makefile new file mode 100644 index 000000000000..eabfe2733c41 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_v682_48x8c_platform.o rtc-sd2405.o diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/modules/centec_v682_48x8c_platform.c b/platform/centec/sonic-platform-modules-v682/48x8c/modules/centec_v682_48x8c_platform.c new file mode 100644 index 000000000000..049ca4a710c3 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/modules/centec_v682_48x8c_platform.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define SFP_NUM 48 +#define QSFP_NUM 8 +#define PORT_NUM (SFP_NUM + QSFP_NUM) +#endif + +#if SEP("drivers:leds") +extern void v682_48x8c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness v682_48x8c_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port0", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port1", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port2", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port3", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port4", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port5", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port6", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port7", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port8", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port9", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port10", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port11", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port12", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port13", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port14", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port15", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port16", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port17", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port18", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port19", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port20", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port21", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port22", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port23", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port24", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port25", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port26", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port27", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port28", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port29", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port30", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port31", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port32", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port33", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port34", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port35", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port36", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port37", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port38", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port39", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port40", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port41", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port42", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port43", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port44", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port45", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port46", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port47", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port48", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port49", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port50", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port51", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port52", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port53", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port54", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +{ .name = "port55", .brightness_set = v682_48x8c_led_port_set, .brightness_get = v682_48x8c_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void v682_48x8c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum] = set_value; + + return; +} + +enum led_brightness v682_48x8c_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum]; +} + +static int v682_48x8c_init_led(void) +{ + int ret = 0; + int i = 0; + + for (i = 0; i < PORT_NUM; i++) + { + ret = led_classdev_register(NULL, &(led_dev_port[i])); + if (ret != 0) + { + printk(KERN_CRIT "create v682_48x8c led_dev_port%d device failed\n", i); + continue; + } + } + + return ret; +} + +static int v682_48x8c_exit_led(void) +{ + int i = 0; + + for (i = 0; i < PORT_NUM; i++) + { + led_classdev_unregister(&(led_dev_port[i])); + } + + return 0; +} +#endif + +static int v682_48x8c_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "init v682_48x8c board dirver...\n"); + + ret = v682_48x8c_init_led(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "init v682_48x8c board driver failed\n"); + else + printk(KERN_ALERT "init v682_48x8c board dirver...ok\n"); + + return 0; +} + +static void v682_48x8c_exit(void) +{ + printk(KERN_INFO "deinit v682_48x8c board dirver...\n"); + + v682_48x8c_exit_led(); + + printk(KERN_INFO "deinit v682_48x8c board dirver...ok\n"); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("v682-48x8c board driver"); +module_init(v682_48x8c_init); +module_exit(v682_48x8c_exit); diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/modules/rtc-sd2405.c b/platform/centec/sonic-platform-modules-v682/48x8c/modules/rtc-sd2405.c new file mode 100644 index 000000000000..c22ab3349144 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/modules/rtc-sd2405.c @@ -0,0 +1,264 @@ +/* + * rtc class driver for the SD2405 chip + * + * Author: Dale Farnsworth + * + * based on previously existing rtc class drivers + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include + +#define DRV_VERSION "0.1" + +/* + * register indices + */ +#define SD2405_REG_SC 0x0 /* seconds 00-59 */ +#define SD2405_REG_MN 0x1 /* minutes 00-59 */ +#define SD2405_REG_HR 0x2 /* hours 00-23 */ +#define SD2405_REG_DW 0x3 /* day of week 1-7 */ +#define SD2405_REG_DT 0x4 /* day of month 00-31 */ +#define SD2405_REG_MO 0x5 /* month 01-12 */ +#define SD2405_REG_YR 0x6 /* year 00-99 */ + +#define SD2405_REG_CTRL1 0xf /* control 1 */ +#define SD2405_REG_CTRL2 0x10 /* control 2 */ +#define SD2405_REG_CTRL3 0x11 /* control 3 ARST*/ + +#define SD2405_REG_LEN 7 + +/* + * register write protect + */ +#define SD2405_REG_CONTROL1_WRITE 0x80 +#define SD2405_REG_CONTROL2_WRITE 0x84 + + +#define SD2405_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ + +static struct i2c_driver sd2405_driver; + +#if 1 +/* modified by shil, for bug 46153 */ +static int sd2405_i2c_read_regs(struct i2c_client *client, u8 *buf) +{ + int i; + + for (i = 0; i < SD2405_REG_LEN; i++) { + buf[i] = i2c_smbus_read_byte_data(client, SD2405_REG_SC+i); + } + return 0; +} + +/* modified by shil, for bug 46153 */ +static int sd2405_i2c_write_regs(struct i2c_client *client, u8 const *buf) +{ + int i; + + for (i = 0; i < SD2405_REG_LEN; i++) { + i2c_smbus_write_byte_data(client, SD2405_REG_SC+i, buf[i]); + msleep(SD2405_IDLE_TIME_AFTER_WRITE); + } + return 0; +} + +#else +static int sd2405_i2c_read_regs(struct i2c_client *client, u8 *buf) +{ + struct i2c_msg msgs[1] = { + { + .addr = client->addr, + .flags = I2C_M_RD, /* read */ + .len = SD2405_REG_LEN, + .buf = buf} + }; + int rc; + + rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (rc != ARRAY_SIZE(msgs)) { + dev_err(&client->dev, "%s: register read failed\n", __func__); + return -EIO; + } + return 0; +} + +static int sd2405_i2c_write_regs(struct i2c_client *client, u8 const *buf) +{ + int rc; + + u8 temp_reg[SD2405_REG_LEN+1] = {0}; + memcpy(&temp_reg[1], buf, SD2405_REG_LEN); + + struct i2c_msg msgs[1] = { + { + .addr = client->addr, + .flags = 0, /* write */ + .len = SD2405_REG_LEN+1, + .buf = temp_reg} + }; + + rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (rc != ARRAY_SIZE(msgs)) + goto write_failed; + msleep(SD2405_IDLE_TIME_AFTER_WRITE); + + return 0; + + write_failed: + dev_err(&client->dev, "%s: register write failed\n", __func__); + return -EIO; +} +#endif + +static int sd2405_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) +{ + int rc; + u8 regs[SD2405_REG_LEN]; + + rc = sd2405_i2c_read_regs(client, regs); + if (rc < 0) + return rc; + + tm->tm_sec = bcd2bin(regs[SD2405_REG_SC]); + tm->tm_min = bcd2bin(regs[SD2405_REG_MN]); + tm->tm_hour = bcd2bin(regs[SD2405_REG_HR] & 0x3f); + tm->tm_wday = bcd2bin(regs[SD2405_REG_DW]); + tm->tm_mday = bcd2bin(regs[SD2405_REG_DT]); + tm->tm_mon = bcd2bin(regs[SD2405_REG_MO]) - 1; + tm->tm_year = bcd2bin(regs[SD2405_REG_YR]) + 100; + + return 0; +} + +static int sd2405_i2c_set_write_protect(struct i2c_client *client) +{ + int rc; + rc = i2c_smbus_write_byte_data(client, SD2405_REG_CTRL1, 0); + rc += i2c_smbus_write_byte_data(client, SD2405_REG_CTRL2, 0); + if (rc < 0) { + dev_err(&client->dev, "%s: control register write failed\n", + __func__); + return -EIO; + } + return 0; +} + +static int sd2405_i2c_clear_write_protect(struct i2c_client *client) +{ + int rc; + rc = i2c_smbus_write_byte_data(client, SD2405_REG_CTRL2, SD2405_REG_CONTROL1_WRITE); + rc += i2c_smbus_write_byte_data(client, SD2405_REG_CTRL1, SD2405_REG_CONTROL2_WRITE); + if (rc < 0) { + dev_err(&client->dev, "%s: control register write failed\n", + __func__); + return -EIO; + } + return 0; +} + +static int +sd2405_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) +{ + u8 regs[SD2405_REG_LEN]; + int rc; + + rc = sd2405_i2c_clear_write_protect(client); + if (rc < 0) + return rc; + + regs[SD2405_REG_SC] = bin2bcd(tm->tm_sec); + regs[SD2405_REG_MN] = bin2bcd(tm->tm_min); + regs[SD2405_REG_HR] = bin2bcd(tm->tm_hour)|0x80; + regs[SD2405_REG_DW] = bin2bcd(tm->tm_wday); + regs[SD2405_REG_DT] = bin2bcd(tm->tm_mday); + regs[SD2405_REG_MO] = bin2bcd(tm->tm_mon + 1); + regs[SD2405_REG_YR] = bin2bcd(tm->tm_year - 100); + + rc = sd2405_i2c_write_regs(client, regs); + if (rc < 0) + return rc; + + rc = sd2405_i2c_set_write_protect(client); + if (rc < 0) + return rc; + + return 0; +} + +static int sd2405_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return sd2405_i2c_read_time(to_i2c_client(dev), tm); +} + +static int sd2405_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return sd2405_i2c_set_time(to_i2c_client(dev), tm); +} + +static const struct rtc_class_ops sd2405_rtc_ops = { + .read_time = sd2405_rtc_read_time, + .set_time = sd2405_rtc_set_time, +}; + +static int +sd2405_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct rtc_device *rtc; + +/* modified by shil, for bug 46153 */ +#if 0 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; +#endif + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + i2c_set_clientdata(client, rtc); + rtc->ops = &sd2405_rtc_ops; + + return rtc_register_device(rtc); +} + +static struct i2c_device_id sd2405_id[] = { + { "sd2405", 0 }, + { } +}; + +static struct i2c_driver sd2405_driver = { + .driver = { + .name = "rtc-sd2405", + }, + .probe = sd2405_probe, + .id_table = sd2405_id, +}; + +static int __init sd2405_init(void) +{ + return i2c_add_driver(&sd2405_driver); +} + +static void __exit sd2405_exit(void) +{ + i2c_del_driver(&sd2405_driver); +} + +MODULE_DESCRIPTION("Maxim SD2405 RTC driver"); +MODULE_AUTHOR("Dale Farnsworth "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(sd2405_init); +module_exit(sd2405_exit); diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/service/48x8c_platform.service b/platform/centec/sonic-platform-modules-v682/48x8c/service/48x8c_platform.service new file mode 100644 index 000000000000..af5f5b779e66 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/service/48x8c_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-v682-48x8c start +ExecStop=-/etc/init.d/platform-modules-v682-48x8c stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/service/release.py b/platform/centec/sonic-platform-modules-v682/48x8c/service/release.py new file mode 100644 index 000000000000..8ae790a24fdc --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/service/release.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import os +import time + +def release_board(): + if open('/proc/cmdline', 'r').readlines()[0].find('SONIC_BOOT_TYPE=warm') != -1: + return + + os.system('i2cset -y 0 0x37 0x4 0x0') + time.sleep(1) + os.system('i2cset -y 0 0x37 0x4 0x1') + time.sleep(1) + os.system('echo 1 > /sys/bus/pci/devices/0000\:00\:1c.0/remove') + time.sleep(1) + os.system('echo 1 > /sys/bus/pci/rescan') + time.sleep(1) + # EPLD_QSFP_RST + os.system('i2cset -y 0 0x36 0x5 0xff') + os.system('i2cset -y 0 0x37 0x5 0xff') + # EPLD_QSFP_INT_MASK + os.system('i2cset -y 0 0x36 0xd 0xff') + os.system('i2cset -y 0 0x37 0xd 0xff') + # EPLD_PPU_INT_MASK + os.system('i2cset -y 0 0x36 0xb 0x00') + # EPLD_SFP_DISABLE1 + os.system('i2cset -y 0 0x36 0xe 0x00') + os.system('i2cset -y 0 0x37 0xe 0x00') + # EPLD_SFP_DISABLE2 + os.system('i2cset -y 0 0x36 0xf 0x00') + os.system('i2cset -y 0 0x37 0xf 0x00') + # EPLD_SFP_DISABLE3 + os.system('i2cset -y 0 0x36 0x10 0x00') + os.system('i2cset -y 0 0x37 0x10 0x00') + +if __name__ == '__main__': + release_board() diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/setup.py b/platform/centec/sonic-platform-modules-v682/48x8c/setup.py new file mode 100644 index 000000000000..57724ad4b4f8 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize centec v682-48x8c platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) + diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/__init__.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/__init__.py new file mode 100644 index 000000000000..6e50c02e9d1f --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer", "led"] +from . import platform diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/chassis.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/chassis.py new file mode 100644 index 000000000000..7a137fc534f8 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/chassis.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import re + import time + import collections + from sonic_py_common import device_info + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 2 +NUM_THERMAL = 1 +NUM_PSU = 2 + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +REBOOT_CAUSE_DIR = "/host/reboot-cause/" +REBOOT_CAUSE_FILE = os.path.join(REBOOT_CAUSE_DIR, "reboot-cause.txt") + +class Chassis(ChassisBase): + # System status LED + _led = None + + def __init__(self): + ChassisBase.__init__(self) + + self.data = {'valid':0, 'last':0} + self.sfp_presence = {} + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "V682-48x8c", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + _port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + # Initialize EEPROM + self._eeprom = Eeprom() + + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i + 1) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index + 1) + self._psu_list.append(psu) + + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + # Initialize SFP + for port_cfg in _port_cfgs: + sfp = Sfp(int(port_cfg.index), 'SFP' if int(port_cfg.index) < 48 else 'QSFP') + self._sfp_list.append(sfp) + self.sfp_presence[int(port_cfg.index)] = False + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + 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(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + 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_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. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + 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. + """ + if os.path.exists(REBOOT_CAUSE_FILE): + with open(REBOOT_CAUSE_FILE) as reboot_cause_file: + reboot_cause = reboot_cause_file.readline() + if re.search(r'User issued', reboot_cause) is None: + return (self.REBOOT_CAUSE_POWER_LOSS, None) + else: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + else: + return (self.REBOOT_CAUSE_POWER_LOSS, None) + + def get_change_event(self, timeout=2000): + """ + 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. + """ + SFP_STATUS_INSERTED = '1' + SFP_STATUS_REMOVED = '0' + + now = time.time() + port_dict = {} + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return False, {'sfp': {}} + + for sfp in self._sfp_list: + sfp_presence = sfp.get_presence() + if sfp_presence != self.sfp_presence[sfp.index]: + self.sfp_presence[sfp.index] = sfp_presence + if sfp_presence: + port_dict[sfp.index] = SFP_STATUS_INSERTED + else: + port_dict[sfp.index] = SFP_STATUS_REMOVED + + if bool(port_dict): + self.data['last'] = now + self.data['valid'] = 1 + ret = True + else: + time.sleep(0.5) + ret = False + + ret_dict = {'sfp': port_dict} + return ret, ret_dict + + def get_num_psus(self): + return len(self._psu_list) + + def get_psu(self, psu_index): + return self._psu_list[psu_index] + + def initizalize_system_led(self): + from .led import SystemLed + Chassis._led = SystemLed() + + 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 if not Chassis._led else Chassis._led.set_status(color) + + 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. + """ + return None if not Chassis._led else Chassis._led.get_status() diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/eeprom.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/eeprom.py new file mode 100644 index 000000000000..7d2750475717 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/eeprom.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_eeprom import eeprom_tlvinfo + from sonic_py_common import device_info + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + self.__eeprom_path = platform_path + '/eeprom_file' + + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + + self.__eeprom_tlv_dict = dict() + try: + self.open_eeprom() + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += str(tlv[6:6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + 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_tlv_dict + diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan.py new file mode 100644 index 000000000000..5f7b256eafb8 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_PATH = "/sys/class/hwmon/hwmon{}/" +FAN_MAX_PWM = 255 +FAN_FAN_PWM = "pwm{}" +FAN_FAN_INPUT = "fan{}_input" +FAN_MAX_RPM = 15000 +FAN_NAME_LIST = ["FAN-{}-1", "FAN-{}-2", "FAN-{}-3", "FAN-{}-4"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + + FanBase.__init__(self) + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except IOError: + return False + return True + + def __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + direction = self.FAN_DIRECTION_EXHAUST + return direction + + 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) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH.format(self.fan_tray_index + 1), fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return int(speed) + + 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) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + # target = 0 + # fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + # fan_target_sysfs_path = self.__search_file_by_name( + # FAN_PATH.format(self.fan_tray_index + 1), fan_target_sysfs_name) + # fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0 + # target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM) + + # return target + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH.format(self.fan_tray_index + 1), fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return 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 + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + fan_target_sysfs_path = self.__search_file_by_name( + FAN_PATH.format(self.fan_tray_index + 1), fan_target_sysfs_name) + return self.__write_txt_file(fan_target_sysfs_path, int(pwm)) + + 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: always True + """ + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fan_index].format(self.fan_tray_index) + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: always True + """ + + return True + + def get_status(self): + """ + Retrieves the status of the FAN + Returns: + bool: always True + """ + return True diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan_drawer.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..9940645ff92d --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/fan_drawer.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +######################################################################## +# Centec V682 48X8C +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CENTEC_FANS_PER_FANTRAY = 4 + + +class FanDrawer(FanDrawerBase): + """Centec V682 48X8C Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + for i in range(CENTEC_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) + + def set_status_led(self, color): + """ + Sets the state of the fan drawer status LED + + Args: + color: A string representing the color with which to set the + fan drawer status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + return True diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/led.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/led.py new file mode 100644 index 000000000000..492d6983ea76 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/led.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the led status which are available in the platform +# +############################################################################# + +from subprocess import Popen, PIPE, STDOUT + +class SystemLed(object): + STATUS_LED_COLOR_GREEN = 'green' + STATUS_LED_COLOR_ORANGE = 'orange' + STATUS_LED_COLOR_OFF = 'off' + + SYSTEM_LED_PATH = '/sys/class/leds/system/brightness' + + def set_status(self, color): + status = False + + if color == SystemLed.STATUS_LED_COLOR_ORANGE: + cmd = 'i2cset -y 0 0x36 0x2 0xb' + Popen(cmd, shell=True) + status = True + elif color == SystemLed.STATUS_LED_COLOR_OFF: + cmd = 'i2cset -y 0 0x36 0x2 0x0' + Popen(cmd, shell=True) + status = True + elif color == SystemLed.STATUS_LED_COLOR_GREEN: + cmd = 'i2cset -y 0 0x36 0x2 0x5' + Popen(cmd, shell=True) + status = True + + return status + + def get_status(self): + cmd = 'i2cget -y 0 0x36 0x2' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + if status == 11: + return SystemLed.STATUS_LED_COLOR_ORANGE + elif status == 0: + return SystemLed.STATUS_LED_COLOR_OFF + else: + return SystemLed.STATUS_LED_COLOR_GREEN diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/platform.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/platform.py new file mode 100644 index 000000000000..59d37da538a1 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/platform.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs for Centec V682-48X8C +# + + +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): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/psu.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/psu.py new file mode 100644 index 000000000000..779209c71c2e --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/psu.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from __future__ import print_function + +from subprocess import Popen, PIPE, STDOUT + +try: + from sonic_platform_base.psu_base import PsuBase +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +class Psu(PsuBase): + """Centec Platform-specific PSU class""" + + def __init__(self, index): + self._index = index + self._fan_list = [] + + def get_presence(self): + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + presence = ((status & (1 << (3 * (self._index - 1) + 1))) == 0) + return presence + + def get_powergood_status(self): + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + powergood = ((status & (1 << (3 * (self._index - 1) + 2))) != 0) + return powergood diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/sfp.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/sfp.py new file mode 100644 index 000000000000..1d4154ff8384 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/sfp.py @@ -0,0 +1,1618 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import os +import time +import re +import collections +#import subprocess +#import sonic_device_util +from ctypes import create_string_buffer +from subprocess import Popen, PIPE, STDOUT +from sonic_py_common import device_info + +try: + from sonic_platform_base.sfp_base import SfpBase +# from sonic_platform_base.sonic_eeprom import eeprom_dts + 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") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 +SFP_INFO_OFFSET = 0 +SFP_DOM_OFFSET = 256 + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 1 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_MODULE_THRESHOLD_OFFSET = 512 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 560 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWEROVERRIDE_BIT = 0 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +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') + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + dom_supported = True + dom_temp_supported = True + dom_volt_supported = True + dom_rx_power_supported = True + dom_tx_power_supported = True + dom_tx_disable_supported = True + calibration = 1 + + # Path to QSFP sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "x86_64-centec_v682_48x8c-r0" + HWSKU = "V682-48x8c" + + def __init__(self, sfp_index, sfp_type): + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, self.HWSKU, "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + # Port number + self.PORT_START = 256 + self.PORT_END = 0 + self.QSFP_START = 48 + self.QSFP_END = 0 + + for port_cfg in self._port_cfgs: + if int(port_cfg.index) <= self.PORT_START: + self.PORT_START = int(port_cfg.index) + elif int(port_cfg.index) >= self.PORT_END: + self.PORT_END = int(port_cfg.index) + self.QSFP_END = self.PORT_END + + # Init index + self.index = sfp_index + self.port_num = self.index + #self.dom_supported = False + self.sfp_type = sfp_type + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + self.port_to_eeprom_mapping = {} + self.port_to_i2c_mapping = { + # mac i2c presence enable(or reset for qsfp) + 32 : (13, 0x36, 0x11, 0, 0x36, 0x0e, 0), + 33 : (12, 0x36, 0x11, 1, 0x36, 0x0e, 1), + 34 : (11, 0x36, 0x11, 2, 0x36, 0x0e, 2), + 35 : (10, 0x36, 0x11, 3, 0x36, 0x0e, 3), + 0 : (17, 0x36, 0x11, 4, 0x36, 0x0e, 4), + 4 : (16, 0x36, 0x11, 5, 0x36, 0x0e, 5), + 8 : (15, 0x36, 0x11, 6, 0x36, 0x0e, 6), + 12 : (14, 0x36, 0x11, 7, 0x36, 0x0e, 7), + 16 : (21, 0x36, 0x12, 0, 0x36, 0x0f, 0), + 20 : (20, 0x36, 0x12, 1, 0x36, 0x0f, 1), + 24 : (19, 0x36, 0x12, 2, 0x36, 0x0f, 2), + 28 : (18, 0x36, 0x12, 3, 0x36, 0x0f, 3), + 40 : (25, 0x36, 0x12, 4, 0x36, 0x0f, 4), + 44 : (24, 0x36, 0x12, 5, 0x36, 0x0f, 5), + 48 : (23, 0x36, 0x12, 6, 0x36, 0x0f, 6), + 52 : (22, 0x36, 0x12, 7, 0x36, 0x0f, 7), + 56 : (29, 0x36, 0x13, 0, 0x36, 0x10, 0), + 60 : (28, 0x36, 0x13, 1, 0x36, 0x10, 1), + 64 : (27, 0x36, 0x13, 2, 0x36, 0x10, 2), + 68 : (26, 0x36, 0x13, 3, 0x36, 0x10, 3), + 72 : (33, 0x36, 0x13, 4, 0x36, 0x10, 4), + 73 : (32, 0x36, 0x13, 5, 0x36, 0x10, 5), + 74 : (31, 0x36, 0x13, 6, 0x36, 0x10, 6), + 75 : (30, 0x36, 0x13, 7, 0x36, 0x10, 7), + 232 : (37, 0x37, 0x11, 0, 0x37, 0x0e, 0), + 233 : (36, 0x37, 0x11, 1, 0x37, 0x0e, 1), + 234 : (35, 0x37, 0x11, 2, 0x37, 0x0e, 2), + 235 : (34, 0x37, 0x11, 3, 0x37, 0x0e, 3), + 200 : (41, 0x37, 0x11, 4, 0x37, 0x0e, 4), + 204 : (40, 0x37, 0x11, 5, 0x37, 0x0e, 5), + 208 : (39, 0x37, 0x11, 6, 0x37, 0x0e, 6), + 212 : (38, 0x37, 0x11, 7, 0x37, 0x0e, 7), + 216 : (45, 0x37, 0x12, 0, 0x37, 0x0f, 0), + 220 : (44, 0x37, 0x12, 1, 0x37, 0x0f, 1), + 224 : (43, 0x37, 0x12, 2, 0x37, 0x0f, 2), + 228 : (42, 0x37, 0x12, 3, 0x37, 0x0f, 3), + 160 : (49, 0x37, 0x12, 4, 0x37, 0x0f, 4), + 164 : (48, 0x37, 0x12, 5, 0x37, 0x0f, 5), + 168 : (47, 0x37, 0x12, 6, 0x37, 0x0f, 6), + 172 : (46, 0x37, 0x12, 7, 0x37, 0x0f, 7), + 176 : (53, 0x37, 0x13, 0, 0x37, 0x10, 0), + 180 : (52, 0x37, 0x13, 1, 0x37, 0x10, 1), + 184 : (51, 0x37, 0x13, 2, 0x37, 0x10, 2), + 188 : (50, 0x37, 0x13, 3, 0x37, 0x10, 3), + 192 : (57, 0x37, 0x13, 4, 0x37, 0x10, 4), + 193 : (56, 0x37, 0x13, 5, 0x37, 0x10, 5), + 194 : (55, 0x37, 0x13, 6, 0x37, 0x10, 6), + 195 : (54, 0x37, 0x13, 7, 0x37, 0x10, 7), + 120 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 121 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 122 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 123 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 124 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 125 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 126 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 127 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 80 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 81 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 82 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 83 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 84 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 85 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 86 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 87 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 240 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 241 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 242 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 243 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 244 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 245 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 246 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 247 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 280 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 281 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 282 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 283 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 284 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3), + 285 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3), + 286 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3), + 287 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3) + } + + for port_cfg in self._port_cfgs: + i2c_idx = self.port_to_i2c_mapping[int(port_cfg.lanes.split(',')[0])][0] + port_eeprom_path = eeprom_path.format(i2c_idx) + self.port_to_eeprom_mapping[int(port_cfg.index)] = port_eeprom_path + + self.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'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', + 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + SfpBase.__init__(self) + + + 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 __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def get_presence(self): + """ + Retrieves the presence of the SFP module + Returns: + bool: True if SFP module is present, False if not + """ + # Check for invalid port_num + if self.port_num < self.PORT_START or self.port_num > self.PORT_END: + return False + + sfp_info = self.port_to_i2c_mapping[int(self._port_cfgs[self.port_num].lanes.split(',')[0])] + cmd = 'i2cget -y 0 {0} {1}'.format(sfp_info[1], sfp_info[2]) + presence = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + presence &= (1 << sfp_info[3]) + + try: + with open(self.port_to_eeprom_mapping[self.port_num], mode='rb', buffering=0) as fd: + fd.read() + except IOError: + return False + + return (presence == 0) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except Exception: + eeprom_raw = None + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + 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.calibration = 0 + return + + if self.sfp_type == "QSFP": + 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_specific_bytes( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_dom_capability = int(qsfp_dom_capability_raw[0], 16) + + qsfp_version_compliance_raw = self.__read_eeprom_specific_bytes( + QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_OFFSET) + if qsfp_version_compliance_raw is not None: + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + 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 + return + + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qsfp_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qsfp_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qsfp_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qsfp_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qsfp_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + self.dom_tx_disable_supported = True + 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": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + 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 + application_advertisement |1*255VCHAR |supported applications advertisement + ======================================================================== + """ + + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + transceiver_info_dict['specification_compliance'] = '{}' + if not self.get_presence(): + return transceiver_info_dict + + if self.sfp_type == QSFP_TYPE: + offset = QSFP_INFO_OFFSET + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return transceiver_info_dict + + elif self.sfp_type == SFP_TYPE: + offset = SFP_INFO_OFFSET + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return transceiver_info_dict + else: + return transceiver_info_dict + + # Add retry for xcvr eeprom to get ready + max_retry = 10 + for i in range(0,max_retry): + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is not None: + break + else: + if not self.get_presence(): + return transceiver_info_dict + elif i == max_retry-1: + pass + else: + time.sleep(0.5) + + if sfp_interface_bulk_raw is None: + return transceiver_info_dict + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + 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'] + transceiver_info_dict['type_abbrv_name'] = 'N/A' + 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. + ======================================================================== + """ + + if not self.get_presence(): + return None + + self._dom_capability_detect() + + if self.sfp_type == QSFP_TYPE: + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not sfpi_obj or not sfpd_obj: + return None + + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + offset = QSFP_DOM_OFFSET + offset_xcvr = QSFP_INFO_OFFSET + + # 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_specific_bytes( + (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_dom_capability_data = sfpi_obj.parse_dom_capability( + qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) + 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_specific_bytes( + (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) + 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'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH) + if qsfp_dom_rev_raw is not None: + qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + + # The tx_power monitoring is only available on QSFP which compliant with SFF-8636 + # and claimed that it support tx_power with one indicator bit. + dom_channel_monitor_data = {} + dom_channel_monitor_raw = None + qsfp_tx_power_support = qsfp_dom_capability_data['data']['Tx_power_support']['value'] + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + + else: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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) + 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'] + + if dom_channel_monitor_raw: + 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'] + elif self.sfp_type == SFP_TYPE: + sfpd_obj = sff8472Dom() + if not sfpd_obj: + return None + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET) + if eeprom_ifraw is not None: + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = SFP_DOM_OFFSET + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + + 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_specific_bytes( + (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH) + 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_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_voltage_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] + transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] + else: + return None + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num( + transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disable_channel'] = self.get_tx_disable_channel() + + 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. + ======================================================================== + """ + transceiver_dom_threshold_info_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + if self.sfp_type == QSFP_TYPE: + sfpd_obj = sff8436Dom() + if not self.get_presence() or not sfpd_obj: + return None + DOM_OFFSET = 0 + transceiver_dom_threshold_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + offset = DOM_OFFSET + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + module_threshold_values = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_channel_thres_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNEL_THRESHOLD_OFFSET), QSFP_CHANNEL_THRESHOLD_WIDTH) + if dom_channel_thres_raw is not None: + channel_threshold_values = sfpd_obj.parse_channel_threshold_values(dom_channel_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + else: + channel_threshold_data = None + if channel_threshold_data: + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + for key in transceiver_dom_threshold_dict: + transceiver_dom_threshold_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_dict[key]) + + return transceiver_dom_threshold_dict + + elif self.sfp_type == SFP_TYPE: + sfpd_obj = sff8472Dom() + + if not self.get_presence() and not sfpd_obj: + return None + DOM_OFFSET = 256 + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + if eeprom_ifraw is not None: + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_threshold_info_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['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']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + else: + return None + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + # Check for invalid port_num + if self.port_num < self.PORT_START or self.port_num > self.PORT_END or self.sfp_type == SFP_TYPE: + return False + + sfp_info = self.port_to_i2c_mapping[int(self._port_cfgs[self.port_num].lanes.split(',')[0])] + cmd = 'i2cget -y 0 {0} {1}'.format(sfp_info[4], sfp_info[5]) + reset_status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + reset_status &= (1 << sfp_info[6]) + + return (reset_status == 1) + + 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. + """ + if not self.dom_supported: + return None + + rx_los_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + elif self.sfp_type == SFP_TYPE: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + else: + return None + + return rx_los_list + + 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. + """ + if not self.dom_supported: + return None + + tx_fault_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + elif self.sfp_type == SFP_TYPE: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + else: + return None + + return tx_fault_list + + 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 + """ + if not self.dom_supported: + return None + + tx_disable_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + elif self.sfp_type == SFP_TYPE: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0xC0 != 0) + else: + return None + else: + return None + + return tx_disable_list + + 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. + """ + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return 0 + elif self.sfp_type == QSFP_TYPE: + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + else: + return None + + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this QSFP module + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + 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 + """ + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_POWEROVERRIDE_OFFSET), QSFP_POWEROVERRIDE_WIDTH) + if dom_control_raw is not None: + if int(dom_control_raw[0],16) & (0x01 << QSFP_POWEROVERRIDE_BIT): + return True + else: + return False + else: + return None + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_temp_supported: + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) + 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 + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = 1 + + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + 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 + else: + return None + else: + 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 + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_volt_supported: + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + voltage = self._convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + sfpd_obj._calibration_type = self.calibration + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + voltage = self._convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + else: + 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'] + """ + tx_bias_list = [] + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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 == SFP_TYPE: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = self.calibration + + if self.dom_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + 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'])) + else: + return None + else: + return None + else: + return None + + 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'] + """ + rx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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) + 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: + return None + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + 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'])) + else: + return None + else: + return None + else: + return None + + 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'] + """ + tx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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_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: + return None + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + 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'])) + else: + return None + else: + return None + else: + return None + + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default state. + Returns: + A boolean, True if successful, False if not + """ + if not self.get_presence(): + return False + + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + sfp_info = self.port_to_i2c_mapping[int(self._port_cfgs[self.port_num].lanes.split(',')[0])] + cmd = 'i2cget -y 0 {0} {1}'.format(sfp_info[4], sfp_info[5]) + reset = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + + reset &= ~(1 << sfp_info[6]) + cmd = 'i2cset -y 0 {0} {1} {2}'.format(sfp_info[4], sfp_info[5], reset) + Popen(cmd, shell=True) + + reset |= (1 << sfp_info[6]) + cmd = 'i2cset -y 0 {0} {1} {2}'.format(sfp_info[4], sfp_info[5], reset) + Popen(cmd, shell=True) + + return True + + 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 + """ + if not self.get_presence(): + return False + + if self.sfp_type == SFP_TYPE: + if self.dom_tx_disable_supported: + offset = 256 + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + status_control_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if status_control_raw is not None: + # Set bit 6 for Soft TX Disable Select + # 01000000 = 64 and 10111111 = 191 + tx_disable_bit = 64 if tx_disable else 191 + status_control = int(status_control_raw[0], 16) + tx_disable_ctl = (status_control | tx_disable_bit) if tx_disable else ( + status_control & tx_disable_bit) + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="r+b", buffering=0) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom.seek(offset + SFP_STATUS_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + else: + return False + elif self.sfp_type == QSFP_TYPE: + if self.dom_tx_disable_supported: + channel_mask = 0x0f + if tx_disable: + return self.tx_disable_channel(channel_mask, True) + else: + return self.tx_disable_channel(channel_mask, False) + else: + return False + else: + return None + + 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 + """ + if not self.get_presence(): + return False + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + if self.dom_tx_disable_supported: + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + if disable: + tx_disable_ctl = channel_state | channel + else: + tx_disable_ctl = channel_state & (~channel) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + else: + return False + else: + return None + + 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 + """ + 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 + """ + # SFP doesn't support this feature + if not self.get_presence(): + return False + + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfsfile_eeprom = open(self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + else: + return None + + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return "Ethernet{}".format(self.port_num) + diff --git a/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/thermal.py b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/thermal.py new file mode 100644 index 000000000000..ca4e35969269 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48x8c/sonic_platform/thermal.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1" + + def __init__(self, thermal_index): + self.index = thermal_index + self.high_threshold = float(112) + + # Add thermal name + self.THERMAL_NAME_LIST.append("ASIC") + + # Set hwmon path + self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH + self.ss_key = self.THERMAL_NAME_LIST[self.index - 1] + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + raise IOError("Unable to open %s file !" % file_path) + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return float("{:.3f}".format(temp)) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + 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 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + 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 + """ + return self.high_threshold + + 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 + """ + self.high_threshold = float(temperature) + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + if not self.get_presence(): + return False + + return True diff --git a/platform/centec/sonic-platform-modules-v682/48y8c-d/service/release.py b/platform/centec/sonic-platform-modules-v682/48y8c-d/service/release.py index 2c799e6ef3d6..a5174b02daa4 100644 --- a/platform/centec/sonic-platform-modules-v682/48y8c-d/service/release.py +++ b/platform/centec/sonic-platform-modules-v682/48y8c-d/service/release.py @@ -1,10 +1,10 @@ -#!/usr/bin/python2 +#!/usr/bin/env python import os import sys import time -susi4_lib = '/usr/local/lib/python2.7/dist-packages/' +susi4_lib = '/usr/local/lib/python3.9/dist-packages/' if not susi4_lib in os.environ.setdefault('LD_LIBRARY_PATH', ''): os.environ['LD_LIBRARY_PATH'] += (':' + susi4_lib) try: diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/modules/Makefile b/platform/centec/sonic-platform-modules-v682/48y8c/modules/Makefile new file mode 100644 index 000000000000..53c96acb0cb7 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_v682_48y8c_platform.o rtc-sd2405.o diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/modules/centec_v682_48y8c_platform.c b/platform/centec/sonic-platform-modules-v682/48y8c/modules/centec_v682_48y8c_platform.c new file mode 100644 index 000000000000..28e0e9f2610d --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/modules/centec_v682_48y8c_platform.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define SFP_NUM 48 +#define QSFP_NUM 8 +#define PORT_NUM (SFP_NUM + QSFP_NUM) +#endif + +#if SEP("drivers:leds") +extern void v682_48y8c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness v682_48y8c_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port0", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port1", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port2", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port3", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port4", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port5", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port6", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port7", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port8", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port9", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port10", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port11", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port12", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port13", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port14", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port15", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port16", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port17", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port18", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port19", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port20", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port21", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port22", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port23", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port24", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port25", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port26", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port27", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port28", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port29", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port30", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port31", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port32", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port33", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port34", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port35", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port36", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port37", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port38", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port39", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port40", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port41", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port42", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port43", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port44", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port45", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port46", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port47", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port48", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port49", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port50", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port51", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port52", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port53", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port54", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +{ .name = "port55", .brightness_set = v682_48y8c_led_port_set, .brightness_get = v682_48y8c_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void v682_48y8c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum] = set_value; + + return; +} + +enum led_brightness v682_48y8c_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum]; +} + +static int v682_48y8c_init_led(void) +{ + int ret = 0; + int i = 0; + + for (i = 0; i < PORT_NUM; i++) + { + ret = led_classdev_register(NULL, &(led_dev_port[i])); + if (ret != 0) + { + printk(KERN_CRIT "create v682_48y8c led_dev_port%d device failed\n", i); + continue; + } + } + + return ret; +} + +static int v682_48y8c_exit_led(void) +{ + int i = 0; + + for (i = 0; i < PORT_NUM; i++) + { + led_classdev_unregister(&(led_dev_port[i])); + } + + return 0; +} +#endif + +static int v682_48y8c_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "init v682_48y8c board dirver...\n"); + + ret = v682_48y8c_init_led(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "init v682_48y8c board driver failed\n"); + else + printk(KERN_ALERT "init v682_48y8c board dirver...ok\n"); + + return 0; +} + +static void v682_48y8c_exit(void) +{ + printk(KERN_INFO "deinit v682_48y8c board dirver...\n"); + + v682_48y8c_exit_led(); + + printk(KERN_INFO "deinit v682_48y8c board dirver...ok\n"); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("v682-48y8c board driver"); +module_init(v682_48y8c_init); +module_exit(v682_48y8c_exit); diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/modules/rtc-sd2405.c b/platform/centec/sonic-platform-modules-v682/48y8c/modules/rtc-sd2405.c new file mode 100644 index 000000000000..c22ab3349144 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/modules/rtc-sd2405.c @@ -0,0 +1,264 @@ +/* + * rtc class driver for the SD2405 chip + * + * Author: Dale Farnsworth + * + * based on previously existing rtc class drivers + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include + +#define DRV_VERSION "0.1" + +/* + * register indices + */ +#define SD2405_REG_SC 0x0 /* seconds 00-59 */ +#define SD2405_REG_MN 0x1 /* minutes 00-59 */ +#define SD2405_REG_HR 0x2 /* hours 00-23 */ +#define SD2405_REG_DW 0x3 /* day of week 1-7 */ +#define SD2405_REG_DT 0x4 /* day of month 00-31 */ +#define SD2405_REG_MO 0x5 /* month 01-12 */ +#define SD2405_REG_YR 0x6 /* year 00-99 */ + +#define SD2405_REG_CTRL1 0xf /* control 1 */ +#define SD2405_REG_CTRL2 0x10 /* control 2 */ +#define SD2405_REG_CTRL3 0x11 /* control 3 ARST*/ + +#define SD2405_REG_LEN 7 + +/* + * register write protect + */ +#define SD2405_REG_CONTROL1_WRITE 0x80 +#define SD2405_REG_CONTROL2_WRITE 0x84 + + +#define SD2405_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ + +static struct i2c_driver sd2405_driver; + +#if 1 +/* modified by shil, for bug 46153 */ +static int sd2405_i2c_read_regs(struct i2c_client *client, u8 *buf) +{ + int i; + + for (i = 0; i < SD2405_REG_LEN; i++) { + buf[i] = i2c_smbus_read_byte_data(client, SD2405_REG_SC+i); + } + return 0; +} + +/* modified by shil, for bug 46153 */ +static int sd2405_i2c_write_regs(struct i2c_client *client, u8 const *buf) +{ + int i; + + for (i = 0; i < SD2405_REG_LEN; i++) { + i2c_smbus_write_byte_data(client, SD2405_REG_SC+i, buf[i]); + msleep(SD2405_IDLE_TIME_AFTER_WRITE); + } + return 0; +} + +#else +static int sd2405_i2c_read_regs(struct i2c_client *client, u8 *buf) +{ + struct i2c_msg msgs[1] = { + { + .addr = client->addr, + .flags = I2C_M_RD, /* read */ + .len = SD2405_REG_LEN, + .buf = buf} + }; + int rc; + + rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (rc != ARRAY_SIZE(msgs)) { + dev_err(&client->dev, "%s: register read failed\n", __func__); + return -EIO; + } + return 0; +} + +static int sd2405_i2c_write_regs(struct i2c_client *client, u8 const *buf) +{ + int rc; + + u8 temp_reg[SD2405_REG_LEN+1] = {0}; + memcpy(&temp_reg[1], buf, SD2405_REG_LEN); + + struct i2c_msg msgs[1] = { + { + .addr = client->addr, + .flags = 0, /* write */ + .len = SD2405_REG_LEN+1, + .buf = temp_reg} + }; + + rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (rc != ARRAY_SIZE(msgs)) + goto write_failed; + msleep(SD2405_IDLE_TIME_AFTER_WRITE); + + return 0; + + write_failed: + dev_err(&client->dev, "%s: register write failed\n", __func__); + return -EIO; +} +#endif + +static int sd2405_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) +{ + int rc; + u8 regs[SD2405_REG_LEN]; + + rc = sd2405_i2c_read_regs(client, regs); + if (rc < 0) + return rc; + + tm->tm_sec = bcd2bin(regs[SD2405_REG_SC]); + tm->tm_min = bcd2bin(regs[SD2405_REG_MN]); + tm->tm_hour = bcd2bin(regs[SD2405_REG_HR] & 0x3f); + tm->tm_wday = bcd2bin(regs[SD2405_REG_DW]); + tm->tm_mday = bcd2bin(regs[SD2405_REG_DT]); + tm->tm_mon = bcd2bin(regs[SD2405_REG_MO]) - 1; + tm->tm_year = bcd2bin(regs[SD2405_REG_YR]) + 100; + + return 0; +} + +static int sd2405_i2c_set_write_protect(struct i2c_client *client) +{ + int rc; + rc = i2c_smbus_write_byte_data(client, SD2405_REG_CTRL1, 0); + rc += i2c_smbus_write_byte_data(client, SD2405_REG_CTRL2, 0); + if (rc < 0) { + dev_err(&client->dev, "%s: control register write failed\n", + __func__); + return -EIO; + } + return 0; +} + +static int sd2405_i2c_clear_write_protect(struct i2c_client *client) +{ + int rc; + rc = i2c_smbus_write_byte_data(client, SD2405_REG_CTRL2, SD2405_REG_CONTROL1_WRITE); + rc += i2c_smbus_write_byte_data(client, SD2405_REG_CTRL1, SD2405_REG_CONTROL2_WRITE); + if (rc < 0) { + dev_err(&client->dev, "%s: control register write failed\n", + __func__); + return -EIO; + } + return 0; +} + +static int +sd2405_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) +{ + u8 regs[SD2405_REG_LEN]; + int rc; + + rc = sd2405_i2c_clear_write_protect(client); + if (rc < 0) + return rc; + + regs[SD2405_REG_SC] = bin2bcd(tm->tm_sec); + regs[SD2405_REG_MN] = bin2bcd(tm->tm_min); + regs[SD2405_REG_HR] = bin2bcd(tm->tm_hour)|0x80; + regs[SD2405_REG_DW] = bin2bcd(tm->tm_wday); + regs[SD2405_REG_DT] = bin2bcd(tm->tm_mday); + regs[SD2405_REG_MO] = bin2bcd(tm->tm_mon + 1); + regs[SD2405_REG_YR] = bin2bcd(tm->tm_year - 100); + + rc = sd2405_i2c_write_regs(client, regs); + if (rc < 0) + return rc; + + rc = sd2405_i2c_set_write_protect(client); + if (rc < 0) + return rc; + + return 0; +} + +static int sd2405_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return sd2405_i2c_read_time(to_i2c_client(dev), tm); +} + +static int sd2405_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return sd2405_i2c_set_time(to_i2c_client(dev), tm); +} + +static const struct rtc_class_ops sd2405_rtc_ops = { + .read_time = sd2405_rtc_read_time, + .set_time = sd2405_rtc_set_time, +}; + +static int +sd2405_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct rtc_device *rtc; + +/* modified by shil, for bug 46153 */ +#if 0 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; +#endif + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + i2c_set_clientdata(client, rtc); + rtc->ops = &sd2405_rtc_ops; + + return rtc_register_device(rtc); +} + +static struct i2c_device_id sd2405_id[] = { + { "sd2405", 0 }, + { } +}; + +static struct i2c_driver sd2405_driver = { + .driver = { + .name = "rtc-sd2405", + }, + .probe = sd2405_probe, + .id_table = sd2405_id, +}; + +static int __init sd2405_init(void) +{ + return i2c_add_driver(&sd2405_driver); +} + +static void __exit sd2405_exit(void) +{ + i2c_del_driver(&sd2405_driver); +} + +MODULE_DESCRIPTION("Maxim SD2405 RTC driver"); +MODULE_AUTHOR("Dale Farnsworth "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(sd2405_init); +module_exit(sd2405_exit); diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/service/48y8c_platform.service b/platform/centec/sonic-platform-modules-v682/48y8c/service/48y8c_platform.service new file mode 100644 index 000000000000..48327ec456b2 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/service/48y8c_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-v682-48y8c start +ExecStop=-/etc/init.d/platform-modules-v682-48y8c stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/service/release.py b/platform/centec/sonic-platform-modules-v682/48y8c/service/release.py new file mode 100644 index 000000000000..8ae790a24fdc --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/service/release.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import os +import time + +def release_board(): + if open('/proc/cmdline', 'r').readlines()[0].find('SONIC_BOOT_TYPE=warm') != -1: + return + + os.system('i2cset -y 0 0x37 0x4 0x0') + time.sleep(1) + os.system('i2cset -y 0 0x37 0x4 0x1') + time.sleep(1) + os.system('echo 1 > /sys/bus/pci/devices/0000\:00\:1c.0/remove') + time.sleep(1) + os.system('echo 1 > /sys/bus/pci/rescan') + time.sleep(1) + # EPLD_QSFP_RST + os.system('i2cset -y 0 0x36 0x5 0xff') + os.system('i2cset -y 0 0x37 0x5 0xff') + # EPLD_QSFP_INT_MASK + os.system('i2cset -y 0 0x36 0xd 0xff') + os.system('i2cset -y 0 0x37 0xd 0xff') + # EPLD_PPU_INT_MASK + os.system('i2cset -y 0 0x36 0xb 0x00') + # EPLD_SFP_DISABLE1 + os.system('i2cset -y 0 0x36 0xe 0x00') + os.system('i2cset -y 0 0x37 0xe 0x00') + # EPLD_SFP_DISABLE2 + os.system('i2cset -y 0 0x36 0xf 0x00') + os.system('i2cset -y 0 0x37 0xf 0x00') + # EPLD_SFP_DISABLE3 + os.system('i2cset -y 0 0x36 0x10 0x00') + os.system('i2cset -y 0 0x37 0x10 0x00') + +if __name__ == '__main__': + release_board() diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/setup.py b/platform/centec/sonic-platform-modules-v682/48y8c/setup.py new file mode 100644 index 000000000000..e0713e550f11 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize centec v682-48y8c platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) + diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/__init__.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/__init__.py new file mode 100644 index 000000000000..6e50c02e9d1f --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer", "led"] +from . import platform diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/chassis.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/chassis.py new file mode 100644 index 000000000000..566612e40654 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/chassis.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import re + import time + import collections + from sonic_py_common import device_info + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 2 +NUM_THERMAL = 1 +NUM_PSU = 2 + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +REBOOT_CAUSE_DIR = "/host/reboot-cause/" +REBOOT_CAUSE_FILE = os.path.join(REBOOT_CAUSE_DIR, "reboot-cause.txt") + +class Chassis(ChassisBase): + # System status LED + _led = None + + def __init__(self): + ChassisBase.__init__(self) + + self.data = {'valid':0, 'last':0} + self.sfp_presence = {} + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "V682-48y8c", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + _port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + # Initialize EEPROM + self._eeprom = Eeprom() + + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i + 1) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index + 1) + self._psu_list.append(psu) + + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + # Initialize SFP + for port_cfg in _port_cfgs: + sfp = Sfp(int(port_cfg.index), 'SFP' if int(port_cfg.index) < 48 else 'QSFP') + self._sfp_list.append(sfp) + self.sfp_presence[int(port_cfg.index)] = False + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + 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(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + 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_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. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + 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. + """ + if os.path.exists(REBOOT_CAUSE_FILE): + with open(REBOOT_CAUSE_FILE) as reboot_cause_file: + reboot_cause = reboot_cause_file.readline() + if re.search(r'User issued', reboot_cause) is None: + return (self.REBOOT_CAUSE_POWER_LOSS, None) + else: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + else: + return (self.REBOOT_CAUSE_POWER_LOSS, None) + + def get_change_event(self, timeout=2000): + """ + 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. + """ + SFP_STATUS_INSERTED = '1' + SFP_STATUS_REMOVED = '0' + + now = time.time() + port_dict = {} + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return False, {'sfp': {}} + + for sfp in self._sfp_list: + sfp_presence = sfp.get_presence() + if sfp_presence != self.sfp_presence[sfp.index]: + self.sfp_presence[sfp.index] = sfp_presence + if sfp_presence: + port_dict[sfp.index] = SFP_STATUS_INSERTED + else: + port_dict[sfp.index] = SFP_STATUS_REMOVED + + if bool(port_dict): + self.data['last'] = now + self.data['valid'] = 1 + ret = True + else: + time.sleep(0.5) + ret = False + + ret_dict = {'sfp': port_dict} + return ret, ret_dict + + def get_num_psus(self): + return len(self._psu_list) + + def get_psu(self, psu_index): + return self._psu_list[psu_index] + + def initizalize_system_led(self): + from .led import SystemLed + Chassis._led = SystemLed() + + 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 if not Chassis._led else Chassis._led.set_status(color) + + 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. + """ + return None if not Chassis._led else Chassis._led.get_status() diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/eeprom.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/eeprom.py new file mode 100644 index 000000000000..7d2750475717 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/eeprom.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_eeprom import eeprom_tlvinfo + from sonic_py_common import device_info + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + self.__eeprom_path = platform_path + '/eeprom_file' + + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + + self.__eeprom_tlv_dict = dict() + try: + self.open_eeprom() + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += str(tlv[6:6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + 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_tlv_dict + diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan.py new file mode 100644 index 000000000000..5f7b256eafb8 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_PATH = "/sys/class/hwmon/hwmon{}/" +FAN_MAX_PWM = 255 +FAN_FAN_PWM = "pwm{}" +FAN_FAN_INPUT = "fan{}_input" +FAN_MAX_RPM = 15000 +FAN_NAME_LIST = ["FAN-{}-1", "FAN-{}-2", "FAN-{}-3", "FAN-{}-4"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + + FanBase.__init__(self) + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except IOError: + return False + return True + + def __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + direction = self.FAN_DIRECTION_EXHAUST + return direction + + 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) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH.format(self.fan_tray_index + 1), fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return int(speed) + + 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) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + # target = 0 + # fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + # fan_target_sysfs_path = self.__search_file_by_name( + # FAN_PATH.format(self.fan_tray_index + 1), fan_target_sysfs_name) + # fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0 + # target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM) + + # return target + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH.format(self.fan_tray_index + 1), fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return 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 + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + fan_target_sysfs_path = self.__search_file_by_name( + FAN_PATH.format(self.fan_tray_index + 1), fan_target_sysfs_name) + return self.__write_txt_file(fan_target_sysfs_path, int(pwm)) + + 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: always True + """ + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fan_index].format(self.fan_tray_index) + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: always True + """ + + return True + + def get_status(self): + """ + Retrieves the status of the FAN + Returns: + bool: always True + """ + return True diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan_drawer.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..781ba7957a4e --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/fan_drawer.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +######################################################################## +# Centec V682 48Y8C +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CENTEC_FANS_PER_FANTRAY = 4 + + +class FanDrawer(FanDrawerBase): + """Centec V682 48Y8C Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + for i in range(CENTEC_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) + + def set_status_led(self, color): + """ + Sets the state of the fan drawer status LED + + Args: + color: A string representing the color with which to set the + fan drawer status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + return True diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/led.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/led.py new file mode 100644 index 000000000000..492d6983ea76 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/led.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the led status which are available in the platform +# +############################################################################# + +from subprocess import Popen, PIPE, STDOUT + +class SystemLed(object): + STATUS_LED_COLOR_GREEN = 'green' + STATUS_LED_COLOR_ORANGE = 'orange' + STATUS_LED_COLOR_OFF = 'off' + + SYSTEM_LED_PATH = '/sys/class/leds/system/brightness' + + def set_status(self, color): + status = False + + if color == SystemLed.STATUS_LED_COLOR_ORANGE: + cmd = 'i2cset -y 0 0x36 0x2 0xb' + Popen(cmd, shell=True) + status = True + elif color == SystemLed.STATUS_LED_COLOR_OFF: + cmd = 'i2cset -y 0 0x36 0x2 0x0' + Popen(cmd, shell=True) + status = True + elif color == SystemLed.STATUS_LED_COLOR_GREEN: + cmd = 'i2cset -y 0 0x36 0x2 0x5' + Popen(cmd, shell=True) + status = True + + return status + + def get_status(self): + cmd = 'i2cget -y 0 0x36 0x2' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + if status == 11: + return SystemLed.STATUS_LED_COLOR_ORANGE + elif status == 0: + return SystemLed.STATUS_LED_COLOR_OFF + else: + return SystemLed.STATUS_LED_COLOR_GREEN diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/platform.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/platform.py new file mode 100644 index 000000000000..358edc6f19f2 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/platform.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs for Centec V682-48Y8C-D +# + + +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): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/psu.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/psu.py new file mode 100644 index 000000000000..779209c71c2e --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/psu.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from __future__ import print_function + +from subprocess import Popen, PIPE, STDOUT + +try: + from sonic_platform_base.psu_base import PsuBase +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +class Psu(PsuBase): + """Centec Platform-specific PSU class""" + + def __init__(self, index): + self._index = index + self._fan_list = [] + + def get_presence(self): + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + presence = ((status & (1 << (3 * (self._index - 1) + 1))) == 0) + return presence + + def get_powergood_status(self): + cmd = 'i2cget -y 0 0x36 0x1e' + status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + powergood = ((status & (1 << (3 * (self._index - 1) + 2))) != 0) + return powergood diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/sfp.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/sfp.py new file mode 100644 index 000000000000..3475753cd49d --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/sfp.py @@ -0,0 +1,1618 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import os +import time +import re +import collections +#import subprocess +#import sonic_device_util +from ctypes import create_string_buffer +from subprocess import Popen, PIPE, STDOUT +from sonic_py_common import device_info + +try: + from sonic_platform_base.sfp_base import SfpBase +# from sonic_platform_base.sonic_eeprom import eeprom_dts + 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") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 +SFP_INFO_OFFSET = 0 +SFP_DOM_OFFSET = 256 + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 1 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_MODULE_THRESHOLD_OFFSET = 512 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 560 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWEROVERRIDE_BIT = 0 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +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') + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + dom_supported = True + dom_temp_supported = True + dom_volt_supported = True + dom_rx_power_supported = True + dom_tx_power_supported = True + dom_tx_disable_supported = True + calibration = 1 + + # Path to QSFP sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "x86_64-centec_v682_48y8c-r0" + HWSKU = "V682-48y8c" + + def __init__(self, sfp_index, sfp_type): + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, self.HWSKU, "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + # Port number + self.PORT_START = 256 + self.PORT_END = 0 + self.QSFP_START = 48 + self.QSFP_END = 0 + + for port_cfg in self._port_cfgs: + if int(port_cfg.index) <= self.PORT_START: + self.PORT_START = int(port_cfg.index) + elif int(port_cfg.index) >= self.PORT_END: + self.PORT_END = int(port_cfg.index) + self.QSFP_END = self.PORT_END + + # Init index + self.index = sfp_index + self.port_num = self.index + #self.dom_supported = False + self.sfp_type = sfp_type + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + self.port_to_eeprom_mapping = {} + self.port_to_i2c_mapping = { + # mac i2c presence enable(or reset for qsfp) + 32 : (13, 0x36, 0x11, 0, 0x36, 0x0e, 0), + 33 : (12, 0x36, 0x11, 1, 0x36, 0x0e, 1), + 34 : (11, 0x36, 0x11, 2, 0x36, 0x0e, 2), + 35 : (10, 0x36, 0x11, 3, 0x36, 0x0e, 3), + 0 : (17, 0x36, 0x11, 4, 0x36, 0x0e, 4), + 4 : (16, 0x36, 0x11, 5, 0x36, 0x0e, 5), + 8 : (15, 0x36, 0x11, 6, 0x36, 0x0e, 6), + 12 : (14, 0x36, 0x11, 7, 0x36, 0x0e, 7), + 16 : (21, 0x36, 0x12, 0, 0x36, 0x0f, 0), + 20 : (20, 0x36, 0x12, 1, 0x36, 0x0f, 1), + 24 : (19, 0x36, 0x12, 2, 0x36, 0x0f, 2), + 28 : (18, 0x36, 0x12, 3, 0x36, 0x0f, 3), + 40 : (25, 0x36, 0x12, 4, 0x36, 0x0f, 4), + 44 : (24, 0x36, 0x12, 5, 0x36, 0x0f, 5), + 48 : (23, 0x36, 0x12, 6, 0x36, 0x0f, 6), + 52 : (22, 0x36, 0x12, 7, 0x36, 0x0f, 7), + 56 : (29, 0x36, 0x13, 0, 0x36, 0x10, 0), + 60 : (28, 0x36, 0x13, 1, 0x36, 0x10, 1), + 64 : (27, 0x36, 0x13, 2, 0x36, 0x10, 2), + 68 : (26, 0x36, 0x13, 3, 0x36, 0x10, 3), + 72 : (33, 0x36, 0x13, 4, 0x36, 0x10, 4), + 73 : (32, 0x36, 0x13, 5, 0x36, 0x10, 5), + 74 : (31, 0x36, 0x13, 6, 0x36, 0x10, 6), + 75 : (30, 0x36, 0x13, 7, 0x36, 0x10, 7), + 232 : (37, 0x37, 0x11, 0, 0x37, 0x0e, 0), + 233 : (36, 0x37, 0x11, 1, 0x37, 0x0e, 1), + 234 : (35, 0x37, 0x11, 2, 0x37, 0x0e, 2), + 235 : (34, 0x37, 0x11, 3, 0x37, 0x0e, 3), + 200 : (41, 0x37, 0x11, 4, 0x37, 0x0e, 4), + 204 : (40, 0x37, 0x11, 5, 0x37, 0x0e, 5), + 208 : (39, 0x37, 0x11, 6, 0x37, 0x0e, 6), + 212 : (38, 0x37, 0x11, 7, 0x37, 0x0e, 7), + 216 : (45, 0x37, 0x12, 0, 0x37, 0x0f, 0), + 220 : (44, 0x37, 0x12, 1, 0x37, 0x0f, 1), + 224 : (43, 0x37, 0x12, 2, 0x37, 0x0f, 2), + 228 : (42, 0x37, 0x12, 3, 0x37, 0x0f, 3), + 160 : (49, 0x37, 0x12, 4, 0x37, 0x0f, 4), + 164 : (48, 0x37, 0x12, 5, 0x37, 0x0f, 5), + 168 : (47, 0x37, 0x12, 6, 0x37, 0x0f, 6), + 172 : (46, 0x37, 0x12, 7, 0x37, 0x0f, 7), + 176 : (53, 0x37, 0x13, 0, 0x37, 0x10, 0), + 180 : (52, 0x37, 0x13, 1, 0x37, 0x10, 1), + 184 : (51, 0x37, 0x13, 2, 0x37, 0x10, 2), + 188 : (50, 0x37, 0x13, 3, 0x37, 0x10, 3), + 192 : (57, 0x37, 0x13, 4, 0x37, 0x10, 4), + 193 : (56, 0x37, 0x13, 5, 0x37, 0x10, 5), + 194 : (55, 0x37, 0x13, 6, 0x37, 0x10, 6), + 195 : (54, 0x37, 0x13, 7, 0x37, 0x10, 7), + 120 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 121 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 122 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 123 : (61, 0x36, 0x14, 0, 0x36, 0x05, 0), + 124 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 125 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 126 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 127 : (60, 0x36, 0x14, 1, 0x36, 0x05, 1), + 80 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 81 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 82 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 83 : (59, 0x36, 0x14, 2, 0x36, 0x05, 2), + 84 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 85 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 86 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 87 : (58, 0x36, 0x14, 3, 0x36, 0x05, 3), + 240 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 241 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 242 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 243 : (65, 0x37, 0x14, 0, 0x37, 0x05, 0), + 244 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 245 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 246 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 247 : (64, 0x37, 0x14, 1, 0x37, 0x05, 1), + 280 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 281 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 282 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 283 : (63, 0x37, 0x14, 2, 0x37, 0x05, 2), + 284 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3), + 285 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3), + 286 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3), + 287 : (62, 0x37, 0x14, 3, 0x37, 0x05, 3) + } + + for port_cfg in self._port_cfgs: + i2c_idx = self.port_to_i2c_mapping[int(port_cfg.lanes.split(',')[0])][0] + port_eeprom_path = eeprom_path.format(i2c_idx) + self.port_to_eeprom_mapping[int(port_cfg.index)] = port_eeprom_path + + self.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'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', + 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + SfpBase.__init__(self) + + + 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 __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def get_presence(self): + """ + Retrieves the presence of the SFP module + Returns: + bool: True if SFP module is present, False if not + """ + # Check for invalid port_num + if self.port_num < self.PORT_START or self.port_num > self.PORT_END: + return False + + sfp_info = self.port_to_i2c_mapping[int(self._port_cfgs[self.port_num].lanes.split(',')[0])] + cmd = 'i2cget -y 0 {0} {1}'.format(sfp_info[1], sfp_info[2]) + presence = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + presence &= (1 << sfp_info[3]) + + try: + with open(self.port_to_eeprom_mapping[self.port_num], mode='rb', buffering=0) as fd: + fd.read() + except IOError: + return False + + return (presence == 0) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except Exception: + eeprom_raw = None + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + 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.calibration = 0 + return + + if self.sfp_type == "QSFP": + 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_specific_bytes( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_dom_capability = int(qsfp_dom_capability_raw[0], 16) + + qsfp_version_compliance_raw = self.__read_eeprom_specific_bytes( + QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_OFFSET) + if qsfp_version_compliance_raw is not None: + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + 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 + return + + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qsfp_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qsfp_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qsfp_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qsfp_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qsfp_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + self.dom_tx_disable_supported = True + 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": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + 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 + application_advertisement |1*255VCHAR |supported applications advertisement + ======================================================================== + """ + + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + transceiver_info_dict['specification_compliance'] = '{}' + if not self.get_presence(): + return transceiver_info_dict + + if self.sfp_type == QSFP_TYPE: + offset = QSFP_INFO_OFFSET + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return transceiver_info_dict + + elif self.sfp_type == SFP_TYPE: + offset = SFP_INFO_OFFSET + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return transceiver_info_dict + else: + return transceiver_info_dict + + # Add retry for xcvr eeprom to get ready + max_retry = 10 + for i in range(0,max_retry): + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is not None: + break + else: + if not self.get_presence(): + return transceiver_info_dict + elif i == max_retry-1: + pass + else: + time.sleep(0.5) + + if sfp_interface_bulk_raw is None: + return transceiver_info_dict + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + 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'] + transceiver_info_dict['type_abbrv_name'] = 'N/A' + 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. + ======================================================================== + """ + + if not self.get_presence(): + return None + + self._dom_capability_detect() + + if self.sfp_type == QSFP_TYPE: + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not sfpi_obj or not sfpd_obj: + return None + + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + offset = QSFP_DOM_OFFSET + offset_xcvr = QSFP_INFO_OFFSET + + # 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_specific_bytes( + (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_dom_capability_data = sfpi_obj.parse_dom_capability( + qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) + 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_specific_bytes( + (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) + 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'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH) + if qsfp_dom_rev_raw is not None: + qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + + # The tx_power monitoring is only available on QSFP which compliant with SFF-8636 + # and claimed that it support tx_power with one indicator bit. + dom_channel_monitor_data = {} + dom_channel_monitor_raw = None + qsfp_tx_power_support = qsfp_dom_capability_data['data']['Tx_power_support']['value'] + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + + else: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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) + 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'] + + if dom_channel_monitor_raw: + 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'] + elif self.sfp_type == SFP_TYPE: + sfpd_obj = sff8472Dom() + if not sfpd_obj: + return None + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET) + if eeprom_ifraw is not None: + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = SFP_DOM_OFFSET + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + + 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_specific_bytes( + (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH) + 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_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_voltage_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] + transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] + else: + return None + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num( + transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disable_channel'] = self.get_tx_disable_channel() + + 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. + ======================================================================== + """ + transceiver_dom_threshold_info_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + if self.sfp_type == QSFP_TYPE: + sfpd_obj = sff8436Dom() + if not self.get_presence() or not sfpd_obj: + return None + DOM_OFFSET = 0 + transceiver_dom_threshold_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + offset = DOM_OFFSET + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + module_threshold_values = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_channel_thres_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNEL_THRESHOLD_OFFSET), QSFP_CHANNEL_THRESHOLD_WIDTH) + if dom_channel_thres_raw is not None: + channel_threshold_values = sfpd_obj.parse_channel_threshold_values(dom_channel_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + else: + channel_threshold_data = None + if channel_threshold_data: + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + for key in transceiver_dom_threshold_dict: + transceiver_dom_threshold_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_dict[key]) + + return transceiver_dom_threshold_dict + + elif self.sfp_type == SFP_TYPE: + sfpd_obj = sff8472Dom() + + if not self.get_presence() and not sfpd_obj: + return None + DOM_OFFSET = 256 + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + if eeprom_ifraw is not None: + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_threshold_info_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['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']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + else: + return None + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + # Check for invalid port_num + if self.port_num < self.PORT_START or self.port_num > self.PORT_END or self.sfp_type == SFP_TYPE: + return False + + sfp_info = self.port_to_i2c_mapping[int(self._port_cfgs[self.port_num].lanes.split(',')[0])] + cmd = 'i2cget -y 0 {0} {1}'.format(sfp_info[4], sfp_info[5]) + reset_status = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + reset_status &= (1 << sfp_info[6]) + + return (reset_status == 1) + + 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. + """ + if not self.dom_supported: + return None + + rx_los_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + elif self.sfp_type == SFP_TYPE: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + else: + return None + + return rx_los_list + + 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. + """ + if not self.dom_supported: + return None + + tx_fault_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + elif self.sfp_type == SFP_TYPE: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + else: + return None + + return tx_fault_list + + 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 + """ + if not self.dom_supported: + return None + + tx_disable_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + elif self.sfp_type == SFP_TYPE: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0xC0 != 0) + else: + return None + else: + return None + + return tx_disable_list + + 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. + """ + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return 0 + elif self.sfp_type == QSFP_TYPE: + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + else: + return None + + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this QSFP module + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + 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 + """ + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_POWEROVERRIDE_OFFSET), QSFP_POWEROVERRIDE_WIDTH) + if dom_control_raw is not None: + if int(dom_control_raw[0],16) & (0x01 << QSFP_POWEROVERRIDE_BIT): + return True + else: + return False + else: + return None + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_temp_supported: + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) + 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 + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = 1 + + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + 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 + else: + return None + else: + 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 + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_volt_supported: + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + voltage = self._convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + sfpd_obj._calibration_type = self.calibration + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + voltage = self._convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + else: + 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'] + """ + tx_bias_list = [] + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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 == SFP_TYPE: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = self.calibration + + if self.dom_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + 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'])) + else: + return None + else: + return None + else: + return None + + 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'] + """ + rx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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) + 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: + return None + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + 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'])) + else: + return None + else: + return None + else: + return None + + 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'] + """ + tx_power_list = [] + + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + 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_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: + return None + else: + return None + elif self.sfp_type == SFP_TYPE: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + 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'])) + else: + return None + else: + return None + else: + return None + + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default state. + Returns: + A boolean, True if successful, False if not + """ + if not self.get_presence(): + return False + + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + sfp_info = self.port_to_i2c_mapping[int(self._port_cfgs[self.port_num].lanes.split(',')[0])] + cmd = 'i2cget -y 0 {0} {1}'.format(sfp_info[4], sfp_info[5]) + reset = int(Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True).stdout.readline(), 16) + + reset &= ~(1 << sfp_info[6]) + cmd = 'i2cset -y 0 {0} {1} {2}'.format(sfp_info[4], sfp_info[5], reset) + Popen(cmd, shell=True) + + reset |= (1 << sfp_info[6]) + cmd = 'i2cset -y 0 {0} {1} {2}'.format(sfp_info[4], sfp_info[5], reset) + Popen(cmd, shell=True) + + return True + + 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 + """ + if not self.get_presence(): + return False + + if self.sfp_type == SFP_TYPE: + if self.dom_tx_disable_supported: + offset = 256 + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + status_control_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_STATUS_CONTROL_OFFSET), SFP_STATUS_CONTROL_WIDTH) + if status_control_raw is not None: + # Set bit 6 for Soft TX Disable Select + # 01000000 = 64 and 10111111 = 191 + tx_disable_bit = 64 if tx_disable else 191 + status_control = int(status_control_raw[0], 16) + tx_disable_ctl = (status_control | tx_disable_bit) if tx_disable else ( + status_control & tx_disable_bit) + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="r+b", buffering=0) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom.seek(offset + SFP_STATUS_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + else: + return False + elif self.sfp_type == QSFP_TYPE: + if self.dom_tx_disable_supported: + channel_mask = 0x0f + if tx_disable: + return self.tx_disable_channel(channel_mask, True) + else: + return self.tx_disable_channel(channel_mask, False) + else: + return False + else: + return None + + 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 + """ + if not self.get_presence(): + return False + # SFP doesn't support this feature + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + if self.dom_tx_disable_supported: + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + if disable: + tx_disable_ctl = channel_state | channel + else: + tx_disable_ctl = channel_state & (~channel) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + else: + return False + else: + return None + + 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 + """ + 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 + """ + # SFP doesn't support this feature + if not self.get_presence(): + return False + + if self.sfp_type == SFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfsfile_eeprom = open(self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + else: + return None + + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return "Ethernet{}".format(self.port_num) + diff --git a/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/thermal.py b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/thermal.py new file mode 100644 index 000000000000..ca4e35969269 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/48y8c/sonic_platform/thermal.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1" + + def __init__(self, thermal_index): + self.index = thermal_index + self.high_threshold = float(112) + + # Add thermal name + self.THERMAL_NAME_LIST.append("ASIC") + + # Set hwmon path + self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH + self.ss_key = self.THERMAL_NAME_LIST[self.index - 1] + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + raise IOError("Unable to open %s file !" % file_path) + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return float("{:.3f}".format(temp)) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + 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 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + 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 + """ + return self.high_threshold + + 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 + """ + self.high_threshold = float(temperature) + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + if not self.get_presence(): + return False + + return True diff --git a/platform/centec/sonic-platform-modules-v682/debian/control b/platform/centec/sonic-platform-modules-v682/debian/control index 2c79ea7193ee..3460d4b00ba5 100644 --- a/platform/centec/sonic-platform-modules-v682/debian/control +++ b/platform/centec/sonic-platform-modules-v682/debian/control @@ -7,5 +7,15 @@ Standards-Version: 3.9.3 Package: platform-modules-v682-48y8c-d Architecture: amd64 -Depends: linux-image-4.19.0-12-2-amd64-unsigned +Depends: linux-image-5.10.0-8-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-v682-48y8c +Architecture: amd64 +Depends: linux-image-5.10.0-8-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-v682-48x8c +Architecture: amd64 +Depends: linux-image-5.10.0-8-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.init b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.init new file mode 100644 index 000000000000..16b23082d6f9 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.init @@ -0,0 +1,200 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-v682-48x8c +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + +function install_python_api_package() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} + +function load_system_eeprom_file() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + mkdir -p /mnt/onie-boot + mount -t ext4 -L ONIE-BOOT /mnt/onie-boot + dd if=/mnt/onie-boot/eeprom_file of=$device/$platform/eeprom_file bs=1 skip=1046528 + dd if=/mnt/onie-boot/eeprom_file of=$device/$platform/eeprom_cipher bs=1 count=32 + MACADDR=`decode-syseeprom | grep "Base MAC Address" | awk '{print $6}'` + ifconfig eth0 hw ether $MACADDR + umount /mnt/onie-boot + rmdir /mnt/onie-boot +} + +function load_kernel_modules() +{ + modprobe centec_v682_48x8c_platform + modprobe dal + modprobe knet + modprobe tun + modprobe tap +} + +function remove_kernel_modules() +{ + modprobe -r tap + modprobe -r tun + modprobe -r knet + modprobe -r dal + modprobe -r centec_v682_48x8c_platform +} + +function release_board() +{ + systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target + chmod a+x /usr/local/lib/python3.9/dist-packages/release.py + /usr/local/lib/python3.9/dist-packages/release.py +} + +function create_i2c_device_nodes() +{ + # load pca954x driver for pca9548 + modprobe i2c-mux-pca954x + modprobe optoe + + # i2c-0 for SMBus + # i2c-1 for CP2112 + # create i2c 2,3,4,5,6,7,8,9 for pca9548 0x70 channel 0,1,2,3,4,5,6,7 + echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device + # create i2c 13,12,11,10,17,16,15,14 for fiber 0,1,2,3,4,5,6,7 + echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-13/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-12/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-11/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-15/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-14/new_device + # create i2c 21,20,19,18,25,24,23,22 for fiber 8,9,10,11,12,13,14,15 + echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-3/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-21/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-20/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-19/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-18/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-25/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-24/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-23/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-22/new_device + # create i2c 29,28,27,26,33,32,31,30 for fiber 16,17,18,19,20,21,22,23 + echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-4/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-29/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-28/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-27/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-26/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-33/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-32/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-31/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-30/new_device + # create i2c 37,36,35,34,41,40,39,38 for fiber 24,25,26,27,28,29,30,31 + echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-6/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-37/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-36/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-35/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-34/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-41/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-40/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-39/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-38/new_device + # create i2c 45,44,43,42,49,48,47,46 for fiber 32,33,34,35,36,37,38,39 + echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-7/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-45/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-44/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-43/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-42/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-49/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-48/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-47/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-46/new_device + # create i2c 53,52,51,50,57,56,55,54 for fiber 40,41,42,43,44,45,46,47 + echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-8/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-53/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-52/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-51/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-50/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-57/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-56/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-55/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-54/new_device + # create i2c 61,60,59,58,65,64,63,62 for fiber 48,49,50,51,52,53,54,55 + echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-5/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-61/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-60/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-59/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-58/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-65/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-64/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-63/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-62/new_device + + # for rtc sd2405 + echo sd2405 0x32 > /sys/bus/i2c/devices/i2c-0/new_device + # load rtc-sd2405 driver for rtc sd2405 + modprobe rtc-sd2405 + sleep 1 + hwclock -s -f /dev/rtc1 > /dev/null 2>&1 + + # for sensor lm77 + echo lm77 0x49 > /sys/bus/i2c/devices/i2c-0/new_device + # load lm77 driver for sensor lm77 + modprobe lm77 + + # for fan adt7470 + echo adt7470 0x2c > /sys/bus/i2c/devices/i2c-9/new_device + echo adt7470 0x2e > /sys/bus/i2c/devices/i2c-9/new_device + # load adt7470 driver for fan adt7470 + modprobe adt7470 +} + +case "$1" in +start) + echo -n "Init Centec V682-48X8C ... " + + depmod -a + modprobe i2c-dev + + release_board + load_kernel_modules + create_i2c_device_nodes + install_python_api_package + load_system_eeprom_file + + echo "done." + ;; + +stop) + echo -n "Deinit Centec V682-48X8C ... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-v682-48x8c {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.install b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.install new file mode 100644 index 000000000000..c798deffaede --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.install @@ -0,0 +1,2 @@ +48x8c/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-centec_v682_48x8c-r0 +48x8c/service/release.py usr/local/lib/python3.9/dist-packages diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.postinst b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.postinst new file mode 100644 index 000000000000..a4f0261a1d3e --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48x8c.postinst @@ -0,0 +1,2 @@ +systemctl enable 48x8c_platform.service +systemctl start 48x8c_platform.service diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.init b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.init index 92ce88465d11..b74489e9a30d 100644 --- a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.init +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.init @@ -17,16 +17,26 @@ function install_python_api_package() device="/usr/share/sonic/device" platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) - rv=$(pip2 show sonic-platform > /dev/null 2>/dev/null) - if [ $? -ne 0 ]; then - rv=$(pip2 install $device/$platform/sonic_platform-1.0-py2-none-any.whl) - fi rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) if [ $? -ne 0 ]; then rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) fi } +function load_system_eeprom_file() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + mkdir -p /mnt/onie-boot + mount -t ext4 -L ONIE-BOOT /mnt/onie-boot + dd if=/mnt/onie-boot/eeprom_file of=$device/$platform/eeprom_file bs=1 skip=1046528 + dd if=/mnt/onie-boot/eeprom_file of=$device/$platform/eeprom_cipher bs=1 count=32 + MACADDR=`decode-syseeprom | grep "Base MAC Address" | awk '{print $6}'` + ifconfig eth0 hw ether $MACADDR + umount /mnt/onie-boot + rmdir /mnt/onie-boot +} + function load_kernel_modules() { depmod -a @@ -50,10 +60,10 @@ function release_board() { systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target - chmod a+x /usr/local/lib/python2.7/dist-packages/libSUSI-4.00.so.1 - chmod a+x /usr/local/lib/python2.7/dist-packages/_Susi4.so - chmod a+x /usr/local/lib/python2.7/dist-packages/release.py - /usr/local/lib/python2.7/dist-packages/release.py + chmod a+x /usr/local/lib/python3.9/dist-packages/libSUSI-4.00.so.1 + chmod a+x /usr/local/lib/python3.9/dist-packages/_Susi4.so + chmod a+x /usr/local/lib/python3.9/dist-packages/release.py + /usr/local/lib/python3.9/dist-packages/release.py } @@ -64,6 +74,7 @@ start) release_board load_kernel_modules install_python_api_package + load_system_eeprom_file echo "done." ;; diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.install b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.install index e3f3758b333e..8a5a1440cfe3 100644 --- a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.install +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c-d.install @@ -1,5 +1,4 @@ -48y8c-d/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-centec_v682_48y8c_d-r0 48y8c-d/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-centec_v682_48y8c_d-r0 -48y8c-d/service/release.py usr/local/lib/python2.7/dist-packages -48y8c-d/service/_Susi4.so usr/local/lib/python2.7/dist-packages -48y8c-d/service/libSUSI-4.00.so.1 usr/local/lib/python2.7/dist-packages +48y8c-d/service/release.py usr/local/lib/python3.9/dist-packages +48y8c-d/service/_Susi4.so usr/local/lib/python3.9/dist-packages +48y8c-d/service/libSUSI-4.00.so.1 usr/local/lib/python3.9/dist-packages diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.init b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.init new file mode 100644 index 000000000000..16a85d40e72b --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.init @@ -0,0 +1,200 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-v682-48y8c +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + +function install_python_api_package() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} + +function load_system_eeprom_file() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + mkdir -p /mnt/onie-boot + mount -t ext4 -L ONIE-BOOT /mnt/onie-boot + dd if=/mnt/onie-boot/eeprom_file of=$device/$platform/eeprom_file bs=1 skip=1046528 + dd if=/mnt/onie-boot/eeprom_file of=$device/$platform/eeprom_cipher bs=1 count=32 + MACADDR=`decode-syseeprom | grep "Base MAC Address" | awk '{print $6}'` + ifconfig eth0 hw ether $MACADDR + umount /mnt/onie-boot + rmdir /mnt/onie-boot +} + +function load_kernel_modules() +{ + modprobe centec_v682_48y8c_platform + modprobe dal + modprobe knet + modprobe tun + modprobe tap +} + +function remove_kernel_modules() +{ + modprobe -r tap + modprobe -r tun + modprobe -r knet + modprobe -r dal + modprobe -r centec_v682_48y8c_platform +} + +function release_board() +{ + systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target + chmod a+x /usr/local/lib/python3.9/dist-packages/release.py + /usr/local/lib/python3.9/dist-packages/release.py +} + +function create_i2c_device_nodes() +{ + # load pca954x driver for pca9548 + modprobe i2c-mux-pca954x + modprobe optoe + + # i2c-0 for SMBus + # i2c-1 for CP2112 + # create i2c 2,3,4,5,6,7,8,9 for pca9548 0x70 channel 0,1,2,3,4,5,6,7 + echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device + # create i2c 13,12,11,10,17,16,15,14 for fiber 0,1,2,3,4,5,6,7 + echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-13/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-12/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-11/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-15/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-14/new_device + # create i2c 21,20,19,18,25,24,23,22 for fiber 8,9,10,11,12,13,14,15 + echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-3/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-21/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-20/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-19/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-18/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-25/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-24/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-23/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-22/new_device + # create i2c 29,28,27,26,33,32,31,30 for fiber 16,17,18,19,20,21,22,23 + echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-4/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-29/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-28/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-27/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-26/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-33/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-32/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-31/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-30/new_device + # create i2c 37,36,35,34,41,40,39,38 for fiber 24,25,26,27,28,29,30,31 + echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-6/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-37/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-36/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-35/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-34/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-41/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-40/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-39/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-38/new_device + # create i2c 45,44,43,42,49,48,47,46 for fiber 32,33,34,35,36,37,38,39 + echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-7/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-45/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-44/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-43/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-42/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-49/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-48/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-47/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-46/new_device + # create i2c 53,52,51,50,57,56,55,54 for fiber 40,41,42,43,44,45,46,47 + echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-8/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-53/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-52/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-51/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-50/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-57/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-56/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-55/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-54/new_device + # create i2c 61,60,59,58,65,64,63,62 for fiber 48,49,50,51,52,53,54,55 + echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-5/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-61/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-60/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-59/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-58/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-65/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-64/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-63/new_device + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-62/new_device + + # for rtc sd2405 + echo sd2405 0x32 > /sys/bus/i2c/devices/i2c-0/new_device + # load rtc-sd2405 driver for rtc sd2405 + modprobe rtc-sd2405 + sleep 1 + hwclock -s -f /dev/rtc1 > /dev/null 2>&1 + + # for sensor lm77 + echo lm77 0x49 > /sys/bus/i2c/devices/i2c-0/new_device + # load lm77 driver for sensor lm77 + modprobe lm77 + + # for fan adt7470 + echo adt7470 0x2c > /sys/bus/i2c/devices/i2c-9/new_device + echo adt7470 0x2e > /sys/bus/i2c/devices/i2c-9/new_device + # load adt7470 driver for fan adt7470 + modprobe adt7470 +} + +case "$1" in +start) + echo -n "Init Centec V682-48Y8C ... " + + depmod -a + modprobe i2c-dev + + release_board + load_kernel_modules + create_i2c_device_nodes + install_python_api_package + load_system_eeprom_file + + echo "done." + ;; + +stop) + echo -n "Deinit Centec V682-48Y8C ... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-v682-48y8c {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.install b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.install new file mode 100644 index 000000000000..999baedb4b20 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.install @@ -0,0 +1,2 @@ +48y8c/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-centec_v682_48y8c-r0 +48y8c/service/release.py usr/local/lib/python3.9/dist-packages diff --git a/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.postinst b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.postinst new file mode 100644 index 000000000000..30915b9e6fe0 --- /dev/null +++ b/platform/centec/sonic-platform-modules-v682/debian/platform-modules-v682-48y8c.postinst @@ -0,0 +1,2 @@ +systemctl enable 48y8c_platform.service +systemctl start 48y8c_platform.service diff --git a/platform/centec/sonic-platform-modules-v682/debian/rules b/platform/centec/sonic-platform-modules-v682/debian/rules index c50356d4517d..2e0e0dc0ffee 100755 --- a/platform/centec/sonic-platform-modules-v682/debian/rules +++ b/platform/centec/sonic-platform-modules-v682/debian/rules @@ -17,7 +17,7 @@ PACKAGE_PRE_NAME := platform-modules-v682 KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= 48y8c-d +MODULE_DIRS:= 48y8c-d 48y8c 48x8c MODULE_DIR := modules SERVICE_DIR := service CLASSES_DIR := classes @@ -41,7 +41,6 @@ build: (for mod in $(MODULE_DIRS); do \ make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ cd $${mod}; \ - python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ cd -; \ done)