From ab433232eaba5b4e5760ebf8ccc1f86f74811317 Mon Sep 17 00:00:00 2001 From: panyi Date: Fri, 6 Jan 2023 19:29:37 +0800 Subject: [PATCH 01/13] b6010 update --- .../RA-b6010-48gt4x-board.json | 868 ++ .../RA-b6010-48gt4x-p-chip-profile.txt | 96 + .../RA-b6010-48gt4x-p-datapath.txt | 281 + .../RA-B6010-48GT4X/default_sku | 1 + .../RA-B6010-48GT4X/phy_mapping.cfg | 198 + .../RA-B6010-48GT4X/port_config.ini | 53 + .../RA-B6010-48GT4X/sai.profile | 4 + .../RA-B6010-48GT4X/start_up.cfg | 48 + .../RA-b6010-48gt4x-board.json | 868 ++ .../RA-b6010-48gt4x-p-chip-profile.txt | 96 + .../RA-b6010-48gt4x-p-datapath.txt | 281 + .../RA-B6010-48GT4X/default_sku | 1 + .../RA-B6010-48GT4X/phy_mapping.cfg | 198 + .../RA-B6010-48GT4X/port_config.ini | 53 + .../RA-B6010-48GT4X/sai.profile | 4 + .../RA-B6010-48GT4X/start_up.cfg | 48 + .../default_sku | 1 + .../installer.conf | 9 + .../plugins/config.py | 22 + .../plugins/eeprom.py | 21 + .../plugins/sfputil.py | 455 ++ .../pmon_daemon_control.json | 7 + .../default_sku | 1 + .../installer.conf | 9 + .../plugins/config.py | 22 + .../plugins/eeprom.py | 21 + .../plugins/sfputil.py | 455 ++ .../pmon_daemon_control.json | 7 + platform/centec-arm64/one-image.mk | 2 + .../centec-arm64/platform-modules-ragile.dep | 10 + .../centec-arm64/platform-modules-ragile.mk | 16 + platform/centec-arm64/rules.mk | 1 + platform/centec-arm64/sai.mk | 7 +- .../sonic-platform-modules-ragile/LICENSE | 15 + .../sonic-platform-modules-ragile/README.md | 1 + .../common/Makefile | 47 + .../common/app/Makefile | 26 + .../common/app/dev_util/Makefile | 36 + .../common/app/dev_util/dfd_debug.c | 46 + .../common/app/dev_util/dfd_utest.c | 1219 +++ .../common/app/dev_util/dfd_utest.h | 104 + .../common/app/firmware_upgrade/Makefile | 24 + .../common/app/firmware_upgrade/Rules.mk | 54 + .../firmware-cpld-ispvme.spec | 27 + .../firmware_driver_ispvme/Makefile | 27 + .../firmware_driver_ispvme/b6510-48vs8cq.c | 497 ++ .../firmware_driver_ispvme/b6510-48vs8cq.h | 29 + .../firmware_cpld_ispvme.c | 285 + .../firmware_cpld_upgrade_ispvme.c | 336 + .../firmware_driver_ispvme/firmware_ispvme.c | 144 + .../include/config_ispvme.h | 11 + .../include/firmware_cpld_ispvme.h | 52 + .../include/firmware_ispvme.h | 88 + .../firmware_upgrade_ispvme/Makefile | 39 + .../firmware_upgrade_ispvme/common.h | 29 + .../firmware_upgrade_ispvme/debug_ispvme.c | 72 + .../firmware_upgrade_ispvme/dfd_fpga_debug.c | 124 + .../firmware_upgrade_ispvme/dfd_fpga_debug.h | 70 + .../firmware_upgrade_ispvme/dfd_fpga_pkt.c | 327 + .../firmware_upgrade_ispvme/dfd_fpga_pkt.h | 98 + .../firmware_upgrade_ispvme/dfd_fpga_upg.c | 1454 ++++ .../firmware_app_ispvme.c | 1870 +++++ .../firmware_upgrade_ispvme/hardware.c | 253 + .../include/debug_ispvme.h | 21 + .../include/firmware_app_ispvme.h | 142 + .../firmware_upgrade_ispvme/ispvm_ui.c | 851 ++ .../firmware_upgrade_ispvme/ivm_core.c | 3035 +++++++ .../firmware_upgrade_ispvme/vmopcode.h | 192 + .../common/app/hw_test/Makefile | 36 + .../common/app/hw_test/ft_ddr_test.c | 2111 +++++ .../common/app/hw_test/hw_dram.c | 800 ++ .../common/app/hw_test/hw_emmc.c | 130 + .../common/app/hw_test/hw_i2c.c | 726 ++ .../common/app/hw_test/hw_misc.c | 720 ++ .../common/app/hw_test/hw_mtdflash.c | 731 ++ .../common/app/hw_test/hw_pci.c | 496 ++ .../common/app/hw_test/hw_test.c | 179 + .../common/app/hw_test/hw_usb.c | 44 + .../app/hw_test/include/hw_dram/fac_common.h | 44 + .../app/hw_test/include/hw_dram/ft_ddr_test.h | 119 + .../app/hw_test/include/hw_dram/hw_dram.h | 22 + .../app/hw_test/include/hw_emmc/hw_emmc.h | 18 + .../app/hw_test/include/hw_i2c/hw_i2c.h | 40 + .../app/hw_test/include/hw_i2c/i2c-dev.h | 71 + .../common/app/hw_test/include/hw_i2c/i2c.h | 742 ++ .../common/app/hw_test/include/hw_i2c/rtc.h | 100 + .../app/hw_test/include/hw_misc/dram_driver.h | 32 + .../app/hw_test/include/hw_misc/hw_misc.h | 37 + .../app/hw_test/include/hw_mtd/hw_mtdflash.h | 38 + .../app/hw_test/include/hw_mtd/mtd-abi.h | 199 + .../app/hw_test/include/hw_pci/hw_pci.h | 38 + .../common/app/hw_test/include/hw_test.h | 27 + .../app/hw_test/include/hw_usb/hw_usb.h | 21 + .../common/app/libextphy.so | Bin 0 -> 632408 bytes .../common/lib/algorithm/__init__.py | 1 + .../common/lib/algorithm/openloop.py | 109 + .../common/lib/algorithm/pid.py | 110 + .../common/lib/eepromutil/__init__.py | 0 .../common/lib/eepromutil/fantlv.py | 223 + .../common/lib/eepromutil/fru.py | 955 +++ .../common/lib/eepromutil/onietlv.py | 451 ++ .../common/lib/plat_hal/__init__.py | 1 + .../common/lib/plat_hal/baseutil.py | 84 + .../common/lib/plat_hal/card.py | 27 + .../common/lib/plat_hal/chassisbase.py | 260 + .../common/lib/plat_hal/dcdc.py | 37 + .../common/lib/plat_hal/devicebase.py | 175 + .../common/lib/plat_hal/fan.py | 317 + .../common/lib/plat_hal/interface.py | 1021 +++ .../common/lib/plat_hal/led.py | 59 + .../common/lib/plat_hal/osutil.py | 261 + .../common/lib/plat_hal/psu.py | 428 + .../common/lib/plat_hal/rotor.py | 137 + .../common/lib/plat_hal/sensor.py | 142 + .../common/lib/plat_hal/temp.py | 77 + .../common/lib/rjutil/__init__.py | 0 .../common/lib/rjutil/baseutil.py | 22 + .../common/lib/rjutil/smbus.py | 774 ++ .../common/modules/Makefile | 33 + .../common/modules/dfd_tlveeprom.c | 522 ++ .../common/modules/dfd_tlveeprom.h | 122 + .../common/modules/i2c-mux-pca954x.c | 3825 +++++++++ .../common/modules/i2c-mux-pca9641.c | 648 ++ .../common/modules/optoe.c | 1198 +++ .../common/modules/ragile.h | 155 + .../common/modules/ragile_common_module.c | 216 + .../common/modules/ragile_platform.c | 79 + .../common/modules/rg_spi_gpio.c | 94 + .../common/modules/rtc-pcf85063.c | 262 + .../common/modules/spi-bitbang-txrx.h | 107 + .../common/modules/spi-gpio.c | 547 ++ .../common/modules/test.c | 68 + .../common/modules/tpm.h | 543 ++ .../common/modules/tpm_tis_core.c | 855 ++ .../common/modules/tpm_tis_core.h | 156 + .../common/modules/tpm_tis_spi.c | 261 + .../common/script/avscontrol.py | 105 + .../common/script/cmdx.py | 51 + .../common/script/dev_monitor.py | 293 + .../common/script/device_i2c.py | 359 + .../common/script/env_check.sh | 82 + .../common/script/face2set | 1396 ++++ .../common/script/facfwupdate | 1188 +++ .../common/script/factest | 7128 +++++++++++++++++ .../common/script/fancontrol.py | 450 ++ .../common/script/grtd_test.py | 1686 ++++ .../common/script/hal_fanctrl.py | 414 + .../common/script/hal_ledctrl.py | 310 + .../common/script/hal_pltfm.py | 380 + .../common/script/interface.py | 76 + .../common/script/platform_manufacturer | 395 + .../common/script/platform_sensors.py | 201 + .../common/script/pmon_sys | 134 + .../common/script/port.py | 3790 +++++++++ .../common/script/portutil.py | 363 + .../common/script/ragilecommon.py | 692 ++ .../common/script/ragileconfig.py | 178 + .../common/script/ragileutil.py | 2011 +++++ .../common/script/slot_monitor.py | 225 + .../common/service/device_i2c.service | 15 + .../common/service/fancontrol.service | 12 + .../common_custom/common_ragile/Makefile | 24 + .../common_ragile/lib/fruutil/__init__.py | 0 .../common_ragile/lib/fruutil/fru.py | 1294 +++ .../common_ragile/lib/fruutil/product.conf | 67 + .../common_ragile/lib/logutil/__init__.py | 0 .../common_ragile/lib/logutil/logutil.py | 64 + .../lib/redfishutil/redfish_api.py | 308 + .../common_ragile/lib/rest/__init__.py | 0 .../common_ragile/lib/rest/rest.py | 1213 +++ .../common_ragile/lib/rjutil/__init__.py | 0 .../common_ragile/lib/rjutil/ragileutil.py | 299 + .../common_ragile/lib/sonic_fwmgr/__init__.py | 0 .../lib/sonic_fwmgr/fwgmr_base.py | 141 + .../common_custom/common_ragile/script/ctccmd | 3 + .../common_ragile/script/privatenetwork.py | 50 + .../common_ragile/script/privatenetwork.sh | 26 + .../common_ragile/script/sfpTempToBmc.py | 167 + .../script/update_machine_config.sh | 24 + .../service/privatenetwork.service | 13 + ...rm64_ragile_ra_b6010_48gt4x_r_r0_config.py | 93 + .../config/fan_ctrl_cfg.json | 25 + .../ra-b6010-48gt4x-r/modules/Makefile | 1 + .../ra-b6010-48gt4x-r/modules/rg_cpld.c | 346 + .../ra-b6010-48gt4x-r_platform.service | 13 + .../ra-b6010-48gt4x-r/setup.py | 16 + .../sonic_platform/__init__.py | 3 + .../sonic_platform/chassis.py | 182 + .../sonic_platform/component.py | 93 + .../sonic_platform/eeprom.py | 119 + .../ra-b6010-48gt4x-r/sonic_platform/fan.py | 131 + .../sonic_platform/fan_drawer.py | 64 + .../sonic_platform/hwaccess.py | 47 + .../sonic_platform/platform.py | 15 + .../ra-b6010-48gt4x-r/sonic_platform/psu.py | 129 + .../sonic_platform/redfish_api.py | 308 + .../ra-b6010-48gt4x-r/sonic_platform/sfp.py | 103 + .../sonic_platform/thermal.py | 88 + .../arm64_ragile_ra_b6010_48gt4x_r0_config.py | 93 + .../ra-b6010-48gt4x/config/fan_ctrl_cfg.json | 37 + .../ra-b6010-48gt4x/modules/Makefile | 1 + .../ra-b6010-48gt4x/modules/rg_cpld.c | 346 + .../service/ra-b6010-48gt4x_platform.service | 13 + .../ra-b6010-48gt4x/setup.py | 16 + .../sonic_platform/__init__.py | 3 + .../ra-b6010-48gt4x/sonic_platform/chassis.py | 181 + .../sonic_platform/component.py | 93 + .../ra-b6010-48gt4x/sonic_platform/eeprom.py | 119 + .../ra-b6010-48gt4x/sonic_platform/fan.py | 135 + .../sonic_platform/fan_drawer.py | 64 + .../sonic_platform/hwaccess.py | 47 + .../sonic_platform/platform.py | 15 + .../ra-b6010-48gt4x/sonic_platform/psu.py | 129 + .../sonic_platform/redfish_api.py | 308 + .../ra-b6010-48gt4x/sonic_platform/sfp.py | 107 + .../ra-b6010-48gt4x/sonic_platform/thermal.py | 88 + platform/centec-arm64/sonic_fit.its | 25 + 217 files changed, 67911 insertions(+), 4 deletions(-) create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/default_sku create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json create mode 100644 platform/centec-arm64/platform-modules-ragile.dep create mode 100755 platform/centec-arm64/platform-modules-ragile.mk create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/LICENSE create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/README.md create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_debug.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Rules.mk create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware-cpld-ispvme.spec create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_ispvme.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_upgrade_ispvme.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_ispvme.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/config_ispvme.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_cpld_ispvme.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_ispvme.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/common.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/debug_ispvme.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_upg.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/firmware_app_ispvme.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/hardware.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/debug_ispvme.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/firmware_app_ispvme.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ispvm_ui.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ivm_core.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/vmopcode.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/ft_ddr_test.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_dram.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_emmc.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_i2c.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_misc.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_mtdflash.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_pci.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_test.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_usb.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/fac_common.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/ft_ddr_test.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/hw_dram.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_emmc/hw_emmc.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/hw_i2c.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c-dev.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/rtc.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/dram_driver.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/hw_misc.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/hw_mtdflash.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/mtd-abi.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_pci/hw_pci.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_test.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_usb/hw_usb.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/app/libextphy.so create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/openloop.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/pid.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fantlv.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fru.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/onietlv.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/baseutil.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/card.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/chassisbase.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/dcdc.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/devicebase.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/fan.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/interface.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/led.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/osutil.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/psu.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/rotor.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/sensor.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/temp.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/baseutil.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/smbus.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca954x.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca9641.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/optoe.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_common_module.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_platform.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rg_spi_gpio.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rtc-pcf85063.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-bitbang-txrx.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-gpio.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/test.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.h create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_spi.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/avscontrol.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/cmdx.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/dev_monitor.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/device_i2c.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/env_check.sh create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/face2set create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/facfwupdate create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/factest create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/common/script/fancontrol.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/grtd_test.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_fanctrl.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_ledctrl.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_pltfm.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/interface.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_manufacturer create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_sensors.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/pmon_sys create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/port.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/portutil.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragilecommon.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileconfig.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileutil.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/script/slot_monitor.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/service/device_i2c.service create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common/service/fancontrol.service create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/fru.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/product.conf create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/logutil/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/logutil/logutil.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/redfishutil/redfish_api.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rest/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rest/rest.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rjutil/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rjutil/ragileutil.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/sonic_fwmgr/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/sonic_fwmgr/fwgmr_base.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/ctccmd create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.sh create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/sfpTempToBmc.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/update_machine_config.sh create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/service/privatenetwork.service create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/arm64_ragile_ra_b6010_48gt4x_r_r0_config.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/fan_ctrl_cfg.json create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/Makefile create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/rg_cpld.c create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/service/ra-b6010-48gt4x-r_platform.service create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/setup.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/__init__.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/chassis.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/component.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/eeprom.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan_drawer.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/hwaccess.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/platform.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/psu.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/redfish_api.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/sfp.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/thermal.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/arm64_ragile_ra_b6010_48gt4x_r0_config.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/fan_ctrl_cfg.json create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/rg_cpld.c create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/service/ra-b6010-48gt4x_platform.service create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/setup.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/chassis.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/component.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/eeprom.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan_drawer.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/hwaccess.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/platform.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/psu.py create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/redfish_api.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/sfp.py create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/thermal.py diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json new file mode 100644 index 000000000000..80fb22238078 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json @@ -0,0 +1,868 @@ +{ + "macleds" : { + "polarity" : 1, + "freq" : 2500, + "interval" : 50000000, + "maps" : [ + { + "port_id" : 0, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port1/brightness" + }, + { + "port_id" : 1, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port2/brightness" + }, + { + "port_id" : 2, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port3/brightness" + }, + { + "port_id" : 3, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port4/brightness" + }, + { + "port_id" : 4, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port5/brightness" + }, + { + "port_id" : 5, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port6/brightness" + }, + { + "port_id" : 6, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port7/brightness" + }, + { + "port_id" : 7, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port8/brightness" + }, + { + "port_id" : 16, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port9/brightness" + }, + { + "port_id" : 17, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port10/brightness" + }, + { + "port_id" : 18, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port11/brightness" + }, + { + "port_id" : 19, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port12/brightness" + }, + { + "port_id" : 20, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port13/brightness" + }, + { + "port_id" : 21, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port14/brightness" + }, + { + "port_id" : 22, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port15/brightness" + }, + { + "port_id" : 23, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port16/brightness" + }, + { + "port_id" : 8, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port17/brightness" + }, + { + "port_id" : 9, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port18/brightness" + }, + { + "port_id" : 10, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port19/brightness" + }, + { + "port_id" : 11, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port20/brightness" + }, + { + "port_id" : 32, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port21/brightness" + }, + { + "port_id" : 33, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port22/brightness" + }, + { + "port_id" : 34, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port23/brightness" + }, + { + "port_id" : 35, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port24/brightness" + }, + { + "port_id" : 36, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port25/brightness" + }, + { + "port_id" : 37, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port26/brightness" + }, + { + "port_id" : 38, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port27/brightness" + }, + { + "port_id" : 39, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port28/brightness" + }, + { + "port_id" : 40, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port29/brightness" + }, + { + "port_id" : 41, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port30/brightness" + }, + { + "port_id" : 42, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port31/brightness" + }, + { + "port_id" : 43, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port32/brightness" + }, + { + "port_id" : 24, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port33/brightness" + }, + { + "port_id" : 25, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port34/brightness" + }, + { + "port_id" : 26, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port35/brightness" + }, + { + "port_id" : 27, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port36/brightness" + }, + { + "port_id" : 48, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port37/brightness" + }, + { + "port_id" : 49, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port38/brightness" + }, + { + "port_id" : 50, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port39/brightness" + }, + { + "port_id" : 51, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port40/brightness" + }, + { + "port_id" : 52, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port41/brightness" + }, + { + "port_id" : 53, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port42/brightness" + }, + { + "port_id" : 54, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port43/brightness" + }, + { + "port_id" : 55, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port44/brightness" + }, + { + "port_id" : 56, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port45/brightness" + }, + { + "port_id" : 57, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port46/brightness" + }, + { + "port_id" : 58, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port47/brightness" + }, + { + "port_id" : 59, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port48/brightness" + }, + { + "port_id" : 12, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port49/brightness" + }, + { + "port_id" : 13, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port50/brightness" + }, + { + "port_id" : 14, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port51/brightness" + }, + { + "port_id" : 15, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port52/brightness" + } + ] + }, + "phys" : [ + { + "macid" : 0, + "busid" : 0, + "addr" : 0, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 1, + "busid" : 0, + "addr" : 1, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 2, + "busid" : 0, + "addr" : 2, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 3, + "busid" : 0, + "addr" : 3, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 4, + "busid" : 0, + "addr" : 4, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 5, + "busid" : 0, + "addr" : 5, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 6, + "busid" : 0, + "addr" : 6, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 7, + "busid" : 0, + "addr" : 7, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 16, + "busid" : 0, + "addr" : 8, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 17, + "busid" : 0, + "addr" : 9, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 18, + "busid" : 0, + "addr" : 10, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 19, + "busid" : 0, + "addr" : 11, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 20, + "busid" : 0, + "addr" : 12, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 21, + "busid" : 0, + "addr" : 13, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 22, + "busid" : 0, + "addr" : 14, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 23, + "busid" : 0, + "addr" : 15, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 8, + "busid" : 0, + "addr" : 16, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 9, + "busid" : 0, + "addr" : 17, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 10, + "busid" : 0, + "addr" : 18, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 11, + "busid" : 0, + "addr" : 19, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 32, + "busid" : 0, + "addr" : 20, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 33, + "busid" : 0, + "addr" : 21, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 34, + "busid" : 0, + "addr" : 22, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 35, + "busid" : 0, + "addr" : 23, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 36, + "busid" : 1, + "addr" : 0, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 37, + "busid" : 1, + "addr" : 1, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 38, + "busid" : 1, + "addr" : 2, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 39, + "busid" : 1, + "addr" : 3, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 40, + "busid" : 1, + "addr" : 4, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 41, + "busid" : 1, + "addr" : 5, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 42, + "busid" : 1, + "addr" : 6, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 43, + "busid" : 1, + "addr" : 7, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 24, + "busid" : 1, + "addr" : 8, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 25, + "busid" : 1, + "addr" : 9, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 26, + "busid" : 1, + "addr" : 10, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 27, + "busid" : 1, + "addr" : 11, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 48, + "busid" : 1, + "addr" : 12, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 49, + "busid" : 1, + "addr" : 13, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 50, + "busid" : 1, + "addr" : 14, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 51, + "busid" : 1, + "addr" : 15, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 52, + "busid" : 1, + "addr" : 16, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 53, + "busid" : 1, + "addr" : 17, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 54, + "busid" : 1, + "addr" : 18, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 55, + "busid" : 1, + "addr" : 19, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 56, + "busid" : 1, + "addr" : 20, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 57, + "busid" : 1, + "addr" : 21, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 58, + "busid" : 1, + "addr" : 22, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 59, + "busid" : 1, + "addr" : 23, + "base_port": 1, + "last_port": 4 + } + ], + "ffe" : { + "board_material" : "BOARD_MATERIAL_M4", + "config" : [ + { + "serdes_id" : [0], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 255, 10, 0] + }, + { + "serdes_id" : [1], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 240, 10, 0] + }, + { + "serdes_id" : [2], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 230, 10, 0] + }, + { + "serdes_id" : [3], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 220, 7, 0] + }, + { + "serdes_id" : [4], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 220, 8, 0] + }, + { + "serdes_id" : [5], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 210, 6, 0] + }, + { + "serdes_id" : [6], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 180, 6, 0] + }, + { + "serdes_id" : [7], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 180, 5, 0] + }, + { + "serdes_id" : [8], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, 160, 4, 0] + }, + { + "serdes_id" : [9], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, 160, 4, 0] + }, + { + "serdes_id" : [10], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [3, 140, 9, 0] + }, + { + "serdes_id" : [11], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [3, 140, 5, 0] + }, + { + "serdes_id" : [12, 13, 14, 15], + "is_dac" : 0, + "speed" : [10000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [3, 94, 15, 0] + } + ] + }, + "ctle" : { + "config" : [ + { + "serdes_id" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], + "auto-en" : 0, + "cfg" : [6, 14, 2] + } + ] + } +} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt new file mode 100644 index 000000000000..2373e27f5f8b --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt @@ -0,0 +1,96 @@ +#----------------- 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] = 1; +[NPM_SUPPORT] = 1; +[DOT1AE_SUPPORT] = 1; + +#----------------- Chip Init Parameter -------------- +#Local chip number and global chip id +[Local chip_num] = 1 +[Local chip0] = 0 +[Local chip1] = 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 + +#----------------- Interrupt Init Parameter -------------- +#0: pin, 1: msi +[Interrupt_mode] = 0 +[IRQ] = 69 + +#----------------- 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 + +#----------------- L2 Init Parameter -------------- +[FDB Hw Learning] = 1 +[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_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 port queue number support 16/8/8 BPE/4 BPE, +#When resrc_profile.cfg exist, queue number valid, +#Default 8 queue mode +#8 queue = 8 +#16 queue = 16 +#4 queue BPE = 17 +#8 queue BPE = 18 +[QOS_PORT_QUEUE_NUM] = 8 +#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_POLICER_MERGE_MODE] = 0 +#QOS service queue mode, default 0,0:logic scr port + dstport enq 1:service id + dstport enq +[QOS_SERVICE_QUEUE_MODE] = 0 +#Global enable logic dst port + dstport enq +[QOS_SERVICE_QUEUE_EGRESS_EN] = 0 + +#----------------- Stacking Init Parameter -------------- +#0: normal mode; 1: spine-leaf mode +[FABRIC MODE] = 0 +[STACKING VERSION] = 1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt new file mode 100644 index 000000000000..959b97a150cc --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt @@ -0,0 +1,281 @@ +#Generated by 'CTC DataPath Tools' on Fri Dec 18 19:15:31 2020 +#Version 1.0, Supported by TsingMa SDK + + +#SERDES_MODE : 0-NONE, 1-XFI, 2-SGMII, 3-Not Support, 4-QSGMII, 5-XAUI, 6-DXAUI, 7-XLG, 8-CG, 9-SGMII2G5 +# 10-USXGMII-S, 11-USXGMII-M2G5, 12-USXGMII-M5G, 13-XXVG, 14-LG, 15-100BASE-FX +#SERDES_RX_POLY: 0-Normal, 1-Inverse +#SERDES_SWITCH : 0-Not Support Dynamic Switch, 1-Support Dynamic Switch + +[WLAN_ENABLE] = 1 +[DOT1AE_ENABLE] = 1 + +[CORE_PLLA] = 600 +#{ +[SERDES_ITEM] +#repeat 32 step 6 +[SERDES_ID] = 0 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 1 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 2 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 3 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 4 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 5 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 6 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 7 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 8 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 9 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 10 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 11 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 12 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 13 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 14 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 15 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 16 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 17 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 18 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 19 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 20 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 21 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 22 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 23 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 24 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 25 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 26 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +[SERDES_ID] = 27 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +[SERDES_ID] = 28 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 29 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 30 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +[SERDES_ID] = 31 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +#repeat end +#} + + +#[SERDES_TO_LPORT] +#{ +# | QSGMII/USXGMII-M2G5 | USXGMII-M5G | USXGMII-S | 100BASE-FX | SGMII/SGMII2G5/XFI | XAUI/DXAUI | XLG | XXVG | LG | CG +#---------|---------------------|-------------|-----------|------------|--------------------|------------|-----|------|----|--- +#serdes 0 |0 /1 /2 /3 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 1 |4 /5 /6 /7 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 2 |16/17/18/19 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 3 |20/21/22/23 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 4 |8 /9 /10/11 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 5 |32/33/34/35 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 6 |36/37/38/39 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 7 |40/41/42/43 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 8 |24/25/26/27 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 9 |48/49/50/51 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 10|52/53/54/55 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 11|56/57/58/59 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 12|NA |NA |NA |12 |12 |12 |12 |NA |NA |NA +#serdes 13|NA |NA |NA |13 |13 |12 |12 |NA |NA |NA +#serdes 14|NA |NA |NA |14 |14 |12 |12 |NA |NA |NA +#serdes 15|NA |NA |NA |15 |15 |12 |12 |NA |NA |NA +#serdes 16|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 17|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 18|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 19|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 20|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 21|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 22|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 23|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 24|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 25|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 26|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 27|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 28|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 29|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 30|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 31|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku new file mode 100644 index 000000000000..2a8d51c1f241 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku @@ -0,0 +1 @@ +RA-B6010-48GT4X l1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg new file mode 100644 index 000000000000..eefd67e9c28b --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg @@ -0,0 +1,198 @@ +#######################PHY_MAPPING_48+4####################### + +#{ +[PHY_MAPPING_ITEM] + +[API_PORT] = 0 +[PHY_ADDR] = 0 +[MDIO_BUS] = 0 + +[API_PORT] = 1 +[PHY_ADDR] = 1 +[MDIO_BUS] = 0 + +[API_PORT] = 2 +[PHY_ADDR] = 2 +[MDIO_BUS] = 0 + +[API_PORT] = 3 +[PHY_ADDR] = 3 +[MDIO_BUS] = 0 + +[API_PORT] = 4 +[PHY_ADDR] = 4 +[MDIO_BUS] = 0 + +[API_PORT] = 5 +[PHY_ADDR] = 5 +[MDIO_BUS] = 0 + +[API_PORT] = 6 +[PHY_ADDR] = 6 +[MDIO_BUS] = 0 + +[API_PORT] = 7 +[PHY_ADDR] = 7 +[MDIO_BUS] = 0 + +[API_PORT] = 16 +[PHY_ADDR] = 8 +[MDIO_BUS] = 0 + +[API_PORT] = 17 +[PHY_ADDR] = 9 +[MDIO_BUS] = 0 + +[API_PORT] = 18 +[PHY_ADDR] = 10 +[MDIO_BUS] = 0 + +[API_PORT] = 19 +[PHY_ADDR] = 11 +[MDIO_BUS] = 0 + +[API_PORT] = 20 +[PHY_ADDR] = 12 +[MDIO_BUS] = 0 + +[API_PORT] = 21 +[PHY_ADDR] = 13 +[MDIO_BUS] = 0 + +[API_PORT] = 22 +[PHY_ADDR] = 14 +[MDIO_BUS] = 0 + +[API_PORT] = 23 +[PHY_ADDR] = 15 +[MDIO_BUS] = 0 + +[API_PORT] = 8 +[PHY_ADDR] = 16 +[MDIO_BUS] = 0 + +[API_PORT] = 9 +[PHY_ADDR] = 17 +[MDIO_BUS] = 0 + +[API_PORT] = 10 +[PHY_ADDR] = 18 +[MDIO_BUS] = 0 + +[API_PORT] = 11 +[PHY_ADDR] = 19 +[MDIO_BUS] = 0 + +[API_PORT] = 32 +[PHY_ADDR] = 20 +[MDIO_BUS] = 0 + +[API_PORT] = 33 +[PHY_ADDR] = 21 +[MDIO_BUS] = 0 + +[API_PORT] = 34 +[PHY_ADDR] = 22 +[MDIO_BUS] = 0 + +[API_PORT] = 35 +[PHY_ADDR] = 23 +[MDIO_BUS] = 0 + +[API_PORT] = 36 +[PHY_ADDR] = 0 +[MDIO_BUS] = 1 + +[API_PORT] = 37 +[PHY_ADDR] = 1 +[MDIO_BUS] = 1 + +[API_PORT] = 38 +[PHY_ADDR] = 2 +[MDIO_BUS] = 1 + +[API_PORT] = 39 +[PHY_ADDR] = 3 +[MDIO_BUS] = 1 + +[API_PORT] = 40 +[PHY_ADDR] = 4 +[MDIO_BUS] = 1 + +[API_PORT] = 41 +[PHY_ADDR] = 5 +[MDIO_BUS] = 1 + +[API_PORT] = 42 +[PHY_ADDR] = 6 +[MDIO_BUS] = 1 + +[API_PORT] = 43 +[PHY_ADDR] = 7 +[MDIO_BUS] = 1 + +[API_PORT] = 24 +[PHY_ADDR] = 8 +[MDIO_BUS] = 1 + +[API_PORT] = 25 +[PHY_ADDR] = 9 +[MDIO_BUS] = 1 + +[API_PORT] = 26 +[PHY_ADDR] = 10 +[MDIO_BUS] = 1 + +[API_PORT] = 27 +[PHY_ADDR] = 11 +[MDIO_BUS] = 1 + +[API_PORT] = 48 +[PHY_ADDR] = 12 +[MDIO_BUS] = 1 + +[API_PORT] = 49 +[PHY_ADDR] = 13 +[MDIO_BUS] = 1 + +[API_PORT] = 50 +[PHY_ADDR] = 14 +[MDIO_BUS] = 1 + +[API_PORT] = 51 +[PHY_ADDR] = 15 +[MDIO_BUS] = 1 + +[API_PORT] = 52 +[PHY_ADDR] = 16 +[MDIO_BUS] = 1 + +[API_PORT] = 53 +[PHY_ADDR] = 17 +[MDIO_BUS] = 1 + +[API_PORT] = 54 +[PHY_ADDR] = 18 +[MDIO_BUS] = 1 + +[API_PORT] = 55 +[PHY_ADDR] = 19 +[MDIO_BUS] = 1 + +[API_PORT] = 56 +[PHY_ADDR] = 20 +[MDIO_BUS] = 1 + +[API_PORT] = 57 +[PHY_ADDR] = 21 +[MDIO_BUS] = 1 + +[API_PORT] = 58 +[PHY_ADDR] = 22 +[MDIO_BUS] = 1 + +[API_PORT] = 59 +[PHY_ADDR] = 23 +[MDIO_BUS] = 1 + +#} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini new file mode 100644 index 000000000000..cd9f488c53b2 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini @@ -0,0 +1,53 @@ +# name lanes alias index speed admin_status +Ethernet1 0 eth-0-1 1 1000 up +Ethernet2 1 eth-0-2 2 1000 up +Ethernet3 2 eth-0-3 3 1000 up +Ethernet4 3 eth-0-4 4 1000 up +Ethernet5 4 eth-0-5 5 1000 up +Ethernet6 5 eth-0-6 6 1000 up +Ethernet7 6 eth-0-7 7 1000 up +Ethernet8 7 eth-0-8 8 1000 up +Ethernet9 16 eth-0-9 9 1000 up +Ethernet10 17 eth-0-10 10 1000 up +Ethernet11 18 eth-0-11 11 1000 up +Ethernet12 19 eth-0-12 12 1000 up +Ethernet13 20 eth-0-13 13 1000 up +Ethernet14 21 eth-0-14 14 1000 up +Ethernet15 22 eth-0-15 15 1000 up +Ethernet16 23 eth-0-16 16 1000 up +Ethernet17 8 eth-0-17 17 1000 up +Ethernet18 9 eth-0-18 18 1000 up +Ethernet19 10 eth-0-19 19 1000 up +Ethernet20 11 eth-0-20 20 1000 up +Ethernet21 32 eth-0-21 21 1000 up +Ethernet22 33 eth-0-22 22 1000 up +Ethernet23 34 eth-0-23 23 1000 up +Ethernet24 35 eth-0-24 24 1000 up +Ethernet25 36 eth-0-25 25 1000 up +Ethernet26 37 eth-0-26 26 1000 up +Ethernet27 38 eth-0-27 27 1000 up +Ethernet28 39 eth-0-28 28 1000 up +Ethernet29 40 eth-0-29 29 1000 up +Ethernet30 41 eth-0-30 30 1000 up +Ethernet31 42 eth-0-31 31 1000 up +Ethernet32 43 eth-0-32 32 1000 up +Ethernet33 24 eth-0-33 33 1000 up +Ethernet34 25 eth-0-34 34 1000 up +Ethernet35 26 eth-0-35 35 1000 up +Ethernet36 27 eth-0-36 36 1000 up +Ethernet37 48 eth-0-37 37 1000 up +Ethernet38 49 eth-0-38 38 1000 up +Ethernet39 50 eth-0-39 39 1000 up +Ethernet40 51 eth-0-40 40 1000 up +Ethernet41 52 eth-0-41 41 1000 up +Ethernet42 53 eth-0-42 42 1000 up +Ethernet43 54 eth-0-43 43 1000 up +Ethernet44 55 eth-0-44 44 1000 up +Ethernet45 56 eth-0-45 45 1000 up +Ethernet46 57 eth-0-46 46 1000 up +Ethernet47 58 eth-0-47 47 1000 up +Ethernet48 59 eth-0-48 48 1000 up +Ethernet49 12 eth-0-49 49 10000 up +Ethernet50 13 eth-0-50 50 10000 up +Ethernet51 14 eth-0-51 51 10000 up +Ethernet52 15 eth-0-52 52 10000 up diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile new file mode 100644 index 000000000000..5a5fe93dd4fe --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile @@ -0,0 +1,4 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-datapath.txt +SAI_PLATFORM_CFG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-board.json +SAI_PHY_DRIVER_PATH=/usr/share/sonic/hwsku/phy_drv \ No newline at end of file diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg new file mode 100644 index 000000000000..b012adedb252 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg @@ -0,0 +1,48 @@ + +chip set serdes 0 ffe mode user-define c0 0 c1 255 c2 10 c3 0 c4 0 +chip set serdes 1 ffe mode user-define c0 0 c1 240 c2 10 c3 0 c4 0 +chip set serdes 2 ffe mode user-define c0 0 c1 230 c2 10 c3 0 c4 0 +chip set serdes 3 ffe mode user-define c0 0 c1 220 c2 7 c3 0 c4 0 +chip set serdes 4 ffe mode user-define c0 0 c1 220 c2 8 c3 0 c4 0 +chip set serdes 5 ffe mode user-define c0 0 c1 210 c2 6 c3 0 c4 0 +chip set serdes 6 ffe mode user-define c0 0 c1 180 c2 6 c3 0 c4 0 +chip set serdes 7 ffe mode user-define c0 0 c1 180 c2 5 c3 0 c4 0 +chip set serdes 8 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0 +chip set serdes 9 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0 +chip set serdes 10 ffe mode user-define c0 3 c1 140 c2 9 c3 0 c4 0 +chip set serdes 11 ffe mode user-define c0 3 c1 140 c2 5 c3 0 c4 0 +chip set serdes 12 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 +chip set serdes 13 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 +chip set serdes 14 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 +chip set serdes 15 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 + + +chip set serdes 0 ctle 6 14 2 +chip set serdes 1 ctle 6 14 2 +chip set serdes 2 ctle 6 14 2 +chip set serdes 3 ctle 6 14 2 +chip set serdes 4 ctle 6 14 2 +chip set serdes 5 ctle 6 14 2 +chip set serdes 6 ctle 6 14 2 +chip set serdes 7 ctle 6 14 2 +chip set serdes 8 ctle 6 14 2 +chip set serdes 9 ctle 6 14 2 +chip set serdes 10 ctle 6 14 2 +chip set serdes 11 ctle 6 14 2 + + + +# rtk eye param, post_amp|main_amp|pre_amp +port 0 phy-attr type 2001 value 0x1c1e00 +port 4 phy-attr type 2001 value 0x101600 +port 16 phy-attr type 2001 value 0x111500 +port 20 phy-attr type 2001 value 0x0e1100 +port 8 phy-attr type 2001 value 0x0f1000 +port 32 phy-attr type 2001 value 0x0e0f00 +port 36 phy-attr type 2001 value 0x0a0a00 +port 40 phy-attr type 2001 value 0x0a0900 +port 24 phy-attr type 2001 value 0x000c00 +port 48 phy-attr type 2001 value 0x000b00 +port 52 phy-attr type 2001 value 0x000b00 +port 56 phy-attr type 2001 value 0x000a00 + diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json new file mode 100644 index 000000000000..80fb22238078 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json @@ -0,0 +1,868 @@ +{ + "macleds" : { + "polarity" : 1, + "freq" : 2500, + "interval" : 50000000, + "maps" : [ + { + "port_id" : 0, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port1/brightness" + }, + { + "port_id" : 1, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port2/brightness" + }, + { + "port_id" : 2, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port3/brightness" + }, + { + "port_id" : 3, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port4/brightness" + }, + { + "port_id" : 4, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port5/brightness" + }, + { + "port_id" : 5, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port6/brightness" + }, + { + "port_id" : 6, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port7/brightness" + }, + { + "port_id" : 7, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port8/brightness" + }, + { + "port_id" : 16, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port9/brightness" + }, + { + "port_id" : 17, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port10/brightness" + }, + { + "port_id" : 18, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port11/brightness" + }, + { + "port_id" : 19, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port12/brightness" + }, + { + "port_id" : 20, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port13/brightness" + }, + { + "port_id" : 21, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port14/brightness" + }, + { + "port_id" : 22, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port15/brightness" + }, + { + "port_id" : 23, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port16/brightness" + }, + { + "port_id" : 8, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port17/brightness" + }, + { + "port_id" : 9, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port18/brightness" + }, + { + "port_id" : 10, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port19/brightness" + }, + { + "port_id" : 11, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port20/brightness" + }, + { + "port_id" : 32, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port21/brightness" + }, + { + "port_id" : 33, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port22/brightness" + }, + { + "port_id" : 34, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port23/brightness" + }, + { + "port_id" : 35, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port24/brightness" + }, + { + "port_id" : 36, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port25/brightness" + }, + { + "port_id" : 37, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port26/brightness" + }, + { + "port_id" : 38, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port27/brightness" + }, + { + "port_id" : 39, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port28/brightness" + }, + { + "port_id" : 40, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port29/brightness" + }, + { + "port_id" : 41, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port30/brightness" + }, + { + "port_id" : 42, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port31/brightness" + }, + { + "port_id" : 43, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port32/brightness" + }, + { + "port_id" : 24, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port33/brightness" + }, + { + "port_id" : 25, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port34/brightness" + }, + { + "port_id" : 26, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port35/brightness" + }, + { + "port_id" : 27, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port36/brightness" + }, + { + "port_id" : 48, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port37/brightness" + }, + { + "port_id" : 49, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port38/brightness" + }, + { + "port_id" : 50, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port39/brightness" + }, + { + "port_id" : 51, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port40/brightness" + }, + { + "port_id" : 52, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port41/brightness" + }, + { + "port_id" : 53, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port42/brightness" + }, + { + "port_id" : 54, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port43/brightness" + }, + { + "port_id" : 55, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port44/brightness" + }, + { + "port_id" : 56, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port45/brightness" + }, + { + "port_id" : 57, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port46/brightness" + }, + { + "port_id" : 58, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port47/brightness" + }, + { + "port_id" : 59, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port48/brightness" + }, + { + "port_id" : 12, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port49/brightness" + }, + { + "port_id" : 13, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port50/brightness" + }, + { + "port_id" : 14, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port51/brightness" + }, + { + "port_id" : 15, + "lchip" : 0, + "ctl_id" : 0, + "mode" : "LED_MODE_1_RXLNK_BIACT", + "fixed" : 0, + "sysfs_path" : "/sys/class/leds/port52/brightness" + } + ] + }, + "phys" : [ + { + "macid" : 0, + "busid" : 0, + "addr" : 0, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 1, + "busid" : 0, + "addr" : 1, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 2, + "busid" : 0, + "addr" : 2, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 3, + "busid" : 0, + "addr" : 3, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 4, + "busid" : 0, + "addr" : 4, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 5, + "busid" : 0, + "addr" : 5, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 6, + "busid" : 0, + "addr" : 6, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 7, + "busid" : 0, + "addr" : 7, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 16, + "busid" : 0, + "addr" : 8, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 17, + "busid" : 0, + "addr" : 9, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 18, + "busid" : 0, + "addr" : 10, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 19, + "busid" : 0, + "addr" : 11, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 20, + "busid" : 0, + "addr" : 12, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 21, + "busid" : 0, + "addr" : 13, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 22, + "busid" : 0, + "addr" : 14, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 23, + "busid" : 0, + "addr" : 15, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 8, + "busid" : 0, + "addr" : 16, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 9, + "busid" : 0, + "addr" : 17, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 10, + "busid" : 0, + "addr" : 18, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 11, + "busid" : 0, + "addr" : 19, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 32, + "busid" : 0, + "addr" : 20, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 33, + "busid" : 0, + "addr" : 21, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 34, + "busid" : 0, + "addr" : 22, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 35, + "busid" : 0, + "addr" : 23, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 36, + "busid" : 1, + "addr" : 0, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 37, + "busid" : 1, + "addr" : 1, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 38, + "busid" : 1, + "addr" : 2, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 39, + "busid" : 1, + "addr" : 3, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 40, + "busid" : 1, + "addr" : 4, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 41, + "busid" : 1, + "addr" : 5, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 42, + "busid" : 1, + "addr" : 6, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 43, + "busid" : 1, + "addr" : 7, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 24, + "busid" : 1, + "addr" : 8, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 25, + "busid" : 1, + "addr" : 9, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 26, + "busid" : 1, + "addr" : 10, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 27, + "busid" : 1, + "addr" : 11, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 48, + "busid" : 1, + "addr" : 12, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 49, + "busid" : 1, + "addr" : 13, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 50, + "busid" : 1, + "addr" : 14, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 51, + "busid" : 1, + "addr" : 15, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 52, + "busid" : 1, + "addr" : 16, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 53, + "busid" : 1, + "addr" : 17, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 54, + "busid" : 1, + "addr" : 18, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 55, + "busid" : 1, + "addr" : 19, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 56, + "busid" : 1, + "addr" : 20, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 57, + "busid" : 1, + "addr" : 21, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 58, + "busid" : 1, + "addr" : 22, + "base_port": 1, + "last_port": 4 + }, + { + "macid" : 59, + "busid" : 1, + "addr" : 23, + "base_port": 1, + "last_port": 4 + } + ], + "ffe" : { + "board_material" : "BOARD_MATERIAL_M4", + "config" : [ + { + "serdes_id" : [0], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 255, 10, 0] + }, + { + "serdes_id" : [1], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 240, 10, 0] + }, + { + "serdes_id" : [2], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 230, 10, 0] + }, + { + "serdes_id" : [3], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 220, 7, 0] + }, + { + "serdes_id" : [4], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 220, 8, 0] + }, + { + "serdes_id" : [5], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 210, 6, 0] + }, + { + "serdes_id" : [6], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 180, 6, 0] + }, + { + "serdes_id" : [7], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [0, 180, 5, 0] + }, + { + "serdes_id" : [8], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, 160, 4, 0] + }, + { + "serdes_id" : [9], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [2, 160, 4, 0] + }, + { + "serdes_id" : [10], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [3, 140, 9, 0] + }, + { + "serdes_id" : [11], + "is_dac" : 0, + "speed" : [1000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [3, 140, 5, 0] + }, + { + "serdes_id" : [12, 13, 14, 15], + "is_dac" : 0, + "speed" : [10000], + "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", + "cfg" : [3, 94, 15, 0] + } + ] + }, + "ctle" : { + "config" : [ + { + "serdes_id" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], + "auto-en" : 0, + "cfg" : [6, 14, 2] + } + ] + } +} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt new file mode 100644 index 000000000000..2373e27f5f8b --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt @@ -0,0 +1,96 @@ +#----------------- 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] = 1; +[NPM_SUPPORT] = 1; +[DOT1AE_SUPPORT] = 1; + +#----------------- Chip Init Parameter -------------- +#Local chip number and global chip id +[Local chip_num] = 1 +[Local chip0] = 0 +[Local chip1] = 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 + +#----------------- Interrupt Init Parameter -------------- +#0: pin, 1: msi +[Interrupt_mode] = 0 +[IRQ] = 69 + +#----------------- 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 + +#----------------- L2 Init Parameter -------------- +[FDB Hw Learning] = 1 +[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_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 port queue number support 16/8/8 BPE/4 BPE, +#When resrc_profile.cfg exist, queue number valid, +#Default 8 queue mode +#8 queue = 8 +#16 queue = 16 +#4 queue BPE = 17 +#8 queue BPE = 18 +[QOS_PORT_QUEUE_NUM] = 8 +#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_POLICER_MERGE_MODE] = 0 +#QOS service queue mode, default 0,0:logic scr port + dstport enq 1:service id + dstport enq +[QOS_SERVICE_QUEUE_MODE] = 0 +#Global enable logic dst port + dstport enq +[QOS_SERVICE_QUEUE_EGRESS_EN] = 0 + +#----------------- Stacking Init Parameter -------------- +#0: normal mode; 1: spine-leaf mode +[FABRIC MODE] = 0 +[STACKING VERSION] = 1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt new file mode 100644 index 000000000000..959b97a150cc --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt @@ -0,0 +1,281 @@ +#Generated by 'CTC DataPath Tools' on Fri Dec 18 19:15:31 2020 +#Version 1.0, Supported by TsingMa SDK + + +#SERDES_MODE : 0-NONE, 1-XFI, 2-SGMII, 3-Not Support, 4-QSGMII, 5-XAUI, 6-DXAUI, 7-XLG, 8-CG, 9-SGMII2G5 +# 10-USXGMII-S, 11-USXGMII-M2G5, 12-USXGMII-M5G, 13-XXVG, 14-LG, 15-100BASE-FX +#SERDES_RX_POLY: 0-Normal, 1-Inverse +#SERDES_SWITCH : 0-Not Support Dynamic Switch, 1-Support Dynamic Switch + +[WLAN_ENABLE] = 1 +[DOT1AE_ENABLE] = 1 + +[CORE_PLLA] = 600 +#{ +[SERDES_ITEM] +#repeat 32 step 6 +[SERDES_ID] = 0 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 1 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 2 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 3 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 4 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 5 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 6 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 7 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 8 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 1 +[SERDES_TX_POLY] = 1 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 9 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 10 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 11 +[SERDES_MODE] = 4 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 12 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 13 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 14 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 15 +[SERDES_MODE] = 1 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 1 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 16 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 17 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 18 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 19 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 20 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 21 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 22 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 23 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 24 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 25 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 26 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +[SERDES_ID] = 27 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +[SERDES_ID] = 28 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 29 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 0 + +[SERDES_ID] = 30 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +[SERDES_ID] = 31 +[SERDES_MODE] = 3 +[SERDES_RX_POLY] = 0 +[SERDES_TX_POLY] = 0 +[SERDES_SWITCH] = 0 +[SERDES_GROUP] = 1 + +#repeat end +#} + + +#[SERDES_TO_LPORT] +#{ +# | QSGMII/USXGMII-M2G5 | USXGMII-M5G | USXGMII-S | 100BASE-FX | SGMII/SGMII2G5/XFI | XAUI/DXAUI | XLG | XXVG | LG | CG +#---------|---------------------|-------------|-----------|------------|--------------------|------------|-----|------|----|--- +#serdes 0 |0 /1 /2 /3 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 1 |4 /5 /6 /7 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 2 |16/17/18/19 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 3 |20/21/22/23 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 4 |8 /9 /10/11 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 5 |32/33/34/35 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 6 |36/37/38/39 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 7 |40/41/42/43 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 8 |24/25/26/27 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 9 |48/49/50/51 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 10|52/53/54/55 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 11|56/57/58/59 |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 12|NA |NA |NA |12 |12 |12 |12 |NA |NA |NA +#serdes 13|NA |NA |NA |13 |13 |12 |12 |NA |NA |NA +#serdes 14|NA |NA |NA |14 |14 |12 |12 |NA |NA |NA +#serdes 15|NA |NA |NA |15 |15 |12 |12 |NA |NA |NA +#serdes 16|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 17|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 18|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 19|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 20|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 21|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 22|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 23|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 24|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 25|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 26|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 27|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 28|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 29|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 30|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#serdes 31|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA +#} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku new file mode 100644 index 000000000000..2a8d51c1f241 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku @@ -0,0 +1 @@ +RA-B6010-48GT4X l1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg new file mode 100644 index 000000000000..eefd67e9c28b --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg @@ -0,0 +1,198 @@ +#######################PHY_MAPPING_48+4####################### + +#{ +[PHY_MAPPING_ITEM] + +[API_PORT] = 0 +[PHY_ADDR] = 0 +[MDIO_BUS] = 0 + +[API_PORT] = 1 +[PHY_ADDR] = 1 +[MDIO_BUS] = 0 + +[API_PORT] = 2 +[PHY_ADDR] = 2 +[MDIO_BUS] = 0 + +[API_PORT] = 3 +[PHY_ADDR] = 3 +[MDIO_BUS] = 0 + +[API_PORT] = 4 +[PHY_ADDR] = 4 +[MDIO_BUS] = 0 + +[API_PORT] = 5 +[PHY_ADDR] = 5 +[MDIO_BUS] = 0 + +[API_PORT] = 6 +[PHY_ADDR] = 6 +[MDIO_BUS] = 0 + +[API_PORT] = 7 +[PHY_ADDR] = 7 +[MDIO_BUS] = 0 + +[API_PORT] = 16 +[PHY_ADDR] = 8 +[MDIO_BUS] = 0 + +[API_PORT] = 17 +[PHY_ADDR] = 9 +[MDIO_BUS] = 0 + +[API_PORT] = 18 +[PHY_ADDR] = 10 +[MDIO_BUS] = 0 + +[API_PORT] = 19 +[PHY_ADDR] = 11 +[MDIO_BUS] = 0 + +[API_PORT] = 20 +[PHY_ADDR] = 12 +[MDIO_BUS] = 0 + +[API_PORT] = 21 +[PHY_ADDR] = 13 +[MDIO_BUS] = 0 + +[API_PORT] = 22 +[PHY_ADDR] = 14 +[MDIO_BUS] = 0 + +[API_PORT] = 23 +[PHY_ADDR] = 15 +[MDIO_BUS] = 0 + +[API_PORT] = 8 +[PHY_ADDR] = 16 +[MDIO_BUS] = 0 + +[API_PORT] = 9 +[PHY_ADDR] = 17 +[MDIO_BUS] = 0 + +[API_PORT] = 10 +[PHY_ADDR] = 18 +[MDIO_BUS] = 0 + +[API_PORT] = 11 +[PHY_ADDR] = 19 +[MDIO_BUS] = 0 + +[API_PORT] = 32 +[PHY_ADDR] = 20 +[MDIO_BUS] = 0 + +[API_PORT] = 33 +[PHY_ADDR] = 21 +[MDIO_BUS] = 0 + +[API_PORT] = 34 +[PHY_ADDR] = 22 +[MDIO_BUS] = 0 + +[API_PORT] = 35 +[PHY_ADDR] = 23 +[MDIO_BUS] = 0 + +[API_PORT] = 36 +[PHY_ADDR] = 0 +[MDIO_BUS] = 1 + +[API_PORT] = 37 +[PHY_ADDR] = 1 +[MDIO_BUS] = 1 + +[API_PORT] = 38 +[PHY_ADDR] = 2 +[MDIO_BUS] = 1 + +[API_PORT] = 39 +[PHY_ADDR] = 3 +[MDIO_BUS] = 1 + +[API_PORT] = 40 +[PHY_ADDR] = 4 +[MDIO_BUS] = 1 + +[API_PORT] = 41 +[PHY_ADDR] = 5 +[MDIO_BUS] = 1 + +[API_PORT] = 42 +[PHY_ADDR] = 6 +[MDIO_BUS] = 1 + +[API_PORT] = 43 +[PHY_ADDR] = 7 +[MDIO_BUS] = 1 + +[API_PORT] = 24 +[PHY_ADDR] = 8 +[MDIO_BUS] = 1 + +[API_PORT] = 25 +[PHY_ADDR] = 9 +[MDIO_BUS] = 1 + +[API_PORT] = 26 +[PHY_ADDR] = 10 +[MDIO_BUS] = 1 + +[API_PORT] = 27 +[PHY_ADDR] = 11 +[MDIO_BUS] = 1 + +[API_PORT] = 48 +[PHY_ADDR] = 12 +[MDIO_BUS] = 1 + +[API_PORT] = 49 +[PHY_ADDR] = 13 +[MDIO_BUS] = 1 + +[API_PORT] = 50 +[PHY_ADDR] = 14 +[MDIO_BUS] = 1 + +[API_PORT] = 51 +[PHY_ADDR] = 15 +[MDIO_BUS] = 1 + +[API_PORT] = 52 +[PHY_ADDR] = 16 +[MDIO_BUS] = 1 + +[API_PORT] = 53 +[PHY_ADDR] = 17 +[MDIO_BUS] = 1 + +[API_PORT] = 54 +[PHY_ADDR] = 18 +[MDIO_BUS] = 1 + +[API_PORT] = 55 +[PHY_ADDR] = 19 +[MDIO_BUS] = 1 + +[API_PORT] = 56 +[PHY_ADDR] = 20 +[MDIO_BUS] = 1 + +[API_PORT] = 57 +[PHY_ADDR] = 21 +[MDIO_BUS] = 1 + +[API_PORT] = 58 +[PHY_ADDR] = 22 +[MDIO_BUS] = 1 + +[API_PORT] = 59 +[PHY_ADDR] = 23 +[MDIO_BUS] = 1 + +#} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini new file mode 100644 index 000000000000..cd9f488c53b2 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini @@ -0,0 +1,53 @@ +# name lanes alias index speed admin_status +Ethernet1 0 eth-0-1 1 1000 up +Ethernet2 1 eth-0-2 2 1000 up +Ethernet3 2 eth-0-3 3 1000 up +Ethernet4 3 eth-0-4 4 1000 up +Ethernet5 4 eth-0-5 5 1000 up +Ethernet6 5 eth-0-6 6 1000 up +Ethernet7 6 eth-0-7 7 1000 up +Ethernet8 7 eth-0-8 8 1000 up +Ethernet9 16 eth-0-9 9 1000 up +Ethernet10 17 eth-0-10 10 1000 up +Ethernet11 18 eth-0-11 11 1000 up +Ethernet12 19 eth-0-12 12 1000 up +Ethernet13 20 eth-0-13 13 1000 up +Ethernet14 21 eth-0-14 14 1000 up +Ethernet15 22 eth-0-15 15 1000 up +Ethernet16 23 eth-0-16 16 1000 up +Ethernet17 8 eth-0-17 17 1000 up +Ethernet18 9 eth-0-18 18 1000 up +Ethernet19 10 eth-0-19 19 1000 up +Ethernet20 11 eth-0-20 20 1000 up +Ethernet21 32 eth-0-21 21 1000 up +Ethernet22 33 eth-0-22 22 1000 up +Ethernet23 34 eth-0-23 23 1000 up +Ethernet24 35 eth-0-24 24 1000 up +Ethernet25 36 eth-0-25 25 1000 up +Ethernet26 37 eth-0-26 26 1000 up +Ethernet27 38 eth-0-27 27 1000 up +Ethernet28 39 eth-0-28 28 1000 up +Ethernet29 40 eth-0-29 29 1000 up +Ethernet30 41 eth-0-30 30 1000 up +Ethernet31 42 eth-0-31 31 1000 up +Ethernet32 43 eth-0-32 32 1000 up +Ethernet33 24 eth-0-33 33 1000 up +Ethernet34 25 eth-0-34 34 1000 up +Ethernet35 26 eth-0-35 35 1000 up +Ethernet36 27 eth-0-36 36 1000 up +Ethernet37 48 eth-0-37 37 1000 up +Ethernet38 49 eth-0-38 38 1000 up +Ethernet39 50 eth-0-39 39 1000 up +Ethernet40 51 eth-0-40 40 1000 up +Ethernet41 52 eth-0-41 41 1000 up +Ethernet42 53 eth-0-42 42 1000 up +Ethernet43 54 eth-0-43 43 1000 up +Ethernet44 55 eth-0-44 44 1000 up +Ethernet45 56 eth-0-45 45 1000 up +Ethernet46 57 eth-0-46 46 1000 up +Ethernet47 58 eth-0-47 47 1000 up +Ethernet48 59 eth-0-48 48 1000 up +Ethernet49 12 eth-0-49 49 10000 up +Ethernet50 13 eth-0-50 50 10000 up +Ethernet51 14 eth-0-51 51 10000 up +Ethernet52 15 eth-0-52 52 10000 up diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile new file mode 100644 index 000000000000..5a5fe93dd4fe --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile @@ -0,0 +1,4 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-datapath.txt +SAI_PLATFORM_CFG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-board.json +SAI_PHY_DRIVER_PATH=/usr/share/sonic/hwsku/phy_drv \ No newline at end of file diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg new file mode 100644 index 000000000000..b012adedb252 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg @@ -0,0 +1,48 @@ + +chip set serdes 0 ffe mode user-define c0 0 c1 255 c2 10 c3 0 c4 0 +chip set serdes 1 ffe mode user-define c0 0 c1 240 c2 10 c3 0 c4 0 +chip set serdes 2 ffe mode user-define c0 0 c1 230 c2 10 c3 0 c4 0 +chip set serdes 3 ffe mode user-define c0 0 c1 220 c2 7 c3 0 c4 0 +chip set serdes 4 ffe mode user-define c0 0 c1 220 c2 8 c3 0 c4 0 +chip set serdes 5 ffe mode user-define c0 0 c1 210 c2 6 c3 0 c4 0 +chip set serdes 6 ffe mode user-define c0 0 c1 180 c2 6 c3 0 c4 0 +chip set serdes 7 ffe mode user-define c0 0 c1 180 c2 5 c3 0 c4 0 +chip set serdes 8 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0 +chip set serdes 9 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0 +chip set serdes 10 ffe mode user-define c0 3 c1 140 c2 9 c3 0 c4 0 +chip set serdes 11 ffe mode user-define c0 3 c1 140 c2 5 c3 0 c4 0 +chip set serdes 12 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 +chip set serdes 13 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 +chip set serdes 14 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 +chip set serdes 15 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 + + +chip set serdes 0 ctle 6 14 2 +chip set serdes 1 ctle 6 14 2 +chip set serdes 2 ctle 6 14 2 +chip set serdes 3 ctle 6 14 2 +chip set serdes 4 ctle 6 14 2 +chip set serdes 5 ctle 6 14 2 +chip set serdes 6 ctle 6 14 2 +chip set serdes 7 ctle 6 14 2 +chip set serdes 8 ctle 6 14 2 +chip set serdes 9 ctle 6 14 2 +chip set serdes 10 ctle 6 14 2 +chip set serdes 11 ctle 6 14 2 + + + +# rtk eye param, post_amp|main_amp|pre_amp +port 0 phy-attr type 2001 value 0x1c1e00 +port 4 phy-attr type 2001 value 0x101600 +port 16 phy-attr type 2001 value 0x111500 +port 20 phy-attr type 2001 value 0x0e1100 +port 8 phy-attr type 2001 value 0x0f1000 +port 32 phy-attr type 2001 value 0x0e0f00 +port 36 phy-attr type 2001 value 0x0a0a00 +port 40 phy-attr type 2001 value 0x0a0900 +port 24 phy-attr type 2001 value 0x000c00 +port 48 phy-attr type 2001 value 0x000b00 +port 52 phy-attr type 2001 value 0x000b00 +port 56 phy-attr type 2001 value 0x000a00 + diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku new file mode 100644 index 000000000000..2a8d51c1f241 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku @@ -0,0 +1 @@ +RA-B6010-48GT4X l1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf new file mode 100644 index 000000000000..a44cb9c23c93 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf @@ -0,0 +1,9 @@ +CONSOLE_SPEED=9600 + +#fix env +config_env(){ + dd if=/dev/mtd1 of=env.bin + flashcp -v env.bin /dev/mtd4 +} +trap_push "config_env || true" + diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py new file mode 100644 index 000000000000..93b331573d6d --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +RAGILE_CARDID = 0x00004099 +RAGILE_PRODUCTNAME = "RA-B6010-48GT4X" +RAGILE_PART_NUMBER = "RJ000001" +RAGILE_LABEL_REVISION = "R01" +RAGILE_ONIE_VERSION = "2018.02" +RAGILE_MAC_SIZE = 3 +RAGILE_MANUF_NAME = "Ragile" +RAGILE_MANUF_COUNTRY = "CHN" +RAGILE_VENDOR_NAME = "Ragile" +RAGILE_DIAG_VERSION = "0.1.0.15" +RAGILE_SERVICE_TAG = "www.ragile.com" + +CPUEEPROMS = {"name":"cpueeprom","bus":5,"loc":0x57,"E2PRODUCT":'2', "E2TYPE":'4'} + +# rg_eeprom = "1-0056/eeprom" +E2_LOC = {"bus":1, "devno":0x56} +E2_PROTECT = {} +FAN_PROTECT = {"bus":1, "devno":0x0d, "addr":0x19, "open":0x00, "close":0xff} + + diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..77016e17944a --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..ad619bf33469 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py @@ -0,0 +1,455 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import subprocess + import re + import os + import threading + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 49 + PORT_END = 52 + PORTS_IN_BLOCK = 53 + EEPROM_OFFSET = 9 + SFP_DEVICE_TYPE = "optoe2" + QSFP_DEVICE_TYPE = "optoe1" + I2C_MAX_ATTEMPT = 3 + + SFP_STATUS_INSERTED = '1' + SFP_STATUS_REMOVED = '0' + + TXWRT_PROTECT = 0X4E + TXWRT_NO_PROTECT = 0X59 + + _port_to_eeprom_mapping = {} + port_to_i2cbus_mapping ={} + port_dict = {} + port_presence_info = {} + port_reset_info = {} + port_txdis_info = {} + port_txwrt_info = {} + port_led_info = {} + + port_rxlos_info = {} + port_txfault_info = {} + port_drop_info = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK)) + + @property + def qsfp_ports(self): + return [] + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + self.port_to_i2cbus_mapping[x] = (x - self.PORT_START + self.EEPROM_OFFSET) + self.port_presence_info["/sys/bus/i2c/devices/3-0030/sfp_presence1"] = [49, 50, 51, 52] + self.port_txdis_info["/sys/bus/i2c/devices/3-0030/tx_disable"] = [49, 50, 51, 52] + self.port_txwrt_info["/sys/bus/i2c/devices/3-0030/tx_write_protect"] = [49, 50, 51, 52] + + # bit 1: los + self.port_rxlos_info["/sys/bus/i2c/devices/3-0030/sfp_rx_loss1"] = [49, 50, 51, 52] + + # bit 1: fault + self.port_txfault_info["/sys/bus/i2c/devices/3-0030/sfp_tx_fault1"] = [49, 50, 51, 52] + + # bit 1: drop + self.port_drop_info["/sys/bus/i2c/devices/3-0030/sfp_drop_record1"] = [49, 50, 51, 52] + + SfpUtilBase.__init__(self) + + def _sfp_read_file_path(self, file_path, offset, num_bytes): + attempts = 0 + while attempts < self.I2C_MAX_ATTEMPT: + try: + file_path.seek(offset) + read_buf = file_path.read(num_bytes) + except: + attempts += 1 + time.sleep(0.05) + else: + return True, read_buf + return False, None + + def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset): + """Tries to read the eeprom file to determine if the + device/sfp is present or not. If sfp present, the read returns + valid bytes. If not, read returns error 'Connection timed out""" + + if not os.path.exists(sysfs_sfp_i2c_client_eeprompath): + return False + else: + with open(sysfs_sfp_i2c_client_eeprompath, "rb", buffering=0) as sysfsfile: + rv, buf = self._sfp_read_file_path(sysfsfile, offset, 1) + return rv + + def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype): + try: + sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path + + # Write device address to new_device file + nd_file = open(sysfs_nd_path, "w") + nd_str = "%s %s" % (devtype, hex(devaddr)) + nd_file.write(nd_str) + nd_file.close() + + except Exception as err: + print(("Error writing to new device file: %s" % str(err))) + return 1 + else: + return 0 + + def _get_port_eeprom_path(self, port_num, devid): + sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" + + if port_num in list(self.port_to_eeprom_mapping.keys()): + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num] + else: + sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" + + i2c_adapter_id = self._get_port_i2c_adapter_id(port_num) + if i2c_adapter_id is None: + print("Error getting i2c bus num") + return None + + # Get i2c virtual bus path for the sfp + sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path, + str(i2c_adapter_id)) + + # If i2c bus for port does not exist + if not os.path.exists(sysfs_sfp_i2c_adapter_path): + print(("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path)) + return None + + sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path, + str(i2c_adapter_id), + hex(devid)[-2:]) + + # If sfp device is not present on bus, Add it + if not os.path.exists(sysfs_sfp_i2c_client_path): + if port_num in self.qsfp_ports: + ret = self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE) + else: + ret = self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE) + if ret != 0: + print("Error adding sfp device") + return None + + sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path + return sysfs_sfp_i2c_client_eeprom_path + + def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + rv, raw = self._sfp_read_file_path(sysfsfile_eeprom, offset, num_bytes) + if rv == False: + return None + + try: + if isinstance(raw, str): + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + else: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except Exception as err: + return None + return eeprom_raw + + def get_eeprom_dom_raw(self, port_num): + if port_num in self.qsfp_ports: + # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw + return None + else: + # Read dom eeprom at addr 0x51 + return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 256) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + presence_path = None + for presence_key in self.port_presence_info: + if port_num in self.port_presence_info[presence_key]: + presence_path = presence_key + presence_offset = self.port_presence_info[presence_key].index(port_num) + break + if presence_path == None: + return False + + try: + data = open(presence_path, "rb") + except IOError: + return False + + presence_data = data.read(2) + if presence_data == "": + return False + result = int(presence_data, 16) + data.close() + + # ModPrsL is active low + if result & (1 << presence_offset) == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + return False + + def set_low_power_mode(self, port_num, lpmode): + return False + + def reset(self, port_num): + return False + + def reset_all(self): + return False + + def _do_write_file(self, file_handle, offset, value): + file_handle.seek(offset) + file_handle.write(hex(value)) + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + currernt_port_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print(("get_transceiver_change_event:Invalid timeout value", timeout)) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print(('get_transceiver_change_event:' \ + 'time wrap / invalid timeout value', timeout)) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + if self.get_presence(x): + currernt_port_dict[x] = self.SFP_STATUS_INSERTED + else: + currernt_port_dict[x] = self.SFP_STATUS_REMOVED + if (currernt_port_dict == self.port_dict): + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + else: + # Update reg value + self.port_dict = currernt_port_dict + return True, self.port_dict + print ("get_transceiver_change_event: Should not reach here.") + return False, {} + + def tx_disable(self, port_num, disable): + if not self.get_presence(port_num): + return False + + if port_num in self.sfp_ports: + txwrt_path = None + txdis_path = None + txdis_offset = 0 + + for key in self.port_txwrt_info: + if port_num in self.port_txwrt_info[key]: + txwrt_path = key + break + if txwrt_path == None: + return False + + for key in self.port_txdis_info: + if port_num in self.port_txdis_info[key]: + txdis_path = key + txdis_offset = self.port_txdis_info[key].index(port_num) + break + if txdis_path == None: + return False + + + try: + with open(txwrt_path, "r+") as sys_file: + sres = hex(self.TXWRT_NO_PROTECT)[2:] + sys_file.write(sres) + + with open(txdis_path, "r+") as sys_file: + txdis_data = sys_file.read(2) + if not txdis_data: + return False + result = int(txdis_data, 16) + if disable: + result = result | (1 << txdis_offset) + else: + result = result & (~(1 << txdis_offset)) + sys_file.seek(0) + sres = hex(result)[2:] + print(result,sres) + sys_file.write(sres) + + with open(txwrt_path, "r+") as sys_file: + sres = hex(self.TXWRT_PROTECT)[2:] + sys_file.write(sres) + except Exception as err: + print(err) + return False + + return True + else: + return False + +########### sysdiag ########### + def _get_cpld_info(self, port_num, info): + path = None + offset = 0 + for key in info: + if port_num in info[key]: + path = key + offset = info[key].index(port_num) + break + return path, offset + + def get_tx_disable(self, port_num): + # cur only support sfp moudle + if port_num not in self.sfp_ports: + return False + + if not self.get_presence(port_num): + return False + + path, offset = self._get_cpld_info(port_num, self.port_txdis_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: disable + if result & (1 << offset): + return True + else: + return False + + def get_rx_los(self, port_num): + # cur only support sfp moudle + if port_num not in self.sfp_ports: + return False + + path, offset = self._get_cpld_info(port_num, self.port_rxlos_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: los + if result & (1 << offset): + return True + else: + return False + + def get_tx_fault(self, port_num): + # cur only support sfp moudle + if port_num not in self.sfp_ports: + return False + + if not self.get_presence(port_num): + return False + + path, offset = self._get_cpld_info(port_num, self.port_txfault_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: fault + if result & (1 << offset): + return True + else: + return False + + return False + + def get_plug_record(self, port_num): + if not self.get_presence(port_num): + return False + + path, offset = self._get_cpld_info(port_num, self.port_drop_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: drop + if result & (1 << offset): + return True + else: + return False diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..5fdf83f1b9e6 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_xcvrd": false, + "skip_syseepromd": false, + "skip_thermalctld": false, + "skip_psud": false +} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/default_sku b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/default_sku new file mode 100644 index 000000000000..2a8d51c1f241 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/default_sku @@ -0,0 +1 @@ +RA-B6010-48GT4X l1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf new file mode 100644 index 000000000000..a44cb9c23c93 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf @@ -0,0 +1,9 @@ +CONSOLE_SPEED=9600 + +#fix env +config_env(){ + dd if=/dev/mtd1 of=env.bin + flashcp -v env.bin /dev/mtd4 +} +trap_push "config_env || true" + diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py new file mode 100644 index 000000000000..93b331573d6d --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +RAGILE_CARDID = 0x00004099 +RAGILE_PRODUCTNAME = "RA-B6010-48GT4X" +RAGILE_PART_NUMBER = "RJ000001" +RAGILE_LABEL_REVISION = "R01" +RAGILE_ONIE_VERSION = "2018.02" +RAGILE_MAC_SIZE = 3 +RAGILE_MANUF_NAME = "Ragile" +RAGILE_MANUF_COUNTRY = "CHN" +RAGILE_VENDOR_NAME = "Ragile" +RAGILE_DIAG_VERSION = "0.1.0.15" +RAGILE_SERVICE_TAG = "www.ragile.com" + +CPUEEPROMS = {"name":"cpueeprom","bus":5,"loc":0x57,"E2PRODUCT":'2', "E2TYPE":'4'} + +# rg_eeprom = "1-0056/eeprom" +E2_LOC = {"bus":1, "devno":0x56} +E2_PROTECT = {} +FAN_PROTECT = {"bus":1, "devno":0x0d, "addr":0x19, "open":0x00, "close":0xff} + + diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..77016e17944a --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..ad619bf33469 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py @@ -0,0 +1,455 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import subprocess + import re + import os + import threading + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 49 + PORT_END = 52 + PORTS_IN_BLOCK = 53 + EEPROM_OFFSET = 9 + SFP_DEVICE_TYPE = "optoe2" + QSFP_DEVICE_TYPE = "optoe1" + I2C_MAX_ATTEMPT = 3 + + SFP_STATUS_INSERTED = '1' + SFP_STATUS_REMOVED = '0' + + TXWRT_PROTECT = 0X4E + TXWRT_NO_PROTECT = 0X59 + + _port_to_eeprom_mapping = {} + port_to_i2cbus_mapping ={} + port_dict = {} + port_presence_info = {} + port_reset_info = {} + port_txdis_info = {} + port_txwrt_info = {} + port_led_info = {} + + port_rxlos_info = {} + port_txfault_info = {} + port_drop_info = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK)) + + @property + def qsfp_ports(self): + return [] + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + self.port_to_i2cbus_mapping[x] = (x - self.PORT_START + self.EEPROM_OFFSET) + self.port_presence_info["/sys/bus/i2c/devices/3-0030/sfp_presence1"] = [49, 50, 51, 52] + self.port_txdis_info["/sys/bus/i2c/devices/3-0030/tx_disable"] = [49, 50, 51, 52] + self.port_txwrt_info["/sys/bus/i2c/devices/3-0030/tx_write_protect"] = [49, 50, 51, 52] + + # bit 1: los + self.port_rxlos_info["/sys/bus/i2c/devices/3-0030/sfp_rx_loss1"] = [49, 50, 51, 52] + + # bit 1: fault + self.port_txfault_info["/sys/bus/i2c/devices/3-0030/sfp_tx_fault1"] = [49, 50, 51, 52] + + # bit 1: drop + self.port_drop_info["/sys/bus/i2c/devices/3-0030/sfp_drop_record1"] = [49, 50, 51, 52] + + SfpUtilBase.__init__(self) + + def _sfp_read_file_path(self, file_path, offset, num_bytes): + attempts = 0 + while attempts < self.I2C_MAX_ATTEMPT: + try: + file_path.seek(offset) + read_buf = file_path.read(num_bytes) + except: + attempts += 1 + time.sleep(0.05) + else: + return True, read_buf + return False, None + + def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset): + """Tries to read the eeprom file to determine if the + device/sfp is present or not. If sfp present, the read returns + valid bytes. If not, read returns error 'Connection timed out""" + + if not os.path.exists(sysfs_sfp_i2c_client_eeprompath): + return False + else: + with open(sysfs_sfp_i2c_client_eeprompath, "rb", buffering=0) as sysfsfile: + rv, buf = self._sfp_read_file_path(sysfsfile, offset, 1) + return rv + + def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype): + try: + sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path + + # Write device address to new_device file + nd_file = open(sysfs_nd_path, "w") + nd_str = "%s %s" % (devtype, hex(devaddr)) + nd_file.write(nd_str) + nd_file.close() + + except Exception as err: + print(("Error writing to new device file: %s" % str(err))) + return 1 + else: + return 0 + + def _get_port_eeprom_path(self, port_num, devid): + sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" + + if port_num in list(self.port_to_eeprom_mapping.keys()): + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num] + else: + sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" + + i2c_adapter_id = self._get_port_i2c_adapter_id(port_num) + if i2c_adapter_id is None: + print("Error getting i2c bus num") + return None + + # Get i2c virtual bus path for the sfp + sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path, + str(i2c_adapter_id)) + + # If i2c bus for port does not exist + if not os.path.exists(sysfs_sfp_i2c_adapter_path): + print(("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path)) + return None + + sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path, + str(i2c_adapter_id), + hex(devid)[-2:]) + + # If sfp device is not present on bus, Add it + if not os.path.exists(sysfs_sfp_i2c_client_path): + if port_num in self.qsfp_ports: + ret = self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE) + else: + ret = self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE) + if ret != 0: + print("Error adding sfp device") + return None + + sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path + return sysfs_sfp_i2c_client_eeprom_path + + def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + rv, raw = self._sfp_read_file_path(sysfsfile_eeprom, offset, num_bytes) + if rv == False: + return None + + try: + if isinstance(raw, str): + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + else: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except Exception as err: + return None + return eeprom_raw + + def get_eeprom_dom_raw(self, port_num): + if port_num in self.qsfp_ports: + # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw + return None + else: + # Read dom eeprom at addr 0x51 + return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 256) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + presence_path = None + for presence_key in self.port_presence_info: + if port_num in self.port_presence_info[presence_key]: + presence_path = presence_key + presence_offset = self.port_presence_info[presence_key].index(port_num) + break + if presence_path == None: + return False + + try: + data = open(presence_path, "rb") + except IOError: + return False + + presence_data = data.read(2) + if presence_data == "": + return False + result = int(presence_data, 16) + data.close() + + # ModPrsL is active low + if result & (1 << presence_offset) == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + return False + + def set_low_power_mode(self, port_num, lpmode): + return False + + def reset(self, port_num): + return False + + def reset_all(self): + return False + + def _do_write_file(self, file_handle, offset, value): + file_handle.seek(offset) + file_handle.write(hex(value)) + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + currernt_port_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print(("get_transceiver_change_event:Invalid timeout value", timeout)) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print(('get_transceiver_change_event:' \ + 'time wrap / invalid timeout value', timeout)) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + if self.get_presence(x): + currernt_port_dict[x] = self.SFP_STATUS_INSERTED + else: + currernt_port_dict[x] = self.SFP_STATUS_REMOVED + if (currernt_port_dict == self.port_dict): + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + else: + # Update reg value + self.port_dict = currernt_port_dict + return True, self.port_dict + print ("get_transceiver_change_event: Should not reach here.") + return False, {} + + def tx_disable(self, port_num, disable): + if not self.get_presence(port_num): + return False + + if port_num in self.sfp_ports: + txwrt_path = None + txdis_path = None + txdis_offset = 0 + + for key in self.port_txwrt_info: + if port_num in self.port_txwrt_info[key]: + txwrt_path = key + break + if txwrt_path == None: + return False + + for key in self.port_txdis_info: + if port_num in self.port_txdis_info[key]: + txdis_path = key + txdis_offset = self.port_txdis_info[key].index(port_num) + break + if txdis_path == None: + return False + + + try: + with open(txwrt_path, "r+") as sys_file: + sres = hex(self.TXWRT_NO_PROTECT)[2:] + sys_file.write(sres) + + with open(txdis_path, "r+") as sys_file: + txdis_data = sys_file.read(2) + if not txdis_data: + return False + result = int(txdis_data, 16) + if disable: + result = result | (1 << txdis_offset) + else: + result = result & (~(1 << txdis_offset)) + sys_file.seek(0) + sres = hex(result)[2:] + print(result,sres) + sys_file.write(sres) + + with open(txwrt_path, "r+") as sys_file: + sres = hex(self.TXWRT_PROTECT)[2:] + sys_file.write(sres) + except Exception as err: + print(err) + return False + + return True + else: + return False + +########### sysdiag ########### + def _get_cpld_info(self, port_num, info): + path = None + offset = 0 + for key in info: + if port_num in info[key]: + path = key + offset = info[key].index(port_num) + break + return path, offset + + def get_tx_disable(self, port_num): + # cur only support sfp moudle + if port_num not in self.sfp_ports: + return False + + if not self.get_presence(port_num): + return False + + path, offset = self._get_cpld_info(port_num, self.port_txdis_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: disable + if result & (1 << offset): + return True + else: + return False + + def get_rx_los(self, port_num): + # cur only support sfp moudle + if port_num not in self.sfp_ports: + return False + + path, offset = self._get_cpld_info(port_num, self.port_rxlos_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: los + if result & (1 << offset): + return True + else: + return False + + def get_tx_fault(self, port_num): + # cur only support sfp moudle + if port_num not in self.sfp_ports: + return False + + if not self.get_presence(port_num): + return False + + path, offset = self._get_cpld_info(port_num, self.port_txfault_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: fault + if result & (1 << offset): + return True + else: + return False + + return False + + def get_plug_record(self, port_num): + if not self.get_presence(port_num): + return False + + path, offset = self._get_cpld_info(port_num, self.port_drop_info) + if path == None: + return False + + result = 0 + try: + with open(path, "r") as sys_file: + data = sys_file.read(2) + result = int(data, 16) + except Exception as e: + print((str(e))) + return False + + # 1: drop + if result & (1 << offset): + return True + else: + return False diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..5fdf83f1b9e6 --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_xcvrd": false, + "skip_syseepromd": false, + "skip_thermalctld": false, + "skip_psud": false +} diff --git a/platform/centec-arm64/one-image.mk b/platform/centec-arm64/one-image.mk index 3bcb9258fc6e..b8ef82853e25 100755 --- a/platform/centec-arm64/one-image.mk +++ b/platform/centec-arm64/one-image.mk @@ -11,6 +11,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48S4X_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2Q_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(FS_S5800_48T4S_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(RA_B6010_48GT4X_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(RA_B6010_48GT4X_R_PLATFORM_MODULE) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) diff --git a/platform/centec-arm64/platform-modules-ragile.dep b/platform/centec-arm64/platform-modules-ragile.dep new file mode 100644 index 000000000000..3963f76eab43 --- /dev/null +++ b/platform/centec-arm64/platform-modules-ragile.dep @@ -0,0 +1,10 @@ + +MPATH := $($(RA_B6010_48GT4X_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/centec-arm64/platform-modules-ragile.mk platform/centec-arm64/platform-modules-ragile.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(addprefix $(MPATH)/,$(shell cd $(MPATH) && git ls-files)) + +$(RA_B6010_48GT4X_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(RA_B6010_48GT4X_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(RA_B6010_48GT4X_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/centec-arm64/platform-modules-ragile.mk b/platform/centec-arm64/platform-modules-ragile.mk new file mode 100755 index 000000000000..dba72a5005df --- /dev/null +++ b/platform/centec-arm64/platform-modules-ragile.mk @@ -0,0 +1,16 @@ +## RA-B6010-48GT4X +RA_B6010_48GT4X_PLATFORM_MODULE_VERSION =1.3 +RA_B6010_48GT4X_R_PLATFORM_MODULE_VERSION =1.3 +export RA_B6010_48GT4X_PLATFORM_MODULE_VERSION + +RA_B6010_48GT4X_PLATFORM_MODULE = platform-modules-ra-b6010-48gt4x_$(RA_B6010_48GT4X_PLATFORM_MODULE_VERSION)_arm64.deb + +$(RA_B6010_48GT4X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ragile +$(RA_B6010_48GT4X_PLATFORM_MODULE)_PLATFORM = arm64-ragile_ra-b6010-48gt4x-r0 +$(RA_B6010_48GT4X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(RA_B6010_48GT4X_PLATFORM_MODULE) + +#ra-b6510-48gt4x-r +RA_B6010_48GT4X_R_PLATFORM_MODULE = platform-modules-ra-b6010-48gt4x-r_$(RA_B6010_48GT4X_R_PLATFORM_MODULE_VERSION)_arm64.deb +$(RA_B6010_48GT4X_R_PLATFORM_MODULE)_PLATFORM = arm64-ragile_ra-b6010-48gt4x-r-r0 +$(eval $(call add_extra_package,$(RA_B6010_48GT4X_PLATFORM_MODULE),$(RA_B6010_48GT4X_R_PLATFORM_MODULE))) diff --git a/platform/centec-arm64/rules.mk b/platform/centec-arm64/rules.mk index d88670f130c9..f08f553ee6cc 100755 --- a/platform/centec-arm64/rules.mk +++ b/platform/centec-arm64/rules.mk @@ -6,6 +6,7 @@ include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk include $(PLATFORM_PATH)/tsingma-bsp.mk include $(PLATFORM_PATH)/platform-modules-centec-e530.mk +include $(PLATFORM_PATH)/platform-modules-ragile.mk include $(PLATFORM_PATH)/platform-modules-fs.mk SONIC_ALL += $(SONIC_ONE_IMAGE) \ diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk index 2a8ee5c45d36..032c4916314a 100755 --- a/platform/centec-arm64/sai.mk +++ b/platform/centec-arm64/sai.mk @@ -1,13 +1,12 @@ # Centec SAI -export CENTEC_SAI_VERSION = 1.11.0-1 +export CENTEC_SAI_VERSION = 1.10.2-1 export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb export CENTEC_SAI_DEV = libsai-dev_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb -$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) -$(CENTEC_SAI_DEV)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI_DEV) +$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sai-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) +$(CENTEC_SAI_DEV)_URL = https://github.com/CentecNetworks/sai-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI_DEV) $(eval $(call add_conflict_package,$(CENTEC_SAI_DEV),$(LIBSAIVS_DEV))) SONIC_ONLINE_DEBS += $(CENTEC_SAI) SONIC_ONLINE_DEBS += $(CENTEC_SAI_DEV) - diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/LICENSE b/platform/centec-arm64/sonic-platform-modules-ragile/LICENSE new file mode 100644 index 000000000000..2d14d2b7785f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2019 Centec, Inc + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/README.md b/platform/centec-arm64/sonic-platform-modules-ragile/README.md new file mode 100644 index 000000000000..6b907de17378 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/README.md @@ -0,0 +1 @@ +platform drivers for Centec E530 for the SONiC project diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/Makefile new file mode 100644 index 000000000000..8a7f579ee7f4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/Makefile @@ -0,0 +1,47 @@ +PWD = $(shell pwd) +CC ?=gcc +INSTALL_MOD_DIR ?=extra +KVERSION ?= $(shell uname -r) +KERNEL_SRC ?= /lib/modules/$(KVERSION) +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +ifdef ENABLE_GCOV +ifeq ($(ENABLE_GCOV), y) +EXTRA_CFLAGS+= -fprofile-arcs -ftest-coverage -lgcov +endif +endif # ENABLE_GCOV +SUB_BUILD_DIR = $(PWD)/build +DIR_KERNEL_SRC = $(PWD)/modules +SCRIPT_DIR = $(PWD)/script +SERVICE_DIR = $(PWD)/service +BLACK_DRIVER_CONF_DIR = $(PWD)/modprobe_conf + +app_dir = $(PWD)/app +app_build_dir = $(app_dir)/build +modules_build_dir = $(DIR_KERNEL_SRC)/build + +INSTALL_MODULE_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) +INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin +INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system +INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3.9/dist-packages +INSTALL_BLACK_DRIVER = $(SUB_BUILD_DIR)/etc/modprobe.d +CTC_48GT4X_PHY_DIR = $(SUB_BUILD_DIR)/usr/share/sonic/device/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X + +all: + $(MAKE) -C $(app_dir) + $(MAKE) -C $(DIR_KERNEL_SRC) + @if [ ! -d ${INSTALL_MODULE_DIR} ]; then mkdir -p ${INSTALL_MODULE_DIR} ;fi + @if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi + @if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi + @if [ ! -d ${CTC_48GT4X_PHY_DIR} ]; then mkdir -p ${CTC_48GT4X_PHY_DIR}/phy_drv ;fi + @if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi + @if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi + cp -r $(app_dir)/*.so $(CTC_48GT4X_PHY_DIR)/phy_drv + #cp -r $(app_build_dir)/module/*.ko $(INSTALL_MODULE_DIR) + cp -r $(modules_build_dir)/*.ko $(INSTALL_MODULE_DIR) + #cp -r $(app_dir)/build/app/* $(INSTALL_SCRIPT_DIR) + if [ -d $(SCRIPT_DIR) ]; then cp -r $(SCRIPT_DIR)/* $(INSTALL_SCRIPT_DIR) ;fi + if [ -d $(SERVICE_DIR) ]; then cp -r $(SERVICE_DIR)/* $(INSTALL_SERVICE_DIR) ;fi + @if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi +clean: + rm -rf $(SUB_BUILD_DIR) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/Makefile new file mode 100644 index 000000000000..9eac041a3a40 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/Makefile @@ -0,0 +1,26 @@ +pes_parent_dir:=$(shell pwd)/$(lastword $(MAKEFILE_LIST)) +pes_parent_dir:=$(shell dirname $(pes_parent_dir)) + +SUBDIRS=$(shell ls -l | grep ^d | awk '{if($$9 != "build") print $$9}') +INC = -I./inc + +COMMON_OUT_PUT := $(shell pwd)/build +common_out_put_dir := $(COMMON_OUT_PUT)/app +common_module_dir := $(COMMON_OUT_PUT)/module/ +export common_out_put_dir common_module_dir + +all : CHECK $(SUBDIRS) +CHECK : + @echo $(pes_parent_dir) + +$(SUBDIRS):ECHO +#������Ŀ¼ + #@echo $@ + make -C $@ + +ECHO: + @echo $(SUBDIRS) + +.PHONY : clean +clean : + -rm -rf $(COMMON_OUT_PUT) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/Makefile new file mode 100644 index 000000000000..f94257fc6715 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/Makefile @@ -0,0 +1,36 @@ +top_srcdir:=$(shell pwd) +#include $(top_srcdir)/Rules.mk +DIR=$(shell pwd) +BUILD_OUTPUT=$(DIR)/tmp +SRCS=$(wildcard *.c) +OBJS=$(patsubst %.c, $(BUILD_OUTPUT)/%.o, $(SRCS)) +DEPS=$(patsubst %.o, %.d, $(OBJS)) +CFLAGS+=-Wall -W -g -I$(DIR)/include +LDFLAGS= +ifdef ENABLE_GCOV +ifeq ($(ENABLE_GCOV), y) +LDFLAGS+= -fprofile-arcs +endif +endif # ENABLE_GCOV +PROGRAM=dfd_debug + +.PHONY: all + +all:$(OBJS) + $(CC) $(OBJS) $(LDFLAGS) -o $(BUILD_OUTPUT)/$(PROGRAM) + @if [ ! -d ${common_out_put_dir} ]; then mkdir -p ${common_out_put_dir} ;fi + cp -p $(BUILD_OUTPUT)/$(PROGRAM) $(common_out_put_dir) + +$(OBJS):$(SRCS) + @if [ ! -d ${BUILD_OUTPUT} ]; then mkdir -p ${BUILD_OUTPUT} ;fi + $(CC) -c $(CFLAGS) $(INCLUDE) $(*F).c -o $@ + +.PHONY: install +install: + @mkdir -p $(common_out_put_dir) + cp -p $(BUILD_OUTPUT)/$(PROGRAM) $(common_out_put_dir) + + +rebuild: clean all +clean: + @rm -rf $(BUILD_OUTPUT)/* \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_debug.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_debug.c new file mode 100644 index 000000000000..bf4032cc3934 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_debug.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "dfd_utest.h" + +int g_dfd_debug_sw = 0; +int g_dfd_debugpp_sw = 0; + + +void dfd_debug_set_init(void) +{ + FILE *fp; + char buf[10]; + + memset(buf, 0, sizeof(buf)); + fp = fopen(DFD_DEBUGP_DEBUG_FILE, "r"); + if (fp != NULL) { + /* file exits into debug mode */ + g_dfd_debug_sw = 1; + fclose(fp); + } + + fp = fopen(DFD_DEBUGPP_DEBUG_FILE, "r"); + if (fp != NULL) { + /* file exits into debug mode */ + g_dfd_debugpp_sw = 1; + fclose(fp); + } + + return; +} + + + +int main(int argc, char* argv[]) +{ + dfd_debug_set_init(); + dfd_utest_cmd_main(argc, argv); + + return 0; +} \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.c new file mode 100644 index 000000000000..aa6fa5575df5 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.c @@ -0,0 +1,1219 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dfd_utest.h" + +#define DFD_UTEST_MAX_RD_NUM (256) +#define DFD_UTEST_MAX_WR_NUM (1) + +#define DEV_MEM_NAME "/dev/mem" +#define DEV_KMEM_NAME "/dev/kmem" + +/* configuration item name */ +#ifdef DFD_UTEST_ITEM +#undef DFD_UTEST_ITEM +#endif +#define DFD_UTEST_ITEM(_id, _type_str, _help_info, _help_info_detail) {_id, #_type_str, dfd_utest_##_type_str, _help_info, _help_info_detail}, +static dfd_utest_t g_dfd_unit_test[] = { + DFD_UTEST_ITEM_ALL +}; + +static int g_sys_page_size; +#define SYS_PAGE_SIZE g_sys_page_size +#define SYS_PAGE_MASK (~(SYS_PAGE_SIZE - 1)) + +void dfd_utest_print_cmd(int argc, char* argv[]) +{ + int i; + + for (i = 1; i < argc; i++) { + if (i != 1) { + printf(" "); + } + printf("%s", argv[i]); + } + return; +} + +void dfd_utest_print_all_help(void) +{ + int i, tbl_size; + + tbl_size = sizeof(g_dfd_unit_test) / sizeof(g_dfd_unit_test[0]); + + for (i = 0; i < tbl_size; i++) { + printf("%-20s\t\t\t%s\r\n", g_dfd_unit_test[i].type_str, g_dfd_unit_test[i].help_info); + } + + return; +} + +void dfd_utest_printf_single_help(int utest_type) +{ + int i, tbl_size; + + tbl_size = sizeof(g_dfd_unit_test) / sizeof(g_dfd_unit_test[0]); + for (i = 0; i < tbl_size; i++) { + if (g_dfd_unit_test[i].utest_type == utest_type) { + printf("%-20s\t\t\t%s\r\n", g_dfd_unit_test[i].type_str, g_dfd_unit_test[i].help_info_detail); + return; + } + } + + DFD_DEBUG_DBG("type: %d not match.\n", utest_type); + return; + +} + + +void dfd_utest_printf_reg(uint8_t *buf, int buf_len, uint16_t offset_addr) +{ + int i, j, tmp; + + j = offset_addr % 16; + tmp = j; + offset_addr -= j; + printf("\n "); + + for (i = 0; i < 16; i++) { + printf("%2x ", i); + } + + for (i = 0; i < buf_len + j; i++) { + if ((i % 16) == 0) { + printf("\n0x%08x ", offset_addr); + offset_addr = offset_addr + 16; + } + if (tmp) { + printf(" "); + tmp--; + } else { + printf("%02x ", buf[i-j]); + } + } + + printf("\n"); + return; +} + +#define I2C_RETRIES 0x0701 +#define I2C_TIMEOUT 0x0702 +#define I2C_RDWR 0x0707 + +#define I2C_SLAVE 0x0703 /* Use this slave address */ + +#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it + is already in use by a driver! */ +#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ +#define I2C_SMBUS 0x0720 /* SMBus transfer */ + +struct i2c_msg +{ + unsigned short addr; + unsigned short flags; +#define I2C_M_TEN 0x0010 +#define I2C_M_RD 0x0001 + unsigned short len; + unsigned char *buf; +}; + +struct i2c_rdwr_ioctl_data +{ + struct i2c_msg *msgs; + int nmsgs; /* The number of nmsgs determines how many start signals there are. + For "single start timing", take 1 */ +}; + +#define DFD_I2C_SHORT_ADDR_TYPE 0 +#define DFD_I2C_RETRY_SLEEP_TIME (10000) /* 10ms */ +#define DFD_I2C_RETRY_TIME (50000 / DFD_I2C_RETRY_SLEEP_TIME) /* 50ms */ +/* i2c_smbus_xfer read or write markers */ +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +/* SMBus transaction types (size parameter in the above functions) + Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 +#define I2C_SMBUS_PROC_CALL 4 +#define I2C_SMBUS_BLOCK_DATA 5 +#define I2C_SMBUS_I2C_BLOCK_BROKEN 6 +#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ +#define I2C_SMBUS_I2C_BLOCK_DATA 8 + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,36) +/* fix tjm */ + +#ifndef __ASSEMBLY__ +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +typedef __signed__ long __s64; +typedef unsigned long __u64; + +#endif /* __ASSEMBLY__ */ + +#else +/* do noting add tjm */ +#endif + + +/* + * Data for SMBus Messages + */ +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ +union i2c_smbus_data { + __u8 byte; + __u16 word; + __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ + /* and one more for user-space compatibility */ +}; + +/* This is the structure as used in the I2C_SMBUS ioctl call */ +struct i2c_smbus_ioctl_data { + __u8 read_write; + __u8 command; + __u32 size; + union i2c_smbus_data *data; +}; +int32_t dfd_read_port_i2c_one_time_smbus(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr, + uint8_t *recv_buf, int32_t size, int addr_type) +{ + union i2c_smbus_data data; + struct i2c_smbus_ioctl_data ioctl_data; + unsigned long addr = dev_addr; + int fd; + int rc; + int rv; + int i; + + memset(&ioctl_data, 0, sizeof(struct i2c_smbus_ioctl_data)); + if (i2c_name == NULL || recv_buf == NULL) { + DFD_DEBUG_ERROR("i2c_num = NULL, recv_buf = NULL\r\n"); + return -1; + } + + DFD_DEBUG_DBG("i2c name: %s, dev_addr: 0x%x, offset_addr: 0x%x, size: %d, addr_type: %d.\n", i2c_name, dev_addr, + offset_addr, size, addr_type); + + rv = 0; + fd = open(i2c_name, O_RDWR | O_SYNC); + if (fd < 0) { + DFD_DEBUG_ERROR("i2c open fail fd %d\n", fd); + rv = fd; + goto err; + } + if (ioctl(fd, I2C_SLAVE_FORCE , addr) < 0) { + DFD_DEBUG_ERROR("ioctl 2C_SLAVE_FORCE %d.\n", errno); + rv =-1; + goto fail; + } + for (i = 0 ;i < size; i++) { + data.byte = 0; + ioctl_data.read_write = I2C_SMBUS_READ; + ioctl_data.command = (offset_addr + i); + ioctl_data.size = I2C_SMBUS_BYTE_DATA; + ioctl_data.data= &data; + + rc = ioctl(fd, I2C_SMBUS, &ioctl_data); + if (rc < 0) { + DFD_DEBUG_ERROR("read, I2C_SMBUS failed: %d.\n", errno); + rv = -1; + goto fail; + } + *(recv_buf + i) = data.byte; + } + fail: + close(fd); + err: + return rv; + +} + +/** + * dfd_read_port_i2c_one_time - read i2c + * @i2c_name: i2c device name + * @dev_addr: device address + * @offset_addr: offset address + * @recv_buf: read buffer + * @size: the size of read buf + * @addr_type: 0:single byte offset access 1:2 byte offset access + * + * return: return 0 or positive value on success,return negative vlaue on failure + */ +int32_t dfd_read_port_i2c_one_time(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr, + uint8_t *recv_buf, int32_t size, int addr_type) +{ + + int32_t fd, rv; + struct i2c_rdwr_ioctl_data ioctl_data; + struct i2c_msg msgs[2]; + uint8_t buf[2]; + + if (i2c_name == NULL || recv_buf == NULL) { + DFD_DEBUG_ERROR("i2c_num = NULL, recv_buf = NULL\r\n"); + return -1; + } + + DFD_DEBUG_DBG("i2c name %s, dev_addr 0x%x, offset_addr 0x%x, size %d, addr_type %d.\n", i2c_name, dev_addr, + offset_addr, size, addr_type); + + rv = 0; + fd = open(i2c_name, O_RDWR | O_SYNC); + if (fd < 0) { + DFD_DEBUG_ERROR("i2c open fail fd %d\n", fd); + return -1; + } + memset(&ioctl_data, 0, sizeof(ioctl_data)); + memset(msgs, 0, sizeof(msgs)); + memset(buf, 0, sizeof(buf)); + if (ioctl(fd, I2C_SLAVE, dev_addr) < 0) { + /* open failed */ + DFD_DEBUG_ERROR("%s %dioctl fail(ret:%d, errno:%s)!\r\n", __func__ , __LINE__, rv, strerror(errno)); + rv = -1; + goto fail; + } + + buf[0] = (uint8_t)(offset_addr); + msgs[0].addr= dev_addr; + msgs[0].len= 2; + msgs[0].buf= buf; + msgs[1].addr= dev_addr; + msgs[1].flags|= I2C_M_RD; + msgs[1].len= 1; + msgs[1].buf= recv_buf; + ioctl_data.nmsgs= 1; + ioctl_data.msgs= msgs; + + rv = ioctl(fd, I2C_RDWR, &ioctl_data); + if(rv < 0) { + DFD_DEBUG_ERROR("%s %dioctl fail(ret:%d, errno:%s)!\r\n", __func__ , __LINE__, rv, strerror(errno)); + goto fail; + } + ioctl_data.msgs= &msgs[1]; + DFD_DEBUG_DBG("ioctlread, return :%d/n", ioctl(fd, I2C_RDWR, &ioctl_data)); + DFD_DEBUG_DBG("dfd_read_port_i2c addr: 0x%X, offset: 0x%X, value: 0x%X\n", dev_addr, offset_addr, *recv_buf); + fail: + close(fd); + return rv; + + +} + +/** + * dfd_read_port_i2c - read i2c + * @i2c_name: i2c device name + * @dev_addr: device address + * @offset_addr: offset address + * @recv_buf: read buffer + * @size: the size of read buf + * + * return: return 0 or positive value on success,return negative value on failure + */ +int32_t dfd_read_port_i2c(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr, + uint8_t *recv_buf, int32_t size) +{ + int i; + int rv; + + for (i = 0; i < DFD_I2C_RETRY_TIME; i++) { + rv = dfd_read_port_i2c_one_time_smbus(i2c_name, dev_addr, offset_addr, recv_buf, size, DFD_I2C_SHORT_ADDR_TYPE); + if (rv < 0) { + DFD_DEBUG_ERROR("(read times %d)i2c name %s, dev_addr 0x%X, offset_addr 0x%X, addr_type %d\n", i, i2c_name, dev_addr, offset_addr, DFD_I2C_SHORT_ADDR_TYPE); + usleep(DFD_I2C_RETRY_SLEEP_TIME); + continue; + } + break; + } + + return rv; +} + +/** + * dfd_write_port_i2c_one_time - read i2c + * @i2c_name: i2c device name + * @dev_addr: device address + * @offset_addr: offset address + * @write_buf: write buffer + * @size: the size of read buf + * @addr_type: 0:single byte offset access 1:2 byte offset access + * + * return: return 0 or positive value on success,return negative value on failure + */ +int32_t dfd_write_port_i2c_one_time(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr, + uint8_t *write_buf, int32_t size,int addr_type) +{ + int32_t fd, rv; + int index; + struct i2c_smbus_ioctl_data ioctl_data; + union i2c_smbus_data data; + uint8_t addr_buf[2]; + uint8_t write_buf_tmp[256]; + + if (i2c_name == NULL || write_buf == NULL ) { + DFD_DEBUG_ERROR("i2c_num = NULL \r\n"); + return -1; + } + + if (size <= 0) { + DFD_DEBUG_ERROR("error:size\n"); + return -1; + } + DFD_DEBUG_DBG("i2c name %s, dev_addr 0x%x, offset_addr 0x%x, size %d, addr_type %d\n",i2c_name, dev_addr, + offset_addr, size, addr_type); + memset(&ioctl_data, 0, sizeof(ioctl_data)); + memset(addr_buf, 0, sizeof(addr_buf)); + memset(write_buf_tmp, 0, sizeof(write_buf_tmp)); + + /* Open the character device, that is, open the channel */ + rv = 0; + + fd = open(i2c_name, O_RDWR | O_SYNC); + if (fd < 0) { + DFD_DEBUG_ERROR("i2c open fail fd %d\n", fd); + return -1; + } + + if (ioctl(fd, I2C_SLAVE_FORCE, dev_addr) < 0) { + DFD_DEBUG_ERROR("ioctl, I2C_SLAVE failed: %d.\n", errno); + rv = -1; + goto fail; + } + + for (index = 0; index < size; index++) { + data.byte = *(write_buf + index); + ioctl_data.read_write = I2C_SMBUS_WRITE; + ioctl_data.command = (offset_addr + index); + ioctl_data.size = I2C_SMBUS_BYTE_DATA; + ioctl_data.data= &data; + rv = ioctl(fd, I2C_SMBUS, (unsigned long)&ioctl_data); + if(rv < 0) { + DFD_DEBUG_ERROR("ioctl fail(ret:%d, errno:%s %d) !\r\n", rv, strerror(errno),errno); + break; + } + DFD_DEBUG_DBG("ret:%d value:0x%02x\n", rv, data.byte); + usleep(5000); /* SMBUS will fail to write multiple bytes without delay, here the delay is 5ms (experience value) */ + } + +fail: + close(fd); + return rv; +} + +/** + * dfd_write_port_i2c - write i2c + * @i2c_name: i2c device name + * @dev_addr: device address + * @offset_addr: offset address + * @write_buf: write buffer + * @size: the size of read buf + * + * return: return 0 or positive value on success,return negative value on failure + */ +int32_t dfd_write_port_i2c(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr, + uint8_t *write_buf, int32_t size) +{ + int i; + int rv; + + for (i = 0; i < DFD_I2C_RETRY_TIME; i++) { + rv = dfd_write_port_i2c_one_time(i2c_name, dev_addr, offset_addr, write_buf,size, DFD_I2C_SHORT_ADDR_TYPE); + if (rv < 0) { + DFD_DEBUG_ERROR("(write times %d)i2c name %s, dev_addr 0x%X, offset_addr 0x%X, addr_type %d\n", + i, i2c_name, dev_addr, offset_addr, DFD_I2C_SHORT_ADDR_TYPE); + usleep(DFD_I2C_RETRY_SLEEP_TIME); + continue; + } + break; + } + + return rv; +} + +static int dfd_read_io_port(uint16_t offset_addr, uint8_t *recv_buf, int32_t size) +{ + int fd; + int ret; + + fd = open("/dev/port", O_RDWR); + if (fd < 0) { + printf("open failed ret %d.\n", fd); + return -1; + } + + ret = lseek(fd, offset_addr, SEEK_SET); + if (ret < 0) { + printf("lseek failed ret %d.\n", ret); + goto exit; + } + + ret = read(fd, recv_buf, size); + if (ret != size) { + printf("read failed ret %d size %d.\n", ret, size); + ret = -1; + goto exit; + } + +exit: + close(fd); + return ret; +} + +static int dfd_write_io_port(uint16_t offset_addr, uint8_t *write_buf, int32_t size) +{ + int fd; + int ret; + + fd = open("/dev/port", O_RDWR); + if (fd < 0) { + printf("open failed ret %d.\n", fd); + return -1; + } + + ret = lseek(fd, offset_addr, SEEK_SET); + if (ret < 0) { + printf("lseek failed ret %d.\n", ret); + goto exit; + } + + ret = write(fd, write_buf, size); + if (ret != size) { + printf("write failed ret %d size %d.\n", ret, size); + ret = -1; + goto exit; + } + +exit: + close(fd); + return ret; +} + +static int dfd_process_mem(char *dev_name, char is_wr, char width, off_t offset, uint8_t *buf, int32_t size) +{ + int mfd, ret = 0; + void *base; + int i, j; + unsigned int val; + off_t map_offset; + size_t map_size; + + /* only support 1/2/4 byte unit read and write */ + if (size & (width - 1)) { + printf("size %d invalid.\n", size); + return -1; + } + + mfd = open(dev_name, O_RDWR); + if (mfd < 0) { + printf("Cannot open %s.\n", dev_name); + return -1; + } + + g_sys_page_size = getpagesize(); + map_offset = offset & SYS_PAGE_MASK; + map_size = size + offset - map_offset; + base = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, map_offset); + if (base == MAP_FAILED) { + printf("mmap offset 0x%lx failed error(%s).\n", map_offset, strerror(errno)); + close(mfd); + return -1; + } + printf("width %d map_offset 0x%lx, offset 0x%lx, mmap base %p, g_sys_page_size %d\n", + width, map_offset, offset, base, g_sys_page_size); + + if (is_wr) { + for (i = 0; i < size; i = i + width) { + val = 0; + for (j = 0; j < width; j++) { + val |= buf[i + j] << (8 * j); + } + switch (width) { + case 1: + *((volatile unsigned char*)(base + i + offset - map_offset)) = val; + break; + case 2: + *((volatile unsigned short*)(base + i + offset - map_offset)) = val; + break; + case 4: + *((volatile unsigned int*)(base + i + offset - map_offset)) = val; + break; + default: + ret = -1; + printf("Not support width %d.\n", width); + goto exit; + } + } + } else { + for (i = 0; i < size; i = i + width) { + switch (width) { + case 1: + val = *((volatile unsigned char*)(base + i + offset - map_offset)); + break; + case 2: + val = *((volatile unsigned short*)(base + i + offset - map_offset)); + break; + case 4: + val = *((volatile unsigned int*)(base + i + offset - map_offset)); + break; + default: + ret = -1; + printf("Not support width %d.\n", width); + goto exit; + } + for (j = 0; j < width; j++) { + buf[i + j] = (val >> (8 * j)) & 0xff; + } + } + } +exit: + munmap(base, map_size); + close(mfd); + return ret; +} + +int dfd_utest_i2c_rd(int argc, char* argv[]) +{ + int ret; + uint8_t value[DFD_UTEST_MAX_RD_NUM]; + uint16_t dev_addr, offset_addr; + char *stopstring; + int num, i2c_bus; + char i2c_path[32]; + + if (argc != 6) { + DFD_DEBUG_ERROR("params error\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_RD); + goto exit; + } + + i2c_bus = strtol(argv[2], &stopstring, 10); + dev_addr = strtol(argv[3], &stopstring, 16); + offset_addr = strtol(argv[4], &stopstring, 16); + num = strtol(argv[5], &stopstring, 10); + + if (num > DFD_UTEST_MAX_RD_NUM) { + DFD_DEBUG_ERROR("Input num %d exceed max.\n", num); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_RD); + goto exit; + } + + dfd_utest_print_cmd(argc, argv); + printf(":\n"); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus); + ret = dfd_read_port_i2c(i2c_path, dev_addr, offset_addr, value, num); + if (ret < 0) { + printf("failed ret %d\n", ret); + goto exit; + } + + dfd_utest_printf_reg(value, num, offset_addr); + +exit: + return DFD_RV_MODE_NOTSUPPORT; + +} + +int dfd_utest_i2c_wr(int argc, char* argv[]) +{ + int ret; + uint16_t dev_addr, offset_addr; + char *stopstring; + int i2c_bus; + char i2c_path[32]; + uint8_t wr_len,i; + uint8_t wr_value[DFD_UTEST_MAX_RD_NUM]; + + if (argc < 6) { + DFD_DEBUG_ERROR("Input invalid.\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_WR); + goto exit; + } + + wr_len = argc - 5; + i2c_bus = strtol(argv[2], &stopstring, 10); + dev_addr = strtol(argv[3], &stopstring, 16); + offset_addr = strtol(argv[4], &stopstring, 16); + + for (i = 0; i < wr_len; i++) { + wr_value[i] = strtol(argv[5+i], &stopstring, 16); + DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]); + } + + dfd_utest_print_cmd(argc, argv); + + printf(":\n"); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus); + + ret = dfd_write_port_i2c(i2c_path, dev_addr, offset_addr, wr_value, wr_len); + if (ret < 0) { + printf("failed ret %d\n", ret); + } else { + printf("success\n"); + } +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +int dfd_utest_io_rd(int argc, char* argv[]) +{ + int ret; + uint8_t value[DFD_UTEST_MAX_RD_NUM]; + uint16_t offset_addr; + char *stopstring; + int num; + + if (argc != 4) { + DFD_DEBUG_ERROR("params error\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_RD); + goto exit; + } + + offset_addr = strtol(argv[2], &stopstring, 16); + num = strtol(argv[3], &stopstring, 10); + + if (num > DFD_UTEST_MAX_RD_NUM) { + DFD_DEBUG_ERROR("Input num %d exceed max.\n", num); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_RD); + goto exit; + } + + dfd_utest_print_cmd(argc, argv); + printf(":\n"); + ret = dfd_read_io_port(offset_addr, value, num); + if (ret < 0) { + printf("failed ret %d\n", ret); + goto exit; + } + + dfd_utest_printf_reg(value, num, offset_addr); + +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +int dfd_utest_io_wr(int argc, char* argv[]) +{ + int ret; + uint16_t offset_addr; + char *stopstring; + int32_t wr_len,i; + uint8_t wr_value[DFD_UTEST_MAX_RD_NUM]; + + if (argc < 4) { + DFD_DEBUG_ERROR("Input invalid.\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_WR); + goto exit; + } + + wr_len = argc - 3; + if (wr_len > DFD_UTEST_MAX_RD_NUM) { + DFD_DEBUG_ERROR("Input num %d exceed max.\n", wr_len); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_WR); + goto exit; + } + + offset_addr = strtol(argv[2], &stopstring, 16); + + for (i = 0; i < wr_len; i++) { + wr_value[i] = strtol(argv[3 + i], &stopstring, 16); + DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]); + } + + dfd_utest_print_cmd(argc, argv); + + printf(":\n"); + ret = dfd_write_io_port(offset_addr, wr_value, wr_len); + if (ret < 0) { + printf("failed ret %d\n", ret); + } else { + printf("success\n"); + } +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +int dfd_utest_phymem_rd(int argc, char* argv[]) +{ + int ret, width; + uint8_t value[DFD_UTEST_MAX_RD_NUM]; + off_t offset_addr; + char *stopstring; + int num; + + if (argc != 5) { + DFD_DEBUG_ERROR("params error\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_RD); + goto exit; + } + + width = strtol(argv[2], &stopstring, 10); + offset_addr = strtol(argv[3], &stopstring, 16); + num = strtol(argv[4], &stopstring, 10); + + if (num > DFD_UTEST_MAX_RD_NUM) { + DFD_DEBUG_ERROR("Input num %d exceed max.\n", num); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_RD); + goto exit; + } + + dfd_utest_print_cmd(argc, argv); + printf(":\n"); + ret = dfd_process_mem(DEV_MEM_NAME, 0, width, offset_addr, value, num); + if (ret < 0) { + printf("failed ret %d\n", ret); + goto exit; + } + + dfd_utest_printf_reg(value, num, offset_addr); + +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +int dfd_utest_phymem_wr(int argc, char* argv[]) +{ + int ret, width; + off_t offset_addr; + char *stopstring; + int32_t wr_len,i; + uint8_t wr_value[DFD_UTEST_MAX_RD_NUM]; + + if (argc < 5) { + DFD_DEBUG_ERROR("Input invalid.\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_WR); + goto exit; + } + + wr_len = argc - 4; + if (wr_len > DFD_UTEST_MAX_RD_NUM) { + DFD_DEBUG_ERROR("Input num %d exceed max.\n", wr_len); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_WR); + goto exit; + } + + width = strtol(argv[2], &stopstring, 10); + offset_addr = strtol(argv[3], &stopstring, 16); + + for (i = 0; i < wr_len; i++) { + wr_value[i] = strtol(argv[4 + i], &stopstring, 16); + DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]); + } + + dfd_utest_print_cmd(argc, argv); + + printf(":\n"); + ret = dfd_process_mem(DEV_MEM_NAME, 1, width, offset_addr, wr_value, wr_len); + if (ret < 0) { + printf("failed ret %d\n", ret); + } else { + printf("success\n"); + } +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +int dfd_utest_kmem_rd(int argc, char* argv[]) +{ + int ret, width; + uint8_t value[DFD_UTEST_MAX_RD_NUM]; + uint16_t offset_addr; + char *stopstring; + int num; + + if (argc != 5) { + DFD_DEBUG_ERROR("params error\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_RD); + goto exit; + } + + width = strtol(argv[2], &stopstring, 10); + offset_addr = strtol(argv[3], &stopstring, 16); + num = strtol(argv[4], &stopstring, 10); + + if (num > DFD_UTEST_MAX_RD_NUM) { + DFD_DEBUG_ERROR("Input num %d exceed max.\n", num); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_RD); + goto exit; + } + + dfd_utest_print_cmd(argc, argv); + printf(":\n"); + ret = dfd_process_mem(DEV_KMEM_NAME, 0, width, offset_addr, value, num); + if (ret < 0) { + printf("failed ret %d\n", ret); + goto exit; + } + + dfd_utest_printf_reg(value, num, offset_addr); + +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +int dfd_utest_kmem_wr(int argc, char* argv[]) +{ + int ret; + uint16_t offset_addr, width; + char *stopstring; + int32_t wr_len,i; + uint8_t wr_value[DFD_UTEST_MAX_RD_NUM]; + + if (argc < 5) { + DFD_DEBUG_ERROR("Input invalid.\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_WR); + goto exit; + } + + wr_len = argc - 4; + if (wr_len > DFD_UTEST_MAX_RD_NUM) { + DFD_DEBUG_ERROR("Input num %d exceed max.\n", wr_len); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_WR); + goto exit; + } + + width = strtol(argv[2], &stopstring, 10); + offset_addr = strtol(argv[3], &stopstring, 16); + + for (i = 0; i < wr_len; i++) { + wr_value[i] = strtol(argv[4 + i], &stopstring, 16); + DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]); + } + + dfd_utest_print_cmd(argc, argv); + + printf(":\n"); + ret = dfd_process_mem(DEV_KMEM_NAME, 1, width, offset_addr, wr_value, wr_len); + if (ret < 0) { + printf("failed ret %d\n", ret); + } else { + printf("success\n"); + } +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +static unsigned long dfd_utest_get_file_size(const char *path) +{ + unsigned long filesize; + struct stat statbuff; + + if (stat(path, &statbuff) < 0) { + filesize = -1; + } else { + filesize = statbuff.st_size; + } + + return filesize; +} + + +int dfd_utest_i2c_file_wr(int argc, char* argv[]) +{ + int ret; + uint16_t dev_addr, offset_addr; + char *stopstring; + int i2c_bus; + char i2c_path[32]; + char *file_name; + unsigned long filesize; + int fd; + uint8_t wr_buf[DFD_UTEST_MAX_RD_NUM]; + int len; + int bpt; /* byte per times*/ + int page_left; + + if (argc != 7) { + printf("Input invalid.\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_FILE_WR); + goto exit; + } + + i2c_bus = strtol(argv[2], &stopstring, 10); + dev_addr = strtol(argv[3], &stopstring, 16); + offset_addr = strtol(argv[4], &stopstring, 16); + bpt = strtol(argv[5], &stopstring, 10); + file_name = argv[6]; + + if ((bpt <= 0) || (bpt > DFD_UTEST_MAX_RD_NUM)) { + bpt = DFD_UTEST_MAX_RD_NUM; + } + + if ((bpt & (bpt - 1)) != 0) { + printf("Bytes per times %d isn't power of two.\n",bpt); + goto exit; + } + + filesize = dfd_utest_get_file_size(file_name); + if (filesize <= 0) { + printf("Input invalid file %s, filesize %lu.\n", file_name, filesize); + goto exit; + } + + fd = open(file_name, O_RDONLY); + if (fd < 0) { + printf("open file[%s] fail.\n", file_name); + goto exit; + } + + dfd_utest_print_cmd(argc, argv); + + printf(":\n"); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus); + + while (filesize > 0) { + memset(wr_buf, 0, DFD_UTEST_MAX_RD_NUM); + len = bpt; + if (offset_addr & (bpt - 1)) { + page_left = bpt - (offset_addr & (bpt - 1)); + len = len > page_left ? page_left : len; + } + + len = read(fd, wr_buf, len); + + ret = dfd_write_port_i2c(i2c_path, dev_addr, offset_addr, wr_buf, len); + if (ret < 0) { + break; + } + offset_addr += len; + filesize -= len; + } + + close(fd); + + if (ret < 0) { + printf("failed ret %d\n", ret); + } else { + printf("success\n"); + } + +exit: + return DFD_RV_MODE_NOTSUPPORT; + +} + +int dfd_utest_sysfs_file_wr(int argc, char* argv[]) +{ + int ret = 0; + uint16_t offset_addr; + char *file_name; + char *sysfs_loc; + char *stopstring; + unsigned long filesize; + int fd, file_fd; + uint8_t wr_buf[DFD_UTEST_MAX_WR_NUM]; + int len, write_len;; + int i; + + + if (argc != 5) { + printf("Input invalid.\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_SYSFS_FILE_WR); + goto exit; + } + + sysfs_loc = argv[2]; + offset_addr = strtol(argv[3], &stopstring, 16); + file_name = argv[4]; + + filesize = dfd_utest_get_file_size(file_name); + if (filesize <= 0) { + printf("Input invalid file %s, filesize %lu.\n", file_name, filesize); + goto exit; + } + + file_fd = open(file_name, O_RDONLY); + if (file_fd < 0) { + printf("open file[%s] fail.\n", file_name); + goto exit; + } + + fd = open(sysfs_loc, O_RDWR | O_SYNC); + if (fd < 0) { + printf("open file[%s] fail.\n", sysfs_loc); + goto open_dev_err; + } + dfd_utest_print_cmd(argc, argv); + + ret = lseek(fd, offset_addr, SEEK_SET); + if (ret < 0) { + printf("lseek file[%s offset=%d] fail,\n", sysfs_loc, offset_addr); + goto fail; + } + + printf(":\n"); + + while (filesize > 0) { + if (filesize > DFD_UTEST_MAX_WR_NUM) { + len = DFD_UTEST_MAX_WR_NUM; + } else { + len = filesize; + } + + memset(wr_buf, 0, DFD_UTEST_MAX_WR_NUM); + len = read(file_fd, wr_buf, len); + for (i = 0; i < DFD_I2C_RETRY_TIME; i++) { + write_len = write(fd, wr_buf, len); + if (write_len != len) { + DFD_DEBUG_ERROR("write file[%s] fail,offset = 0x%x retrytimes = %d len = %d,write_len =%d\n", sysfs_loc, offset_addr, i ,len, write_len); + usleep(DFD_I2C_RETRY_SLEEP_TIME); + continue; + } + break; + } + + if(i == DFD_I2C_RETRY_TIME) { + printf("write file[%s] fail, offset = 0x%x, len = %d,write_len =%d\n", sysfs_loc, offset_addr, len, write_len); + ret = -1; + goto fail; + } + offset_addr += len; + filesize -= len; + usleep(5000); + } + + printf("success\n"); + close(file_fd); + close(fd); + return DFD_RV_OK; + +fail: + close(file_fd); +open_dev_err: + close(fd); +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +int dfd_utest_sysfs_file_rd(int argc, char* argv[]) +{ + int ret = 0; + uint16_t offset_addr; + char *sysfs_loc; + char *stopstring; + int fd; + uint8_t rd_buf[DFD_UTEST_MAX_RD_NUM]; + int len, read_len;; + + + if (argc != 5) { + printf("Input invalid.\n"); + dfd_utest_printf_single_help(DFD_UTEST_ITEM_SYSFS_FILE_RD); + goto exit; + } + + sysfs_loc = argv[2]; + offset_addr = strtol(argv[3], &stopstring, 16); + len = strtol(argv[4], &stopstring, 10); + + if (len > DFD_UTEST_MAX_RD_NUM) { + printf("Input num %d exceed max 256.\n", len); + goto exit; + } + + fd = open(sysfs_loc, O_RDONLY); + if (fd < 0) { + printf("open file[%s] fail.\n", sysfs_loc); + goto exit; + } + dfd_utest_print_cmd(argc, argv); + + printf(":\n"); + + ret = lseek(fd, offset_addr, SEEK_SET); + if (ret < 0) { + printf("lseek failed ret %d.\n", ret); + goto fail; + } + + memset(rd_buf, 0, DFD_UTEST_MAX_RD_NUM); + read_len = read(fd, rd_buf, len); + if (read_len != len) { + printf("read failed read_len %d len %d.\n", read_len, len); + goto fail; + } + dfd_utest_printf_reg(rd_buf, read_len, offset_addr); + close(fd); + return DFD_RV_OK; + +fail: + close(fd); +exit: + return DFD_RV_MODE_NOTSUPPORT; +} + +dfd_utest_proc_fun dfd_utest_get_proc_func(char *type_str) +{ + int i, tbl_size; + + tbl_size = sizeof(g_dfd_unit_test) / sizeof(g_dfd_unit_test[0]); + + for (i = 0; i < tbl_size; i++) { + if (!strncmp(g_dfd_unit_test[i].type_str, type_str, strlen(g_dfd_unit_test[i].type_str))) { + return g_dfd_unit_test[i].utest_func; + } + } + DFD_DEBUG_DBG("type: %s not match.\n", type_str); + return NULL; +} + + +void dfd_utest_cmd_main(int argc, char* argv[]) +{ + char utest_type_str[DFD_UTEST_TYPE_STRING_LEN]; + dfd_utest_proc_fun pfunc; + int ret; + + if (argc < 2) { + dfd_utest_print_all_help(); + return; + } + + pfunc = dfd_utest_get_proc_func(argv[1]); + if (pfunc == NULL) { + DFD_DEBUG_DBG("utest type %s in not support.\n", utest_type_str); + dfd_utest_print_all_help(); + return; + } + ret = pfunc(argc, argv); + if ((ret != DFD_RV_MODE_NOTSUPPORT) && (ret != DFD_RV_INDEX_INVALID)) { + if (ret == DFD_RV_OK) { + DFD_DEBUG_DBG(" [SUCCESS]\n"); + } else { + DFD_DEBUG_DBG(" [FAIL(%d)]\n", ret); + } + } + + return; +} + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.h new file mode 100644 index 000000000000..2ac65d1d6998 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/dev_util/dfd_utest.h @@ -0,0 +1,104 @@ +/* monitor_utest.h */ +#ifndef __DFD_UTEST_H__ +#define __DFD_UTEST_H__ + +extern int g_dfd_debug_sw; +extern int g_dfd_debugpp_sw; + + +#define DFD_UTEST_TRUE_FALSE_STRING(flag) ((flag == true) ? "true" : "false") + +#define DFD_DEBUG_DBG(fmt, args...) do { \ + if (g_dfd_debug_sw) { \ + printf("" fmt,\ + ##args); \ + } \ +} while (0) + +#define DFD_DEBUG_ERROR(fmt, args...) do { \ + if (g_dfd_debugpp_sw) { \ + printf("" fmt,\ + ##args); \ + } \ +} while (0) + + +typedef enum dfd_rv_s { + DFD_RV_OK = 0, + DFD_RV_INIT_ERR = 1, + DFD_RV_SLOT_INVALID = 2, + DFD_RV_MODE_INVALID = 3, + DFD_RV_MODE_NOTSUPPORT = 4, + DFD_RV_TYPE_ERR = 5, + DFD_RV_DEV_NOTSUPPORT = 6, + DFD_RV_DEV_FAIL = 7, + DFD_RV_INDEX_INVALID = 8, + DFD_RV_NO_INTF = 9, + DFD_RV_NO_NODE = 10, + DFD_RV_NODE_FAIL = 11, +} dfd_rv_t; + + + +#define DFD_DEBUG_BUF_LEN (32) +#define DFD_DEBUGP_DEBUG_FILE "/sbin/.dfd_debugp_flag" +#define DFD_DEBUGPP_DEBUG_FILE "/sbin/.dfd_debugpp_flag" + +#define DFD_UTEST_MAX_PARA_NUM (4) +#define DFD_UTEST_TYPE_STRING_LEN (64) +#define DFD_UTEST_MATCH_STRING_LEN (64) +#define DFD_UTEST_HELP_STRING_LEN (256) +#define DFD_UTEST_INVALID_PARA (-1) +#define DFD_UTEST_BUFF_LEN (64) + +typedef enum dfd_fpga_cpld_flag_e { + DFD_CPLD_RW_FLAG = 0x00, + DFD_FPGA_RW_FLAG = 0x01, +} dfd_fpga_cpld_flag_t; + +typedef int (* dfd_utest_proc_fun)(int argc, char* argv[]); + +#define DFD_UTEST_ITEM_ALL \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_RD, i2c_rd, "i2c_rd [i2c_bus] [slave_addr] [offset] [len]", "i2c_rd [i2c_bus] [slave_addr] [offset] [len]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_WR, i2c_wr, "i2c_wr [i2c_bus] [slave_addr] [offset] [data0] ... [dataN]", "i2c_wr [i2c_bus] [slave_addr] [offset] [data0] ... [dataN]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_IO_RD, io_rd, "io_rd [offset] [len]", "io_rd [offset] [len]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_IO_WR, io_wr, "io_wr [offset] [data0]... [dataN]", "io_wr [offset] [data0]... [dataN]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_PHYMEM_RD, phymem_rd, "phymem_rd [bit_width] [offset] [len]", "phymem_rd [bit_width] [offset] [len]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_PHYMEM_WR, phymem_wr, "phymem_wr [bit_width] [offset] [data0]... [dataN]", "phymem_wr [bit_width] [offset] [data0]... [dataN]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_KMEM_RD, kmem_rd, "kmem_rd [bit_width] [offset] [len]", "kmem_rd [bit_width] [offset] [len]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_KMEM_WR, kmem_wr, "kmem_wr [bit_width][offset] [data0]... [dataN]", "kmem_wr [bit_width] [offset] [data0]... [dataN]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_FILE_WR, i2c_file_wr, "i2c_file_wr [i2c_bus] [slave_addr] [offset] [bpt] [filename]", "i2c_file_wr [i2c_bus] [slave_addr] [offset] [bpt] [filename]\nbpt:bytes per times") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_SYSFS_FILE_WR, sysfs_file_wr, "sysfs_file_wr [sysfs_loc] [offset] [filename]", "sysfs_file_wr [sysfs_loc] [offset] [filename]") \ + DFD_UTEST_ITEM(DFD_UTEST_ITEM_SYSFS_FILE_RD, sysfs_file_rd, "sysfs_file_rd [sysfs_loc] [offset] [len]", "sysfs_file_rd [sysfs_loc] [offset] [len]") \ + +/* configuration item id enumeration definition */ +#ifdef DFD_UTEST_ITEM +#undef DFD_UTEST_ITEM +#endif +#define DFD_UTEST_ITEM(_id, _type_str, _help_info, _help_info_detail) _id, +typedef enum dfd_utest_item_id_s { + DFD_UTEST_ITEM_ALL +} dfd_utest_item_id_t; + +typedef struct { + int utest_type; + char type_str[DFD_UTEST_TYPE_STRING_LEN]; + dfd_utest_proc_fun utest_func; + char help_info[DFD_UTEST_HELP_STRING_LEN]; + char help_info_detail[DFD_UTEST_HELP_STRING_LEN]; +} dfd_utest_t; + + +void dfd_utest_cmd_main(int argc, char* argv[]); + +/* function declaration */ +#ifdef DFD_UTEST_ITEM +#undef DFD_UTEST_ITEM +#endif +#define DFD_UTEST_ITEM(_id, _type_str, _help_info, _help_info_detail) int dfd_utest_##_type_str(int argc, char* argv[]); +DFD_UTEST_ITEM_ALL + + +#endif + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Makefile new file mode 100644 index 000000000000..8b6613fedfe2 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Makefile @@ -0,0 +1,24 @@ +top_srcdir:= $(shell pwd) +include $(top_srcdir)/Rules.mk +export top_srcdir + +firmware-y:= +firmware-y += firmware_driver_ispvme +firmware-y += firmware_upgrade_ispvme + +#ifeq ("$(CONFIG_CPLD_UPGRADE_ISPVME)", "y") +#install_cpld_dir:=$(CURDIR)/package_ispvme/$(RAGILE_PRODUCT)/cpld +#endif + +.PHONY: all +all: build + +.PHONY: build +build: $(firmware-y) +$(foreach dir,$(firmware-y),$(eval $(call compile_dirs,$(dir)))) + +.PHONY: rpmpkg +rpmpkg: +ifeq ("$(CONFIG_CPLD_UPGRADE_ISPVME)", "y") + #$(RPMPKG) $(install_cpld_dir) firmware-cpld-ispvme.spec git +endif diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Rules.mk b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Rules.mk new file mode 100644 index 000000000000..e7daa338f06c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/Rules.mk @@ -0,0 +1,54 @@ +CC ?= $(CROSS)gcc +AR ?= $(CROSS)ar +AS ?= $(CROSS)as +LD ?= $(CROSS)ld +STRIP ?= $(CROSS)strip + +# top_srcdir是lsm仓库的顶层目录路径; +# install_root是仓库里的安装目录树 +install_root:=${top_srcdir}/images + +install_header_dir:=${install_root}/header +install_adir:=$(install_root)/lib +install_symbol_dir:=$(install_root)/symbol +# symbol_files是内核模块符号表 +symbol_files:=$(shell find $(EXPORT_SYMBOL) -name 'Module.symvers') +# +# symbol_files += $(shell find $(install_symbol_dir) -name 'Module.symvers') +# 例如, 内核模块B,如果调用了内核模块A(模块A的符号表已导出)的函数,则可在模块B的makefile文件中,声明符号表的位置,使用以下两行语句: +# KBUILD_EXTRA_SYMBOLS += $(symbol_files) +# export KBUILD_EXTRA_SYMBOLS + +# top root: install_rootfs_dir +# install_rootfs_dir是rootfs根文件系统的安装目录树images/rootfs +install_rootfs_dir:=$(install_root)/rootfs + +# install_sodir是动态安装路径 +# 仓库里的组件编译安装so时,makefile的install目标可执行命令cp xx.so $(install_sodir) +install_sodir:=$(install_rootfs_dir)/$(INSTALL_SODIR) + +install_usr_bin_dir:=$(install_rootfs_dir)/usr/bin +# install_sbin_dir是系统应用程序的安装路径 +install_sbin_dir:=$(install_rootfs_dir)/sbin +install_etc_dir:=$(install_rootfs_dir)/etc + +# 内核模块的安装路径 +export INSTALL_MOD_PATH:=$(ROOT) + +# 可以使用BUILD_CFLAGS参数,添加模块目录下自己的头文件搜索路径 +# 可以使用BUILD_LDFLAGS参数,添加模块目录下本仓库内其它组件编译后生成的动态库搜索路径 +BUILD_CFLAGS:=$(CFLAGS) -I$(install_header_dir) +BUILD_LDFLAGS:=$(LDFLAGS) -L/$(install_sodir) -L/$(install_adir) + +define compile_dirs +.PHONY: $(1) +$(1): + @echo;echo "building $(1)..." + @$(MAKE) -C ${1} +endef + +compile.c = $(CC) $(BUILD_CFLAGS) -d -c -o $@ $< +# 例如,应用程序的makefile中,.c编译为.o的规则,可使用以下两行语句: +%.o: %.c + $(compile.c) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware-cpld-ispvme.spec b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware-cpld-ispvme.spec new file mode 100644 index 000000000000..9e0b33404b64 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware-cpld-ispvme.spec @@ -0,0 +1,27 @@ +#ʹ����ȷ�������滻�ļ��а����ַ�'X'�ĵط� + +Summary: Firmware Upgrade Package + +Name: firmware-cpld + +Version: 1.0.0.%patch + +Release: firmware + +License: Ragile + +Group: common + +AutoReqProv: no + +%clean +%description +[common] +%des_name +%des_ver +%des_target + +%files + +%attr(755,root,root) +/* diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/Makefile new file mode 100644 index 000000000000..d159f9955f0e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/Makefile @@ -0,0 +1,27 @@ +#include $(top_srcdir)/debian/rules +#KERNELDIR := ${KBUILD_OUTPUT} + + + +PWD = $(shell pwd) + +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +ifdef ENABLE_GCOV +ifeq ($(ENABLE_GCOV), y) +EXTRA_CFLAGS+= -fprofile-arcs -ftest-coverage -lgcov +endif +endif # ENABLE_GCOV +RAGILE_PRODUCT = b6510-48vs8cq +firmware_driver-objs := firmware_ispvme.o +firmware_driver-objs += firmware_cpld_ispvme.o firmware_cpld_upgrade_ispvme.o + +#ifndef CONFIG_FRM_PRODUCT_FILE + +firmware_driver-objs += $(RAGILE_PRODUCT).o +$(warning $(firmware_driver-objs)) +obj-m := firmware_driver.o +all: + $(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules + @if [ ! -d $(common_module_dir) ]; then mkdir -p $(common_module_dir) ;fi + cp -p $(PWD)/*.ko $(common_module_dir) \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.c new file mode 100644 index 000000000000..1134e0be28f4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.c @@ -0,0 +1,497 @@ +/** + * Copyright(C) 2013 Ragile Network. All rights reserved. + */ +/* + * ca-octeon-cmx.c + * Original Author : support@ragilenetworks.com, 2013-10-25 + * + * ca-octeon-cmx CPLD upgrade driver + * + * History + * v1.0 chenwendai(support@ragilenetworks.com) 2013-10-25 Initial version. + * + */ + +#include +#include +#include +#if 0 +#include +#include +#endif +#include +#include +#include "b6510-48vs8cq.h" + +/* extern void cmic_gpio_set_output_value(int gpio, int val); */ +firmware_device_info_t *current_info = NULL; +static firmware_device_info_t set_gpio_info; +static int set_gpio_info_flag = 0; +firmware_device_info_t default_cpld_info = { + .type = 0, + .tdi = JTAG_TDI, + .tck = JTAG_TCK, + .tms = JTAG_TMS, + .tdo = JTAG_TDO, + .jtag_en = JTAG_EN, + .select = -1, + .cmic_start_gpio = -1, + .cmic_end_gpio = -1, +}; + +firmware_device_info_t as13_cpld_info = { + .type = 0, + .tdi = 67, + .tck = JTAG_TCK, + .tms = JTAG_TMS, + .tdo = 32, + .jtag_en = JTAG_EN, + .select = 48, + .cmic_start_gpio = -1, + .cmic_end_gpio = -1, +}; + +static int firmware_cpld_gpio_is_from_cmic(int gpio) +{ + if (current_info == NULL) { + return -1; + } + + dev_debug(firmware_debug(), "gpio %d current_info.cmic_start_gpio %d current_info.cmic_end_gpio %d.\n", + gpio, current_info->cmic_start_gpio, current_info->cmic_end_gpio); + + if ((current_info->cmic_start_gpio == -1) || (current_info->cmic_end_gpio == -1)) { + return 0; + } + + if ((gpio >= current_info->cmic_start_gpio) && (gpio <= current_info->cmic_end_gpio)) { + return 1; + } + + return 0; +} + +static int firmware_cpld_gpio_get_value(int gpio) +{ +#if 0 + int ret; + + ret = firmware_cpld_gpio_is_from_cmic(gpio); + if (ret < 0) { + dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n", + gpio, ret); + return -1; + } + + if (ret == 1) { + /* Not currently supported */ + dev_debug(firmware_debug(), "gpio %d not support to get value.\n", gpio); + return -1; + } else { + return __gpio_get_value(gpio); + } +#endif + + return __gpio_get_value(gpio); +} + +static void firmware_cpld_gpio_set_output_value(int gpio, int val) +{ +#if 0 + int ret; + + ret = firmware_cpld_gpio_is_from_cmic(gpio); + if (ret < 0) { + dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n", + gpio, ret); + return; + } + + if (ret == 1) { + __gpio_set_value(gpio, val); + /*cmic_gpio_set_output_value(gpio, val);*/ + } else { + __gpio_set_value(gpio, val); + } +#endif + + __gpio_set_value(gpio, val); +} + +static void firmware_cpld_gpio_set_direction(int gpio, int out) +{ + if (out) { + gpio_direction_output(gpio, 1); + } else { + gpio_direction_input(gpio); + } + + return; +} + +static void firmware_cpld_gpio_request(int gpio, char *name) +{ + int ret; + + ret = firmware_cpld_gpio_is_from_cmic(gpio); + if (ret < 0) { + dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n", + gpio, ret); + return; + } + + if (ret == 1) { + /* do nothing */ + } else { + gpio_request(gpio, name); + } + + return; +} + +static void firmware_cpld_gpio_free(int gpio) +{ + int ret; + + ret = firmware_cpld_gpio_is_from_cmic(gpio); + if (ret < 0) { + dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n", + gpio, ret); + return; + } + + if (ret == 1) { + /* do nothing */ + } else { + gpio_free(gpio); + } + + return; +} + + +/* CPLD upgrade initialization operation */ +static int init_cpld(void) +{ + if (current_info == NULL) { + return -1; + } + + firmware_cpld_gpio_request(current_info->tdi, "cpld_upgrade"); + firmware_cpld_gpio_request(current_info->tck, "cpld_upgrade"); + firmware_cpld_gpio_request(current_info->tms, "cpld_upgrade"); + firmware_cpld_gpio_request(current_info->jtag_en, "cpld_upgrade"); + if (current_info->select >= 0) { + firmware_cpld_gpio_request(current_info->select, "cpld_upgrade"); + } + firmware_cpld_gpio_request(current_info->tdo, "cpld_upgrade"); + if (current_info->jtag_4.pin >= 0){ + firmware_cpld_gpio_request(current_info->jtag_1.pin, "cpld_upgrade"); + firmware_cpld_gpio_request(current_info->jtag_2.pin, "cpld_upgrade"); + firmware_cpld_gpio_request(current_info->jtag_3.pin, "cpld_upgrade"); + firmware_cpld_gpio_request(current_info->jtag_4.pin, "cpld_upgrade"); + firmware_cpld_gpio_request(current_info->jtag_5.pin, "cpld_upgrade"); + } + return 0; +} + +/* CPLD upgrade completion operation */ +static int finish_cpld(void) +{ + if (current_info == NULL) { + return -1; + } + + firmware_cpld_gpio_set_output_value(current_info->jtag_en, 0); + if (current_info->select >= 0) { + firmware_cpld_gpio_set_output_value(current_info->select, 0); + } + if (current_info->jtag_4.pin >= 0) { + gpio_direction_input(current_info->jtag_4.pin); + gpio_direction_input(current_info->jtag_1.pin); + gpio_direction_input(current_info->jtag_2.pin); + gpio_direction_input(current_info->jtag_3.pin); + gpio_direction_input(current_info->jtag_5.pin); + } + firmware_cpld_gpio_free(current_info->tdi); + firmware_cpld_gpio_free(current_info->tck); + firmware_cpld_gpio_free(current_info->tms); + firmware_cpld_gpio_free(current_info->jtag_en); + firmware_cpld_gpio_free(current_info->tdo); + if (current_info->jtag_4.pin >= 0) { + firmware_cpld_gpio_free(current_info->jtag_1.pin); + firmware_cpld_gpio_free(current_info->jtag_2.pin); + firmware_cpld_gpio_free(current_info->jtag_3.pin); + firmware_cpld_gpio_free(current_info->jtag_4.pin); + firmware_cpld_gpio_free(current_info->jtag_5.pin); + } + + if (current_info->select >= 0) { + firmware_cpld_gpio_free(current_info->select); + } + + if (set_gpio_info_flag == 1) { + memcpy(current_info, &set_gpio_info, sizeof(firmware_device_info_t)); + set_gpio_info_flag = 0; + } + + dev_debug(firmware_debug(), "%s %d\n", __func__, __LINE__); + + return 0; +} + +static void init_chip_pre(void) +{ + + dev_debug(firmware_debug(), "%s %d\n", __func__, __LINE__); + + /* to be reset every time when upgrade,solve the use of MAC side GPIO, + During the startup process, the MAC terminal will be reset, causing the problem of invalid settings */ + firmware_cpld_gpio_set_direction(current_info->tdi, 1); + firmware_cpld_gpio_set_direction(current_info->tck, 1); + firmware_cpld_gpio_set_direction(current_info->tms, 1); + firmware_cpld_gpio_set_direction(current_info->jtag_en, 1); + if (current_info->select >= 0) { + firmware_cpld_gpio_set_direction(current_info->select, 1); + } + if (current_info->jtag_4.pin >= 0) { + firmware_cpld_gpio_set_direction(current_info->jtag_4.pin, 1); + firmware_cpld_gpio_set_direction(current_info->jtag_3.pin, 1); + firmware_cpld_gpio_set_direction(current_info->jtag_2.pin, 1); + firmware_cpld_gpio_set_direction(current_info->jtag_1.pin, 1); + firmware_cpld_gpio_set_direction(current_info->jtag_5.pin, 1); + } + + firmware_cpld_gpio_set_output_value(current_info->tdi, 1); + firmware_cpld_gpio_set_output_value(current_info->tck, 1); + firmware_cpld_gpio_set_output_value(current_info->tms, 1); + firmware_cpld_gpio_set_output_value(current_info->jtag_en, 1); + if (current_info->jtag_4.pin >= 0) { + firmware_cpld_gpio_set_output_value(current_info->jtag_1.pin, current_info->jtag_1.val); + firmware_cpld_gpio_set_output_value(current_info->jtag_2.pin, current_info->jtag_2.val); + firmware_cpld_gpio_set_output_value(current_info->jtag_3.pin, current_info->jtag_3.val); + firmware_cpld_gpio_set_output_value(current_info->jtag_4.pin, current_info->jtag_4.val); + firmware_cpld_gpio_set_output_value(current_info->jtag_5.pin, current_info->jtag_5.val); + } + if (current_info->select >= 0) { + firmware_cpld_gpio_set_output_value(current_info->select, 1); + } + + firmware_cpld_gpio_set_direction(current_info->tdo, 0); + return; +} + +static int init_chip(int slot) +{ + + dev_debug(firmware_debug(), "%s %d\n", __func__, __LINE__); + + if (current_info == NULL) { + return -1; + } + init_chip_pre(); + + dev_debug(firmware_debug(), "tdi %d %d\n",current_info->tdi, firmware_cpld_gpio_get_value(current_info->tdi)); + dev_debug(firmware_debug(), "tdo %d %d\n",current_info->tdo, firmware_cpld_gpio_get_value(current_info->tdo)); + dev_debug(firmware_debug(), "tck %d %d\n",current_info->tck, firmware_cpld_gpio_get_value(current_info->tck)); + dev_debug(firmware_debug(), "tms %d %d\n",current_info->tms, firmware_cpld_gpio_get_value(current_info->tms)); + dev_debug(firmware_debug(), " jtag_en:%d %d\n",current_info->jtag_en, firmware_cpld_gpio_get_value(current_info->jtag_en)); + if (current_info->select >= 0) { + dev_debug(firmware_debug(), " select:%d %d\n",current_info->select, firmware_cpld_gpio_get_value(current_info->select)); + } + + return 0; +} + + +static int finish_chip(int slot) +{ + if (current_info == NULL) { + return -1; + } + + firmware_cpld_gpio_set_output_value(current_info->jtag_en, 0); + if (current_info->select >= 0) { + firmware_cpld_gpio_set_output_value(current_info->select, 0); + } + if (current_info->jtag_4.pin >= 0) { + firmware_cpld_gpio_set_output_value(current_info->jtag_4.pin, 1); + } + + return 0; +} + +/* TDI pull up */ +static void pull_tdi_up(void) +{ + if (current_info == NULL) { + return; + } + firmware_cpld_gpio_set_output_value(current_info->tdi, 1); +} + +/* TDI pull dowm */ +static void pull_tdi_down(void) +{ + if (current_info == NULL) { + return; + } + firmware_cpld_gpio_set_output_value(current_info->tdi, 0); +} + +/* TCK pull up */ +static void pull_tck_up(void) +{ + if (current_info == NULL) { + return; + } + firmware_cpld_gpio_set_output_value(current_info->tck, 1); +} + +/* TCK pull down */ +static void pull_tck_down(void) +{ + if (current_info == NULL) { + return; + } + firmware_cpld_gpio_set_output_value(current_info->tck, 0); +} + +/* TMS pull up */ +static void pull_tms_up(void) +{ + if (current_info == NULL) { + return; + } + firmware_cpld_gpio_set_output_value(current_info->tms, 1); +} + +/* TCK pull dowm */ +static void pull_tms_down(void) +{ + if (current_info == NULL) { + return; + } + firmware_cpld_gpio_set_output_value(current_info->tms, 0); +} + +/* read TDO */ +static int read_tdo(void) +{ + if (current_info == NULL) { + return -1; + } + return firmware_cpld_gpio_get_value(current_info->tdo); +} + +int B6510_fmw_set_gpio_info(firmware_upg_gpio_info_t *info) +{ + if (info == NULL) { + dev_debug(firmware_debug(), "set gpio info info %p is null.\n", info); + return -1; + } + + set_gpio_info.tdi = info->tdi; + set_gpio_info.tck = info->tck; + set_gpio_info.tms = info->tms; + set_gpio_info.tdo = info->tdo; + set_gpio_info.jtag_en = info->jtag_en; + set_gpio_info.select= info->select; + set_gpio_info.jtag_5.pin = info->jtag_5.pin; + set_gpio_info.jtag_4.pin = info->jtag_4.pin; + set_gpio_info.jtag_3.pin = info->jtag_3.pin; + set_gpio_info.jtag_2.pin = info->jtag_2.pin; + set_gpio_info.jtag_1.pin = info->jtag_1.pin; + set_gpio_info.jtag_5.val = info->jtag_5.val; + set_gpio_info.jtag_4.val = info->jtag_4.val; + set_gpio_info.jtag_3.val = info->jtag_3.val; + set_gpio_info.jtag_2.val = info->jtag_2.val; + set_gpio_info.jtag_1.val = info->jtag_1.val; + set_gpio_info_flag = 1; + dev_debug(firmware_debug(), "set gpio info[tdi:%d tck:%d tms:%d tdo:%d jtag_en:%d select:%d].\n", + info->tdi, info->tck, info->tms, info->tdo, info->jtag_en, info->select); + return 0; +} + +firmware_cpld_t fmw_cpld0 = { + .devname = "firmware_cpld_ispvme0", + .slot = 1, + .chip_index = 1, + .is_used = 1, + .tck_delay = 60, + .pull_tdi_up = pull_tdi_up, + .pull_tdi_down = pull_tdi_down, + .pull_tck_up = pull_tck_up, + .pull_tck_down = pull_tck_down, + .pull_tms_up = pull_tms_up, + .pull_tms_down = pull_tms_down, + .read_tdo = read_tdo, + .init_cpld = init_cpld, + .init_chip = init_chip, + .finish_chip = finish_chip, + .finish_cpld = finish_cpld, + .get_version = NULL, +}; + +static void cpld_release(struct device *dev) +{ + return; +} + + +static struct platform_device cpld = { + .name = "firmware_cpld_ispvme", + .id = 0, + .num_resources = 0, + .dev = { + .release = cpld_release, + } +}; + +extern void set_currrent_cpld_info(firmware_cpld_t *info); +extern int dfd_get_my_card_type(void); + +int fmw_cpld_product_init(void) +{ + current_info = NULL; +#if 0 + int dev_type; + int i; + + dev_type = drv_get_my_dev_type(); + if (dev_type < 0) { + printk(KERN_ERR "Failed to get device type, when upgrade cpld.\n"); + return FIRMWARE_FAILED; + } + + for (i = 0; i < sizeof(cpld_info)/sizeof(cpld_info[0]); i++) { + if (cpld_info[i].type == dev_type) { + current_info = &cpld_info[i]; + printk(KERN_ERR "device type 0x%x match i %d.\n", dev_type, i); + printk(KERN_ERR "tdi[%d] tck[%d] tms[%d] tdo[%d] jtat_en[%d].\n", current_info->tdi, + current_info->tck, current_info->tms, current_info->tdo, current_info->jtag_en); + } + } +#endif + + if (current_info == NULL) { + current_info = &default_cpld_info; + } + + platform_device_register(&cpld); + fmw_cpld_upg_copy_firmware_info(&fmw_cpld0); + + /* fmw_cpld0.init_cpld(); */ + set_currrent_cpld_info(&fmw_cpld0); + + fmw_cpld_reg_gpio_info_set_func(B6510_fmw_set_gpio_info); + + return FIRMWARE_SUCCESS; +} + +void fmw_cpld_product_exit(void) +{ + platform_device_unregister(&cpld); + return; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.h new file mode 100644 index 000000000000..f4893500beab --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/b6510-48vs8cq.h @@ -0,0 +1,29 @@ +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include + +#define JTAG_TDI (32) +#define JTAG_TDO (67) +#define JTAG_TCK (65) +#define JTAG_TMS (6) +#define JTAG_EN (50) + +typedef struct firmware_device_info_s { + int type; + int tdi; + int tck; + int tms; + int tdo; + int jtag_en; + int select; + gpio_group_t jtag_5; + gpio_group_t jtag_4; + gpio_group_t jtag_3; + gpio_group_t jtag_2; + gpio_group_t jtag_1; + int cmic_start_gpio; + int cmic_end_gpio; +} firmware_device_info_t; + +#endif /* __CONFIG_H__ */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_ispvme.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_ispvme.c new file mode 100644 index 000000000000..964054a8dd00 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_ispvme.c @@ -0,0 +1,285 @@ +/** + * Copyright(C) 2013 Ragile Network. All rights reserved. + */ +/* + * firmware_cpld.c + * Original Author : support@ragilenetworks.com, 2013-10-25 + * + * CPLD driver + * + * History + * v1.0 chenwendai(support@ragilenetworks.com) 2013-10-25 Initial version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int firmware_cpld_open(struct inode *inode, struct file *file) +{ + firmware_cpld_t *cpld_info; + firmware_device_t *frm_dev; + + dev_debug(firmware_debug(), "Open cpld device.\n"); + + frm_dev = firmware_get_device_by_minor(FIRMWARE_CPLD, MINOR(inode->i_rdev)); + if (frm_dev == NULL) { + return -ENXIO; + } + + file->private_data = frm_dev; + cpld_info = (firmware_cpld_t *)frm_dev->priv; + + if (cpld_info != NULL && cpld_info->init_cpld) { + cpld_info->init_cpld(); + } + + if (cpld_info != NULL && cpld_info->init_chip) { + cpld_info->init_chip(0); + } + + return FIRMWARE_SUCCESS; +} + +static ssize_t firmware_cpld_read (struct file *file, char __user *buf, size_t count, + loff_t *offset) +{ + return 0; +} + +static ssize_t firmware_cpld_write (struct file *file, const char __user *buf, size_t count, + loff_t *offset) +{ + return 0; +} + +static loff_t firmware_cpld_llseek(struct file *file, loff_t offset, int origin) +{ + return 0; +} + +static long firmware_cpld_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + char value; + void __user *argp; + cmd_info_t cmd_info; + char *buf; + int ret; + + argp = (void __user *)arg; + + switch (cmd) { + case FIRMWARE_JTAG_TDI: + if (copy_from_user(&value, argp, sizeof(value))) { + return -EFAULT; + } + fwm_cpld_tdi_op(value); + break; + case FIRMWARE_JTAG_TCK: + if (copy_from_user(&value, argp, sizeof(value))) { + return -EFAULT; + } + fwm_cpld_tck_op(value); + break; + + case FIRMWARE_JTAG_TMS: + if (copy_from_user(&value, argp, sizeof(value))) { + return -EFAULT; + } + fwm_cpld_tms_op(value); + break; + + case FIRMWARE_JTAG_TDO: + value = fwm_cpld_tdo_op(); + + if (copy_to_user(argp, &value, sizeof(value))) { + return -EFAULT; + } + + break; + + case FIRMWARE_SET_GPIO_INFO: + /* set GPIO information */ + if (copy_from_user(&cmd_info, argp, sizeof(cmd_info_t))) { + return -EFAULT; + } + + buf = (char *) kzalloc(cmd_info.size + 1, GFP_KERNEL); + if (buf == NULL) { + return -ENOMEM; + } + if (copy_from_user(buf, cmd_info.data, cmd_info.size)) { + kfree(buf); + return -EFAULT; + } + + ret = fmw_cpld_set_gpio_info((firmware_upg_gpio_info_t*)buf); + if (ret != FIRMWARE_SUCCESS) { + dev_debug(firmware_debug(), "Failed to set gpio info.\n"); + kfree(buf); + return -ESRCH; + } + + kfree(buf); + break; + + case FIRMWARE_SET_DEBUG_ON: + /* DEBUG ON */ + firmware_set_debug(1); + break; + case FIRMWARE_SET_DEBUG_OFF: + /* DEBUG_OFF */ + firmware_set_debug(0); + break; + + default: + return -ENOTTY; + } + + return FIRMWARE_SUCCESS; +} + +static int firmware_cpld_release(struct inode *inode, struct file *file) +{ + firmware_cpld_t *cpld_info; + firmware_device_t *frm_dev; + + frm_dev = (firmware_device_t *)(file->private_data); + cpld_info = (firmware_cpld_t *)(frm_dev->priv); + + if (cpld_info != NULL && cpld_info->finish_chip) { + cpld_info->finish_chip(0); + } + + if (cpld_info != NULL && cpld_info->finish_cpld) { + cpld_info->finish_cpld(); + } + return 0; +} + +static const struct file_operations cpld_dev_fops = { + .owner = THIS_MODULE, + .llseek = firmware_cpld_llseek, + .read = firmware_cpld_read, + .write = firmware_cpld_write, + .unlocked_ioctl = firmware_cpld_ioctl, + .open = firmware_cpld_open, + .release = firmware_cpld_release, +}; + +static int firmware_cpld_probe(struct platform_device *pdev) +{ + const __be32 *slot; + int len; + int ret; + firmware_cpld_t *cpld_info; + firmware_device_t *frm_dev; + + frm_dev = (firmware_device_t *) kzalloc(sizeof(firmware_device_t), GFP_KERNEL); + if (frm_dev == NULL) { + dev_debug(firmware_debug(), "Failed to kzalloc firmware device.\n"); + return -EPERM; + } + + slot = of_get_property(pdev->dev.of_node, "slot", &len); + if (slot && len == sizeof(*slot)) { + frm_dev->slot = be32_to_cpup(slot); + } else { + frm_dev->slot = firmware_get_device_num(FIRMWARE_CPLD) + 1; + } + + snprintf(frm_dev->name, FIRMWARE_NAME_LEN - 1, "firmware_cpld_ispvme%d", frm_dev->slot - 1); + cpld_info = fmw_cpld_upg_get_cpld(frm_dev->name); + + INIT_LIST_HEAD(&frm_dev->list); + frm_dev->type = FIRMWARE_CPLD; + frm_dev->dev.minor = MISC_DYNAMIC_MINOR; + frm_dev->dev.name = frm_dev->name; + frm_dev->dev.fops = &cpld_dev_fops; + frm_dev->priv = cpld_info; + + dev_debug(firmware_debug(), "Register cpld firmware slot:%d, name:%s.\n", frm_dev->slot, frm_dev->name); + + ret = firmware_device_register(frm_dev); + if (ret < 0) { + dev_debug(firmware_debug(), "Failed to register firmware device.\n"); + kfree(frm_dev); + return -EPERM; + } + + platform_set_drvdata(pdev, frm_dev); + + return 0; +} + +static int __exit firmware_cpld_remove(struct platform_device *dev) +{ + firmware_device_t *frm_dev; + + frm_dev = (firmware_device_t *)platform_get_drvdata(dev); + firmware_device_unregister(frm_dev); + + kfree(frm_dev); + + return 0; +} + +static struct of_device_id cpld_match[] = { + { + .compatible = "firmware_cpld_ispvme", + }, + {}, +}; + +static struct platform_driver cpld_driver = { + .driver = { + .name = "firmware_cpld_ispvme", + .owner = THIS_MODULE, + .of_match_table = cpld_match, + }, + .probe = firmware_cpld_probe, + .remove = firmware_cpld_remove, +}; + +static firmware_driver_t fmw_drv = { + .name = "firmware_cpld_ispvme", + .type = FIRMWARE_CPLD, + .drv = &cpld_driver, +}; + +void firmware_cpld_init(void) +{ + int ret; +#if 0 + struct device_node* node; + node = of_find_node_by_name(NULL, "cpld_upgrade"); + if (node == NULL) { + pr_notice("No cpld_upgrade\r\n"); + return; + } + pr_notice("Found cpld_upgrade\r\n"); +#else + printk(KERN_INFO "Do init cpld_upgrade\r\n"); +#endif + INIT_LIST_HEAD(&fmw_drv.list); + ret = fmw_cpld_upg_init(); + if (ret < 0) { + return; + } + firmware_driver_register(&fmw_drv); +} + +void firmware_cpld_exit(void) +{ + fmw_cpld_upg_exit(); + firmware_driver_unregister(&fmw_drv); + INIT_LIST_HEAD(&fmw_drv.list); +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_upgrade_ispvme.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_upgrade_ispvme.c new file mode 100644 index 000000000000..b01545d1d506 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_cpld_upgrade_ispvme.c @@ -0,0 +1,336 @@ +/** + * Copyright(C) 2013 Ragile Network. All rights reserved. + */ +/* + * firmware_cpld_upgrade.c + * Original Author : support@ragilenetworks.com, 2013-10-25 + * + * CPLD upgrade driver + * + * History + * v1.0 chenwendai(support@ragilenetworks.com) 2013-10-25 Initial version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* TCK clock MAX 16MHz */ +#define TCK_DELAY (current_fmw_cpld->tck_delay) + +#if 0 +static firmware_cpld_t default_fmw_cpld; +#endif +static firmware_cpld_t fmw_cpld[FIRMWARE_MAX_CPLD_NUM]; +static firmware_cpld_t *current_fmw_cpld; + +static firmware_set_gpio_info_func_t g_set_gpio_info_func = NULL; + +void set_currrent_cpld_info(firmware_cpld_t *info) +{ + current_fmw_cpld = info; +} + +static void TDI_PULL_DOWN(void) +{ + if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tdi_down) { + current_fmw_cpld->pull_tdi_down(); + } else { + dev_debug(firmware_debug(), "NO support TDI_PULL_DOWN.\n"); + } +} + +static void TDI_PULL_UP(void) +{ + if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tdi_up) { + current_fmw_cpld->pull_tdi_up(); + } else { + dev_debug(firmware_debug(), "NO support TDI_PULL_UP.\n"); + } +} + +static void TCK_PULL_DOWN(void) +{ + if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tck_down) { + current_fmw_cpld->pull_tck_down(); + } else { + dev_debug(firmware_debug(), "NO support TCK_PULL_DOWN.\n"); + } +} + +static void TCK_PULL_UP(void) +{ + if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tck_up) { + current_fmw_cpld->pull_tck_up(); + } else { + dev_debug(firmware_debug(), "NO support TCK_PULL_UP.\n"); + } +} + +static void TMS_PULL_DOWN(void) +{ + if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tms_down) { + current_fmw_cpld->pull_tms_down(); + } else { + dev_debug(firmware_debug(), "NO support TMS_PULL_DOWN.\n"); + } +} + +static void TMS_PULL_UP(void) +{ + if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tms_up) { + current_fmw_cpld->pull_tms_up(); + } else { + dev_debug(firmware_debug(), "NO support TMS_PULL_UP.\n"); + } +} + +static int TDO_READ(void) +{ + if (current_fmw_cpld != NULL && current_fmw_cpld->read_tdo) { + return current_fmw_cpld->read_tdo(); + } else { + dev_debug(firmware_debug(), "NO support TDO_READ.\n"); + return -1; + } +} + + +firmware_cpld_t *fmw_cpld_upg_get_cpld(char *name) +{ + int i; + + for (i = 0; i < FIRMWARE_MAX_CPLD_NUM; i++) { + if (fmw_cpld[i].is_used == 1 && strcmp(name, fmw_cpld[i].devname) == 0) { + return &fmw_cpld[i]; + } + } + + return NULL; +} + + +int fmw_cpld_upg_copy_firmware_info(firmware_cpld_t *info) +{ + int i; + + for (i = 0; i < FIRMWARE_MAX_CPLD_NUM; i++) { + if (fmw_cpld[i].is_used == 1) { + continue; + } else { + strncpy(fmw_cpld[i].devname, info->devname, FIRMWARE_DEV_NAME_LEN); + fmw_cpld[i].slot = info->slot; + fmw_cpld[i].chip_index = info->chip_index; + fmw_cpld[i].is_used = info->is_used; + fmw_cpld[i].tck_delay = info->tck_delay; + fmw_cpld[i].pull_tdi_up = info->pull_tdi_up; + fmw_cpld[i].pull_tdi_down = info->pull_tdi_down; + fmw_cpld[i].pull_tck_up = info->pull_tck_up; + fmw_cpld[i].pull_tck_down = info->pull_tck_down; + fmw_cpld[i].pull_tms_up = info->pull_tms_up; + fmw_cpld[i].pull_tms_down = info->pull_tms_down; + fmw_cpld[i].read_tdo = info->read_tdo; + fmw_cpld[i].init_cpld = info->init_cpld; + fmw_cpld[i].init_chip = info->init_chip; + fmw_cpld[i].finish_chip = info->finish_chip; + fmw_cpld[i].finish_cpld = info->finish_cpld; + fmw_cpld[i].touch_watch_dog = info->touch_watch_dog; + fmw_cpld[i].keeplive = info->keeplive; + fmw_cpld[i].get_version = info->get_version; + fmw_cpld[i].get_card_name = info->get_card_name; + return 0; + } + } + return -1; +} + +int fmw_cpld_set_gpio_info(firmware_upg_gpio_info_t *info) +{ + if (g_set_gpio_info_func == NULL) { + dev_debug(firmware_debug(), "g_set_gpio_info_func is null.\n"); + return -1; + } + + return g_set_gpio_info_func(info); +} + +void fmw_cpld_reg_gpio_info_set_func(firmware_set_gpio_info_func_t func) +{ + if (func == NULL) { + dev_debug(firmware_debug(), "fmw_cpld_register_gpio_info_set_func func = NULL.\n"); + return; + } + g_set_gpio_info_func = func; + return; + +} +#if 0 +/* CPLD upgrade initialization operation */ +static int fmw_cpld_upg_init_cpld(void) +{ + gpio_request(JTAG_TDI, "cpld_upgrade"); + gpio_request(JTAG_TCK, "cpld_upgrade"); + gpio_request(JTAG_TMS, "cpld_upgrade"); + gpio_request(JTAG_EN, "cpld_upgrade"); + gpio_request(JTAG_TDO, "cpld_upgrade"); + + gpio_direction_output(JTAG_TDI, 1); + gpio_direction_output(JTAG_TCK, 1); + gpio_direction_output(JTAG_TMS, 1); + gpio_direction_output(JTAG_EN, 1); + + gpio_direction_input(JTAG_TDO); + return 0; +} + +/* CPLD upgrade completion operation */ +static int fmw_cpld_upg_finish_cpld(void) +{ + gpio_direction_output(JTAG_EN, 0); + + gpio_free(JTAG_TDI); + gpio_free(JTAG_TCK); + gpio_free(JTAG_TMS); + gpio_free(JTAG_EN); + gpio_free(JTAG_TDO); + return 0; +} + +/* TDI pull up */ +static void fmw_cpld_upg_pull_tdi_up(void) +{ + __gpio_set_value(JTAG_TDI, 1); +} + +/* TDI pull down */ +static void fmw_cpld_upg_pull_tdi_down(void) +{ + __gpio_set_value(JTAG_TDI, 0); +} + +/* TCK pull up */ +static void fmw_cpld_upg_pull_tck_up(void) +{ + __gpio_set_value(JTAG_TCK, 1); +} + +/* TCK pull down */ +static void fmw_cpld_upg_pull_tck_down(void) +{ + __gpio_set_value(JTAG_TCK, 0); +} + +/* TMS pull up */ +static void fmw_cpld_upg_pull_tms_up(void) +{ + __gpio_set_value(JTAG_TMS, 1); +} + +/* TCK pull down */ +static void fmw_cpld_upg_pull_tms_down(void) +{ + __gpio_set_value(JTAG_TMS, 0); +} + +/* read TDO */ +static int fmw_cpld_upg_read_tdo(void) +{ + return __gpio_get_value(JTAG_TDO); +} +#endif +#if 0 +static firmware_cpld_t default_fmw_cpld = { + .devname = "default_firmware_cpld", + .slot = 1, + .is_used = 1, + .tck_delay = 50, + .pull_tdi_up = fmw_cpld_upg_pull_tdi_up, + .pull_tdi_down = fmw_cpld_upg_pull_tdi_down, + .pull_tck_up = fmw_cpld_upg_pull_tck_up, + .pull_tck_down = fmw_cpld_upg_pull_tck_down, + .pull_tms_up = fmw_cpld_upg_pull_tms_up, + .pull_tms_down = fmw_cpld_upg_pull_tms_down, + .read_tdo = fmw_cpld_upg_read_tdo, + .init_cpld = fmw_cpld_upg_init_cpld, + .finish_cpld = fmw_cpld_upg_finish_cpld, +}; +#endif + +/** + * Each product initializes its own related CPLD driver and needs to re-define the interface + * In the new interface, assign the relevant driver to fmw_cpld through the fmw_cpld_upg_copy_firmware_info interface + */ +int __attribute__ ((weak))fmw_cpld_product_init(void) +{ + dev_debug(firmware_debug(), "Nothing cpld init for this product.\n"); + return 0; +} + +void __attribute__ ((weak))fmw_cpld_product_exit(void) +{ + dev_debug(firmware_debug(), "Nothing exit init for this product.\n"); + return; +} + +int fmw_cpld_upg_init(void) +{ + int ret; + memset(fmw_cpld, 0, FIRMWARE_MAX_CPLD_NUM * sizeof(firmware_cpld_t)); + ret = fmw_cpld_product_init(); + if (ret < 0) { + return ret; + } +#if 0 + set_currrent_cpld_info(&default_fmw_cpld); +#endif + + return 0; +} + +void fmw_cpld_upg_exit(void) +{ + fmw_cpld_product_exit(); + return; +} + +void fwm_cpld_tdi_op(int value) +{ + if (value) { + TDI_PULL_UP(); + } else { + TDI_PULL_DOWN(); + } +} + + +void fwm_cpld_tck_op(int value) +{ + if (value) { + TCK_PULL_UP(); + } else { + TCK_PULL_DOWN(); + } +} + + +void fwm_cpld_tms_op(int value) +{ + if (value) { + TMS_PULL_UP(); + } else { + TMS_PULL_DOWN(); + } +} + + +int fwm_cpld_tdo_op() +{ + return TDO_READ(); +} diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_ispvme.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_ispvme.c new file mode 100644 index 000000000000..f3e89bbe2721 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/firmware_ispvme.c @@ -0,0 +1,144 @@ +/** + * Copyright(C) 2013 Ragile Network. All rights reserved. + */ +/* + * firmware.c + * Original Author : support@ragilenetworks.com, 2013-10-25 + * + * firmware upgrade driver + * + * History + * v1.0 chenwendai(support@ragilenetworks.com) 2013-10-25 Initial version. + * + */ +#include +#include +#include +#include + +int drv_debug = 0; +module_param(drv_debug, int, S_IRUGO | S_IWUSR); + +static LIST_HEAD(drv_list); +static LIST_HEAD(dev_list); + +void firmware_set_debug(int value) +{ + drv_debug = value; + return; +} + +int firmware_debug(void) +{ + return drv_debug; +} + +int firmware_driver_register(firmware_driver_t *fw_drv) +{ + int ret; + + if (fw_drv == NULL) { + return FIRMWARE_FAILED; + } + + ret = platform_driver_register(fw_drv->drv); + if (ret < 0) { + return FIRMWARE_FAILED; + } + + list_add(&fw_drv->list, &drv_list); + + return FIRMWARE_SUCCESS; +} + +void firmware_driver_unregister(firmware_driver_t *fw_drv) +{ + list_del_init(&fw_drv->list); + platform_driver_unregister(fw_drv->drv); +} + + +int firmware_get_device_num(int type) +{ + int num; + firmware_device_t *tmp; + + num = 0; + list_for_each_entry(tmp, &dev_list, list) { + if (tmp->type == type) { + num++; + } + } + + return num; +} + +firmware_device_t *firmware_get_device_by_minor(int type, int minor) +{ + firmware_device_t *tmp; + + list_for_each_entry(tmp, &dev_list, list) { + if (tmp->type == type && tmp->dev.minor == minor) { + return tmp; + } + } + + return NULL; +} + +int firmware_device_register(firmware_device_t *fw_dev) +{ + int ret; + firmware_device_t *tmp; + + if (fw_dev == NULL) { + return FIRMWARE_FAILED; + } + + list_for_each_entry(tmp, &dev_list, list) { + if (strcmp(tmp->name, fw_dev->name) == 0) { + return FIRMWARE_FAILED; + } + } + + ret = misc_register(&fw_dev->dev); + if (ret < 0) { + return FIRMWARE_FAILED; + } + + list_add(&fw_dev->list, &dev_list); + return FIRMWARE_SUCCESS; +} + +void firmware_device_unregister(firmware_device_t *fw_dev) +{ + list_del(&fw_dev->list); + misc_deregister(&fw_dev->dev); +} + +static int __init firmware_driver_init(void) +{ + INIT_LIST_HEAD(&drv_list); + INIT_LIST_HEAD(&dev_list); + dev_debug(firmware_debug(), "firmware_driver_init cpld init.\n"); + firmware_cpld_init(); + + return FIRMWARE_SUCCESS; +} + +static void __exit firmware_driver_exit(void) +{ + dev_debug(firmware_debug(), "firmware_driver_exit cpld exit.\n"); + firmware_cpld_exit(); + INIT_LIST_HEAD(&drv_list); + INIT_LIST_HEAD(&dev_list); + return; +} + +module_init(firmware_driver_init); +module_exit(firmware_driver_exit); + +MODULE_AUTHOR("support@ragilenetworks.com"); +MODULE_DESCRIPTION("Firmware upgrade driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/config_ispvme.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/config_ispvme.h new file mode 100644 index 000000000000..3efbfbeba2e4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/config_ispvme.h @@ -0,0 +1,11 @@ +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#define JTAG_TDI (32) +#define JTAG_TDO (67) +#define JTAG_TCK (65) +#define JTAG_TMS (6) +#define JTAG_EN (50) + + +#endif /* __CONFIG_H__ */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_cpld_ispvme.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_cpld_ispvme.h new file mode 100644 index 000000000000..98703df4f9be --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_cpld_ispvme.h @@ -0,0 +1,52 @@ +#ifndef __FIRMWARE_CPLD_H__ +#define __FIRMWARE_CPLD_H__ + +#define FIRMWARE_DEV_NAME_LEN 32 +#define FIRMWARE_MAX_CPLD_NUM 16 + +typedef struct firmware_cpld_s { + char devname[FIRMWARE_DEV_NAME_LEN]; + int slot; + int chip_index; + int is_used; /* 0:unused 1:used */ + u32 tck_delay; /* delay time */ + void (*pull_tdi_up)(void); /* TDI pull up */ + void (*pull_tdi_down)(void); /* TDI pull dowm */ + void (*pull_tck_up)(void); /* TCK pull up */ + void (*pull_tck_down)(void); /* TCK pull dowm */ + void (*pull_tms_up)(void); /* TMS pull up */ + void (*pull_tms_down)(void); /* TCK pull dowm */ + int (*read_tdo)(void); /* read ?TDO */ + int (*init_cpld)(void); /* CPLD upgrade initialization operation */ + int (*init_chip)(int slot); /* Chip related initialization operations */ + int (*finish_chip)(int slot); /* Chip related completion operations */ + int (*finish_cpld)(void); /* CPLD upgrade completion operation */ + int (*check_upgrade_data)(char *src, int src_len, int *dst, int dst_len); + int (*touch_watch_dog)(void); /* touch watch dog related operation */ + int (*keeplive)(void); /* KEEPLIVE */ + int (*get_version)(int slot, char *ver, int len); + int (*get_card_name)(char *name, int len); /* get card name */ +} firmware_cpld_t; + +typedef int (*firmware_set_gpio_info_func_t)(firmware_upg_gpio_info_t *info); + +extern int fmw_cpld_upg_get_chip_name(int slot, firmware_cpld_t *cpld, char *info, int len); +extern int fmw_cpld_upg_get_card_name(int slot, firmware_cpld_t *cpld, char *info, int len); +extern int fmw_cpld_upg_program(int slot, firmware_cpld_t *cpld, char *info, int len); +extern int fmw_cpld_upg_get_version(int slot, firmware_cpld_t *cpld, char *info, int len); +extern firmware_cpld_t *fmw_cpld_upg_get_cpld(char *name); +extern int fmw_cpld_upg_init(void); +extern void fmw_cpld_upg_exit(void); +extern int fmw_cpld_upg_copy_firmware_info(firmware_cpld_t *info); +extern int fmw_cpld_upg_get_chip_info(int slot, firmware_cpld_t *cpld, void *info, int len); + +extern void fwm_cpld_tdi_op(int value); +extern void fwm_cpld_tck_op(int value); +extern void fwm_cpld_tms_op(int value); +extern int fwm_cpld_tdo_op(void); +extern void firmware_cpld_upgrade_init(void); +extern void firmware_cpld_upgrade_finish(void); +extern int fmw_cpld_set_gpio_info(firmware_upg_gpio_info_t *info); +extern void fmw_cpld_reg_gpio_info_set_func(firmware_set_gpio_info_func_t func); + +#endif /* __FIRMWARE_CPLD_H__ */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_ispvme.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_ispvme.h new file mode 100644 index 000000000000..b2c08e6151c7 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_driver_ispvme/include/firmware_ispvme.h @@ -0,0 +1,88 @@ +#ifndef __FIRMWARE_H__ +#define __FIRMWARE_H__ + +#include +#include + +#include + +#define dev_debug(debug, fmt, arg...) \ + if (debug == 1) { do{printk(KERN_ERR fmt,##arg);} while(0); } + +#define FIRMWARE_NAME_LEN 48 + +#define FIRMWARE_FAILED (-1) +#define FIRMWARE_SUCCESS 0 + +enum firmware_type_s { + FIRMWARE_CPLD = 0, + FIRMWARE_FPGA, +}; + +/* ioctl command */ +#define FIRMWARE_TYPE 'F' +#define FIRMWARE_JTAG_TDI _IOR(FIRMWARE_TYPE, 0, char) +#define FIRMWARE_JTAG_TDO _IOR(FIRMWARE_TYPE, 1, char) +#define FIRMWARE_JTAG_TCK _IOR(FIRMWARE_TYPE, 2, char) +#define FIRMWARE_JTAG_TMS _IOR(FIRMWARE_TYPE, 3, char) +#define FIRMWARE_JTAG_EN _IOR(FIRMWARE_TYPE, 4, char) +#define FIRMWARE_SET_DEBUG_ON _IOW(FIRMWARE_TYPE, 5, int) /* debug on */ +#define FIRMWARE_SET_DEBUG_OFF _IOW(FIRMWARE_TYPE, 6, int) /* debug off */ +#define FIRMWARE_SET_GPIO_INFO _IOR(FIRMWARE_TYPE, 7, int) /* Set GPIO pin configuration */ + +typedef struct cmd_info_s { + int size; + void __user *data; +} cmd_info_t; + +typedef struct firmware_device_s { + struct list_head list; /* device linked list */ + int type; /* the type of device */ + int slot; /* position */ + char name[FIRMWARE_NAME_LEN]; /* name */ + struct miscdevice dev; /* device */ + void *priv; /* private data */ +} firmware_device_t; + +typedef struct firmware_driver_s { + struct list_head list; /* linked list */ + int type; /* type */ + char name[FIRMWARE_NAME_LEN]; /* name */ + struct platform_driver *drv; /* driver */ + void *priv; /* private data */ +} firmware_driver_t; + +typedef struct gpio_group_s { + int pin; + int val; + int dir; +} gpio_group_t; + +typedef struct firmware_upg_gpio_info_s { + int tdi; + int tck; + int tms; + int tdo; + int jtag_en; + int select; + gpio_group_t jtag_5; + gpio_group_t jtag_4; + gpio_group_t jtag_3; + gpio_group_t jtag_2; + gpio_group_t jtag_1; +} firmware_upg_gpio_info_t; + +extern int firmware_debug(void); +extern void firmware_set_debug(int value); +extern firmware_device_t *firmware_get_device_by_minor(int type, int minor); +extern int firmware_get_device_num(int type); +extern int firmware_device_register(firmware_device_t *fw_dev); +extern void firmware_device_unregister(firmware_device_t *fw_dev); +extern int firmware_driver_register(firmware_driver_t *fw_drv); +extern void firmware_driver_unregister(firmware_driver_t *fw_drv); +extern void firmware_fpga_init(void); +extern void firmware_cpld_init(void); +extern void firmware_fpga_exit(void); +extern void firmware_cpld_exit(void); + +#endif /* end of __FIRMWARE_H__ */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/Makefile new file mode 100644 index 000000000000..2bdfd8fc67ef --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/Makefile @@ -0,0 +1,39 @@ +include $(top_srcdir)/Rules.mk + +OBJ = firmware_app_ispvme.o debug_ispvme.o hardware.o ispvm_ui.o ivm_core.o dfd_fpga_pkt.o dfd_fpga_upg.o dfd_fpga_debug.o +LIB += $(BUILD_CFALGS) $(BUILD_LDFLAGS) -lpthread -lreadline -lncurses +ifdef ENABLE_GCOV +ifeq ($(ENABLE_GCOV), y) +LIB += -lgcov +endif +endif # ENABLE_GCOV +APP = firmware_upgrade +BUILD_DIR = tmp +ELF_FILE = $(BUILD_DIR)/$(APP) +MAP_FILE = $(BUILD_DIR)/$(APP).map.sym +INCLUDE = -Iinclude + + +.PHONY: build +build:make-dir $(addprefix $(BUILD_DIR)/,$(OBJ)) + $(CC) -o $(ELF_FILE) $(addprefix $(BUILD_DIR)/,$(OBJ)) $(LINKFLAGS) $(LIB) + $(NM) $(ELF_FILE) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' \ + | sort > $(MAP_FILE) + cp -p $(ELF_FILE) $(common_out_put_dir) + +# ����buildĿ¼�������.o�ļ� +.PHONY: make-dir +make-dir: + @mkdir -p $(BUILD_DIR) + +$(BUILD_DIR)/%.o:%.c + $(CC) -c $(CFLAGS) $(INCLUDE) $< -o $@ + +.PHONY: install +install: + echo "firmware_upgrade install success." + cp -p $(ELF_FILE) $(common_out_put_dir) + +.PHONY: clean +clean: + rm -rf $(BUILD_DIR) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/common.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/common.h new file mode 100644 index 000000000000..3957cc410494 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/common.h @@ -0,0 +1,29 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include +#include +#include +#include +#include +#include + +#define FIRMWARE_TYPE 'F' +#define FIRMWARE_JTAG_TDI _IOR(FIRMWARE_TYPE, 0, char) +#define FIRMWARE_JTAG_TDO _IOR(FIRMWARE_TYPE, 1, char) +#define FIRMWARE_JTAG_TCK _IOR(FIRMWARE_TYPE, 2, char) +#define FIRMWARE_JTAG_TMS _IOR(FIRMWARE_TYPE, 3, char) +#define FIRMWARE_JTAG_EN _IOR(FIRMWARE_TYPE, 4, char) +#define FIRMWARE_SET_DEBUG_ON _IOW(FIRMWARE_TYPE, 5, int) /* debug on */ +#define FIRMWARE_SET_DEBUG_OFF _IOW(FIRMWARE_TYPE, 6, int) /* debug off */ +#define FIRMWARE_SET_GPIO_INFO _IOR(FIRMWARE_TYPE, 7, int) /* set GPIO pin configuration */ + +#define JTAG_TDI (1) +#define JTAG_TDO (2) +#define JTAG_TCK (3) +#define JTAG_TMS (4) +#define JTAG_ENABLE (5) +#define JTAG_TRST (6) + + +#endif diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/debug_ispvme.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/debug_ispvme.c new file mode 100644 index 000000000000..8d46379dfe8f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/debug_ispvme.c @@ -0,0 +1,72 @@ +/** + * Copyright(C) 2013 Ragile Network. All rights reserved. + */ +/* + * debug.c + * Original Author : support@ragilenetworks.com, 2013-10-23 + * + * firmware upgrade debug control + * + * History + * v1.0 chenwendai(support@ragilenetworks.com) 2013-10-23 Initial version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * firmware_upgrade_debug:handle debug switch + * + * analyse file /tmp/firmware_upgrade_debug,return the information correspoding to debug + * + * return:return DEBUG_OFF when debug off,return DEBUG_ON when debug on,return DEBUG_IGNORE in other cases + */ +int firmware_upgrade_debug(void) +{ + int size; + FILE *fp; + char debug_info[DEBUG_INFO_LEN]; + + fp = fopen(DEBUG_FILE, "r"); + if (fp == NULL) { + return DEBUG_IGNORE; + } + + memset(debug_info, 0, DEBUG_INFO_LEN); + size = fread(debug_info, DEBUG_INFO_LEN - 1, 1, fp); + if (size < 0) { + fclose(fp); + return DEBUG_IGNORE; + } + + if (strncmp(debug_info, DEBUG_ON_INFO, 1) == 0) { + fclose(fp); + return DEBUG_APP_ON; + } + + if (strncmp(debug_info, DEBUG_ON_KERN, 1) == 0) { + fclose(fp); + return DEBUG_KERN_ON; + } + + if (strncmp(debug_info, DEBUG_ON_ALL, 1) == 0) { + fclose(fp); + return DEBUG_ALL_ON; + } + + if (strncmp(debug_info, DEBUG_OFF_INFO, 1) == 0) { + fclose(fp); + return DEBUG_OFF; + } + + fclose(fp); + return DEBUG_IGNORE; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.c new file mode 100644 index 000000000000..83c1c1693288 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.c @@ -0,0 +1,124 @@ +/* + * Copyright(C) 2001-2013 Ragile Network. All rights reserved. + */ +/* + * dfd_debug.c + * Original Author: support@ragilenetworks.com 2014-11-14 + * + * Function:Device framework driver debugging interface + * + * History + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "dfd_fpga_debug.h" + +#undef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) /sizeof((a)[0])) + +/* Debug switch storage of dfd module */ +int g_dfd_fpga_debug = 0x0; + +/** + * dfd_fpga_pkt_debug_set - Debug switch setting interface of dfd module + * @type: Types of debugging information + * @enable: enable/Disable debugging information + * + * return 0 if success, otherwise reuturn -1. + */ +static int dfd_fpga_pkt_debug_set(int type, int enable) +{ + + if (type >= DFD_DBG_CNT || type < 0) { + DFD_ERROR("unknow dfd debug type=%d\n", type); + return -1; + } + + if (enable) { + g_dfd_fpga_debug |= 1U << type; + } else { + g_dfd_fpga_debug &= ~(1U << type); + } + + return 0; +} + +void dfd_fpga_open_debug(int val) +{ + if (val == 1) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1); + } else if (val == 2) { + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1); + } else if (val == 3) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1); + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1); + } else if (val == 4) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1); + } else { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 0); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 0); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 0); + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 0); + } + + return; +} + +void dfd_fpga_debug_init(void) +{ + FILE *fp; + char buf[10]; + + memset(buf, 0, sizeof(buf)); + fp = fopen(DFD_DEBUG_FILE, "r"); + if (fp != NULL) { + if (fgets(buf, sizeof(buf), fp) != NULL) { + if (strstr(buf, DFD_DEBUG_SET_NO_WARN) != NULL) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 0); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 0); + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0); + } else if (strstr(buf, DFD_DEBUG_SET_NO_VBOSE) != NULL) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 0); + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0); + } else if (strstr(buf, DFD_DEBUG_SET_NO_FLOCK_VBOSE) != NULL) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1); + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0); + } else if (strstr(buf, DFD_DEBUG_SET_ALL) != NULL) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1); + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1); + (void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1); + } else if (strstr(buf, DFD_DEBUG_SET_DBG) != NULL) { + (void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1); + } else if (strstr(buf, DFD_DEBUG_SET_FLOCK) != NULL) { + (void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1); + } + } + + fclose(fp); + } + + return; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.h new file mode 100644 index 000000000000..247e5a1783a8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_debug.h @@ -0,0 +1,70 @@ +#ifndef _DFD_FPGA_DEBUG_H_ +#define _DFD_FPGA_DEBUG_H_ + +#include +#include + +#define DFD_DEBUG_FILE "/sbin/.dfd_debug_flag" + +#define DFD_DEBUG_SET_NO_WARN "0x1" +#define DFD_DEBUG_SET_NO_VBOSE "0x3" +#define DFD_DEBUG_SET_NO_FLOCK_VBOSE "0x7" +#define DFD_DEBUG_SET_ALL "0xf" +#define DFD_DEBUG_SET_DBG "0xd" +#define DFD_DEBUG_SET_FLOCK "0xe" + + +#define DFD_DEBUG_CHECK(type) (g_dfd_fpga_debug & (1U << (type))) + +#define DFD_ERROR(fmt, args...) do { \ + if (DFD_DEBUG_CHECK(DFD_DBG_ERR)) { \ + printf("[%s-%s]:\n" fmt, "DFD", "err", \ + __FILE__, __FUNCTION__, __LINE__, ##args); \ + } \ +} while (0) + +#define DFD_WARN(fmt, args...) do { \ + if (DFD_DEBUG_CHECK(DFD_DBG_WARN)) { \ + printf("[%s-%s]:\n" fmt, "DFD", "warn", \ + __FILE__, __FUNCTION__, __LINE__, ##args); \ + } \ +} while (0) + +#define DFD_VERBOS(fmt, args...) do { \ + if (DFD_DEBUG_CHECK(DFD_DBG_VBOSE)) { \ + printf("[%s-%s]:\n" fmt, "DFD", "vbose", \ + __FILE__, __FUNCTION__, __LINE__, ##args); \ + } \ +} while (0) + +#define DFD_FLOCK_VERBOS(fmt, args...) do { \ + if (DFD_DEBUG_CHECK(DFD_FLOCK_DBG_VBOSE)) { \ + printf("[%s-%s]:\n" fmt, "DFD", "flock_vbose", \ + __FILE__, __FUNCTION__, __LINE__, ##args); \ + } \ +} while (0) + +#define DFD_DBG(fmt, args...) do { \ + if (DFD_DEBUG_CHECK(DFD_DBG_DBG)) { \ + printf("" fmt,\ + ##args); \ + } \ + } while (0) +/* define the type of debugging information */ +typedef enum { + DFD_DBG_ERR, + DFD_DBG_WARN, + DFD_DBG_VBOSE, + DFD_FLOCK_DBG_VBOSE, + DFD_DBG_DBG, + DFD_DBG_CNT +} DFD_DEBUG_TYPE_E; + +extern int g_dfd_fpga_debug; + +int dfd_fpga_debug_set(int type, int enable); +void dfd_fpga_open_debug(int val); +void dfd_fpga_debug_init(void); + +#endif + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.c new file mode 100644 index 000000000000..ea41831edddd --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.c @@ -0,0 +1,327 @@ +/* + * Copyright(C) 2001-2012 Ragile Network. All rights reserved. + */ +/* + * dfd_fpga_pkt.c + * Original Author: support@ragilenetworks.com 2016-08-09 + * + * FPGA message interaction related interface + * + * History + * [Version] [Author] [Date] [Description] + * * v1.0 support@ragilenetworks.com 2016.08.09 Initial version + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dfd_fpga_pkt.h" +#include "dfd_fpga_debug.h" + +#define DFD_FPGA_FAC_MODE_CONFIG_FILE "/tmp/.factory_disabale_cli_tty" + +#if 1 +#define DFD_FPGA_PKT_SEND_PKT_TO_FRAME +#endif + +void dfd_fpga_pkt_print(uint8_t *buf, int buf_len) +{ + int i; + + for (i = 0; i < buf_len; i++) { + if ((i % 16) == 0) { + DFD_DBG("\n"); + } + DFD_DBG("%02x ", buf[i]); + } + + DFD_DBG("\n"); + return; +} + +static unsigned int littel_endian_byte_to_word32(uint8_t *byte_buf, int len) +{ + uint8_t tmp_buf[4]; + unsigned int word; + + word = 0; + + memset(tmp_buf, 0, 4); + memcpy(tmp_buf, byte_buf, len < 4 ? len : 4); + + word = tmp_buf[0] | (tmp_buf[1] << 8) | (tmp_buf[2] << 16) | (tmp_buf[3] << 24); + + return word; +} + +static int littel_endian_word32_to_byte(uint8_t *byte_buf, int len, unsigned int word) +{ + uint8_t tmp_buf[4]; + int ret; + + if (len < 4) { + DFD_ERROR("Not enough buf, word32 to byte: len[%d], word[0x%x]\n"); + return -1; + } + + memset(tmp_buf, 0, 4); + tmp_buf[0] = word & 0xff; + tmp_buf[1] = (word >> 8) & 0xff; + tmp_buf[2] = (word >> 16) & 0xff; + tmp_buf[3] = (word >> 24) & 0xff; + + memcpy(byte_buf, tmp_buf, 4); + + return 0; +} + +static int open_pci_dev(dfd_pci_dev_priv_t *pci_priv, int is_cfg) +{ + int file, ret; + char filename[DFD_PCI_MAX_NAME_SIZE]; + + if (is_cfg) { + ret = snprintf(filename, DFD_PCI_MAX_NAME_SIZE, + "/sys/class/pci_bus/%04x:%02x/device/%04x:%02x:%02x.%d/config", + 0, pci_priv->pcibus, 0, pci_priv->pcibus, pci_priv->slot, pci_priv->fn); + } else { + ret = snprintf(filename, DFD_PCI_MAX_NAME_SIZE, + "/sys/class/pci_bus/%04x:%02x/device/%04x:%02x:%02x.%d/resource%d", + 0, pci_priv->pcibus, 0, pci_priv->pcibus, pci_priv->slot, pci_priv->fn, + pci_priv->bar); + } + + filename[ret] = '\0'; + if ((file = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + DFD_ERROR("Error: Could not open file %s\n", filename); + } + + return file; +} + + +/** + * dfd_fpga_buf_read - provide FPGA write register interface (address must be four-byte aligned) + * @dst: The data structure of sslot and unit corresponding to the target chip + * @addr: address (four-byte alignment). For the byte alignment required by the specific FPGA address, please refer to the FPGA manual + * @buf: Buffer for reading data + * @wr_len: the length of reading data,please refer to the FPGA manual for the length of the specific FPGA address requirements + * return: return if success,else return -1 + */ +int dfd_fpga_pci_read(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int rd_len) +{ + int ret, fd; + unsigned int data; + uint8_t *ptr, *ptr_data; + struct stat sb; + int i; + int len, align; + + if ((pci_priv == NULL) || (buf == NULL)) { + DFD_ERROR("pci_prive or read buf is null.\n"); + return -1; + } + + if ((pci_priv->align < 1) || (offset & (pci_priv->align - 1)) || (rd_len & (pci_priv->align - 1))) { + DFD_ERROR("offset[%d] or rd_len[%d] don't align[%d].\n", offset, rd_len, pci_priv->align); + return -1; + } + + if ((fd = open_pci_dev(pci_priv, 0)) < 0) { + return -1; + } + + if ((ret = fstat(fd, &sb)) == -1) { + DFD_ERROR("Error: Could not fstat : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if (offset + rd_len >= sb.st_size) { + DFD_ERROR("Error: offset is out of range\n"); + close(fd); + return -1; + } + + if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + DFD_ERROR("Error: Could not mmap : %s or resource is IO\n", strerror(errno)); + close(fd); + return -1; + } + + align = pci_priv->align; + len = rd_len; + ret = 0; + i = 0; + ptr_data = ptr + offset; + + while((i < len) && (ret == 0)){ + if (align == 4) { + data = *((volatile unsigned int *)(ptr_data + i)); + ret = littel_endian_word32_to_byte(buf + i, len - i, data); + i += 4; + } else { + ret = -1; + } + } + + munmap(ptr, sb.st_size); + close(fd); + return ret; + +} + +/** + * dfd_fpga_buf_write -provide FPGA write register interface (address must be four-byte aligned) + * @dst: The data structure of sslot and unit corresponding to the target chip + * @addr: address (four-byte alignment). For the byte alignment required by the specific FPGA address, please refer to the FPGA manual + * @buf: Buffer for reading data + * @wr_len: the length of reading data,please refer to the FPGA manual for the length of the specific FPGA address requirements + * return: return if success,else return -1 + */ + +int dfd_fpga_pci_write(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int wr_len) +{ + int ret, fd; + unsigned int data; + uint8_t *ptr, *ptr_data; + struct stat sb; + int i; + int len, align; + + if ((pci_priv == NULL) || (buf == NULL)) { + DFD_ERROR("pci_prive or write buf is null.\n"); + return -1; + } + + if ((pci_priv->align < 1) || (offset & (pci_priv->align - 1)) || (wr_len & (pci_priv->align - 1))) { + DFD_ERROR("offset[%d] or rd_len[%d] don't align[%d].\n", offset, wr_len, pci_priv->align); + return -1; + } + + if ((fd = open_pci_dev(pci_priv, 0)) < 0) { + return -1; + } + + if ((ret = fstat(fd, &sb)) == -1) { + DFD_ERROR("Error: Could not fstat : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if (offset + wr_len >= sb.st_size) { + DFD_ERROR("Error: offset is out of range\n"); + close(fd); + return -1; + } + + if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + DFD_ERROR("Error: Could not mmap : %s or resource is IO\n", strerror(errno)); + close(fd); + return -1; + } + + align = pci_priv->align; + len = wr_len; + ret = 0; + i = 0; + ptr_data = ptr + offset; + + while((i < len) && (ret == 0)){ + if (align == 4) { + data = littel_endian_byte_to_word32(buf + i,len - i); + *((volatile unsigned int *)(ptr_data + i)) = data; + i += 4; + } else { + ret = -1; + } + } + + munmap(ptr, sb.st_size); + close(fd); + return ret; + +} + +/** + * dfd_fpga_read_word -provide FPGA read register interface (address must be four-byte aligned) + * @addr: address (four-byte alignment) + * @val: the returned number of reading + * return: return 0 if success,else return failure + */ +int dfd_fpga_read_word(dfd_pci_dev_priv_t *pci_priv, int addr, int *val) +{ + int ret, i; + uint8_t tmp[DFD_FPGA_PKT_WORD_LEN]; + + if ((pci_priv == NULL) || (val == NULL) || (addr & 0x03)) { + DFD_ERROR("Input para invalid pci_priv %p val %p addr 0x%x.\n", pci_priv, val, addr); + return -1; + } + + ret = dfd_fpga_pci_read(pci_priv, addr, tmp, DFD_FPGA_PKT_WORD_LEN); + if (ret) { + DFD_ERROR("dfd_fpga_pci_read addr 0x%x failed ret %d.\n", addr, ret); + return ret; + } + + *val = littel_endian_byte_to_word32(tmp,DFD_FPGA_PKT_WORD_LEN); + for (i = 0; i < DFD_FPGA_PKT_WORD_LEN; i++) { + DFD_VERBOS("tmp[%d]: 0x%x.\n", i, tmp[i]); + } + DFD_VERBOS("dfd_fpga_read_word addr 0x%x val 0x%x.\n", addr, *val); + + return 0; +} + +/** + * dfd_fpga_write_word -provide FPGA write register interface (address must be four-byte aligned) + * @addr: address (four-byte alignment) + * @val: Data written + * return: return 0 if success,else return failure + */ +int dfd_fpga_write_word(dfd_pci_dev_priv_t *pci_priv, int addr, int val) +{ + int ret, i; + uint8_t tmp[DFD_FPGA_PKT_WORD_LEN]; + + if ((pci_priv == NULL) || (addr & 0x03)) { + DFD_ERROR("Input para invalid pci_priv %p addr 0x%x.\n", pci_priv, addr); + return -1; + } + + littel_endian_word32_to_byte(tmp, DFD_FPGA_PKT_WORD_LEN, val); + for (i = 0; i < DFD_FPGA_PKT_WORD_LEN; i++) { + DFD_VERBOS("tmp[%d]: 0x%x.\n", i, tmp[i]); + } + + ret = dfd_fpga_pci_write(pci_priv, addr, tmp, DFD_FPGA_PKT_WORD_LEN); + if (ret) { + DFD_ERROR("dfd_fpga_pci_write addr 0x%x failed ret %d.\n", addr, ret); + return ret; + } + + DFD_VERBOS("dfd_fpga_write_word addr 0x%x val 0x%x.\n", addr, val); + return 0; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.h new file mode 100644 index 000000000000..70f105ecad5d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_pkt.h @@ -0,0 +1,98 @@ +#ifndef __DFD_FPGA_PKT_H__ +#define __DFD_FPGA_PKT_H__ + +typedef enum dfd_fpga_pkt_op_type_e { + DFD_FPGA_PKT_OP_TYPE_READ = 0, /* read */ + DFD_FPGA_PKT_OP_TYPE_WRITE = 1, /* write */ + DFD_FPGA_PKT_OP_TYPE_END, +} dfd_fpga_pkt_op_type_t; + +typedef enum dfd_fpga_pkt_ack_type_e { + DFD_FPGA_PKT_ACK_TYPE_NO_ERROR = 0, /* successful operation */ + DFD_FPGA_PKT_ACK_TYPE_FCS_ERROR = 1, /* operation FCS check error */ + DFD_FPGA_PKT_ACK_TYPE_FAIL_ERROR = 2, /* operation failed */ + DFD_FPGA_PKT_ACK_TYPE_END, +} dfd_fpga_pkt_ack_type_t; + +typedef enum dfd_rv_s { + DFD_RV_OK = 0, + DFD_RV_INIT_ERR = 1, + DFD_RV_SLOT_INVALID = 2, + DFD_RV_MODE_INVALID = 3, + DFD_RV_MODE_NOTSUPPORT = 4, + DFD_RV_TYPE_ERR = 5, + DFD_RV_DEV_NOTSUPPORT = 6, + DFD_RV_DEV_FAIL = 7, + DFD_RV_INDEX_INVALID = 8, + DFD_RV_NO_INTF = 9, + DFD_RV_NO_NODE = 10, + DFD_RV_NODE_FAIL = 11, +} dfd_rv_t; + +typedef struct dfd_pci_dev_priv_s { + int pcibus; + int slot; + int fn; + int bar; + int offset; + int times; + int align; + int fpga_upg_base; +}dfd_pci_dev_priv_t; + +#define DFD_PCI_MAX_NAME_SIZE 256 + +#define DFD_MAX_FPGA_NUM (8) +#define DFD_FPGA_PKT_WORD_LEN (4) + +#define DFD_FPGA_PKT_MAC_LEN (6) +#define DFD_FPGA_PKT_PAYLOAD_WORD_DATA_LEN (4) + +#define DFD_FPGA_PKT_WORD_RW_LEN (1)/* for each access, according to 1 WORD, 4 bytes to access FPGA */ + +#define DFD_FPGA_PKT_ETYPE (0xfff9) + +#define DFD_FPGA_PKT_PAYLOAD_ADDR_LEN (4) +#define DFD_FPGA_PKT_PAYLOAD_LENGTH_LEN (2) + +#define DFD_FPGA_PKT_PAYLOAD_ADDR_OFFSET (0) +#define DFD_FPGA_PKT_PAYLOAD_LENGTH_OFFSET (DFD_FPGA_PKT_PAYLOAD_ADDR_LEN) +#define DFD_FPGA_PKT_PAYLOAD_DATA_OFFSET ((DFD_FPGA_PKT_PAYLOAD_ADDR_LEN) + (DFD_FPGA_PKT_PAYLOAD_LENGTH_LEN)) + +#define DFD_FPGA_PKT_GET_DATA(payload) (((uint8_t*)(payload)) + DFD_FPGA_PKT_PAYLOAD_DATA_OFFSET) +#define DFD_FPGA_PKT_GET_PAYLOAD_LEN(len) ((DFD_FPGA_PKT_PAYLOAD_ADDR_LEN) + (DFD_FPGA_PKT_PAYLOAD_LENGTH_LEN) + (len)) + +#pragma pack (1) +typedef struct dfd_fpga_pkt_payload_s { + uint32_t addr; /* the address of reading and writting */ + uint16_t length; /* the length of reading and writting */ + uint32_t data; /* read and write data (for read operations, you don't need to care about this field) */ +} dfd_fpga_pkt_payload_t; + +typedef struct dfd_fpga_pkt_rd_payload_s { + uint32_t addr; /* the address of reading */ + uint16_t length; /* the length of reading */ +} dfd_fpga_pkt_rd_payload_t; +#pragma pack () + +typedef enum fpga_version_e { + FPGA_VER_00 = 0x00, + FPGA_VER_01, + FPGA_VER_02, + FPGA_VER_03, + FPGA_VER_04, + FPGA_VER_05, + FPGA_VER_06, +} fpga_version_t; + +int dfd_fpga_upg_init(void); +int dfd_fpga_write_word(dfd_pci_dev_priv_t *pci_priv, int addr, int val); +int dfd_fpga_read_word(dfd_pci_dev_priv_t *pci_priv, int addr, int *val); +int dfd_fpga_pci_write(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int wr_len); +int dfd_fpga_pci_read(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int rd_len); +extern int drv_get_my_dev_type(void); + + + +#endif + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_upg.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_upg.c new file mode 100644 index 000000000000..645d09379803 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/dfd_fpga_upg.c @@ -0,0 +1,1454 @@ +/* + * Copyright(C) 2001-2012 Ragile Network. All rights reserved. + */ +/* + * dfd_fpga_upg.c + * Original Author: support@ragilenetworks.com 2016-08-09 + * + * FPGA upgrade related interface + * + * History + * [Version] [Author] [Date] [Description] + * * v1.0 support@ragilenetworks.com 2016.08.09 Initial version + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dfd_fpga_pkt.h" +#include "dfd_fpga_debug.h" + +typedef struct dfd_fpga_upg_node_s { + int sslot; /* Expansion card slot number */ + int extype; /* Expansion card type */ + int fpga_ver; /* Expansion card FPGA version number */ +} dfd_fpga_upg_node_t; + +/* FPGA upgrade related registers */ +#define FPGA_UPG_CONTENT_BASE_REG_A00 (0xa00) +#define FPGA_UPG_CONTENT_BASE_REG_E00 (0xe00) + +#define FPGA_UPG_STATUS_REG (0x180) +#define FPGA_UPG_SPI_CTRL_REG (0x184) +#define FPGA_UPG_WR_FLASH_STATUS_REG (0x188) +#define FPGA_UPG_RD_FLASH_STATUS_REG (0x18C) +#define FPGA_UPG_INSTRUCTION_REG (0x190) + +#define FPGA_UPG_ADDR_REG (0x194) +#define FPGA_UPG_LENGTH_REG (0x198) +#define FPGA_UPG_DEVICE_ID_REG (0x19C) + +#define FPGA_UPG_DROP_REQ_NUM_REG (0x1A8) + +#define FPGA_VER_ADDRESS (0x00000000) + +#define FPGA_VER_MASK (0xFFFF) +#define FPGA_VERSION(ver) ((ver & FPGA_VER_MASK) >> 8) + +/* define FPGA upgrade related instructions */ +#define FPGA_UPG_INSTRUTION_SE (0xD8) +#define FPGA_UPG_INSTRUTION_RDID (0x9F) +#define FPGA_UPG_INSTRUTION_WRSR (0x01) +#define FPGA_UPG_INSTRUTION_RDSR (0x05) +#define FPGA_UPG_INSTRUTION_WREN (0x06) +#define FPGA_UPG_INSTRUTION_WRDI (0x04) +#define FPGA_UPG_INSTRUTION_BE (0xC7) +#define FPGA_UPG_INSTRUTION_PP (0x02) +#define FPGA_UPG_INSTRUTION_FR (0x0B) +#define FPGA_UPG_INSTRUTION_P4E (0x20) + +#define FPGA_UPG_CONTENT_LENGTH (256) + +#define FPGA_UPG_STATUS_MASK (0x1) +#define FPGA_UPG_ACCESS_ENABLE (0x3) +#define FPGA_UPG_STATUS_RESET (0x0) + +#define FPGA_UPG_SPI_STATUS_MASK (0x1) + +#define FPGA_UPG_RETRY_SLEEP_TIME (10) /* 10us */ +#define FPGA_UPG_RETRY_CNT (1000) + +#define FPGA_UPG_PKT_RETRY_CNT (100) + +#define DFD_FPGA_VERSION_REG (0x10D0) + +#define DFD_FPGA_UPGRADE_BUFF_SIZE (256) +#define DFD_FPGA_UPGADE_RETRY_CNT (10) +#define DFD_FPGA_UPGRADE_CMD_BUFF_SIZE (100) +#define DFD_FPGA_UPGRADE_MAX_NODE (16) + +#define DFD_FPGA_UPDATE_BOOT_ADDR (0x1A0000) /* UPDATE area start address */ +#define DFD_FPGA_UPDATE_BOOT_ADDR_FIX (0x2F0000) +#define DFD_FPGA_SPI_SECTOR_SIZE (0x10000) /* One sector is 64k */ +#define DFD_FPGA_UPDATE_FLASH_SIZE (0x4000000) +#define DFD_FPGA_BASE_TEST_ADD (DFD_FPGA_UPDATE_FLASH_SIZE - DFD_FPGA_SPI_SECTOR_SIZE) + +#define DFD_FPGA_CRITICAL_SWITCH_PAGE_ADDR (0xF00) /* CRITICAL SWITCH page address */ +#define DFD_FPGA_CRITICAL_SWITCH_PAGE_OFFSET (0xFC) /* CRITICAL SWITCH in-page offset address */ +#define DFD_FPGA_CRITICAL_SWITCH_WORD (0xAA995566) /* CRITICAL SWITCH value */ + +#define DFD_FPGA_ERASE_P4E_SIZE (0x1000)/* erase p4e,4k at a time*/ + +#define FPGA_UPG_WAIT_SPI_RETRY_CNT (1000) +#define FPGA_UPG_WAIT_SPI_RETRY_SLEEP_TIME (1000 * 10) /* 10ms */ +#define FPGA_RETRY_TIMES (3) + +static dfd_pci_dev_priv_t default_pci_priv = { + .pcibus = 8, + .slot = 0, + .fn = 0, + .bar = 0, + .align = 4, +}; + +static dfd_pci_dev_priv_t *current_pci_priv = NULL; + +static void dfd_utest_printf_reg(uint8_t *buf, int buf_len) +{ + int i; + + for (i = 0; i < buf_len; i++) { + if ((i % 16) == 0) { + printf("\n"); + } + printf("%02x ", buf[i]); + } + + printf("\n"); + return; +} + + +static int dfd_fpga_upg_write_word(dfd_pci_dev_priv_t *pci_priv, int addr, int val) +{ + int ret; + int i; + int cnt; + + i = 0; + cnt = FPGA_UPG_PKT_RETRY_CNT; + while(i < cnt) { + ret = dfd_fpga_write_word(pci_priv, addr, val); + if (ret) { + i++; + DFD_VERBOS("dfd_fpga_write_word addr 0x%x val 0x%x i %d failed ret %d.\n", addr, val, i, + ret); + continue; + } else { + DFD_VERBOS("dfd_fpga_write_word addr 0x%x val 0x%x success.\n", addr, val); + return 0; + } + } + + DFD_VERBOS("dfd_fpga_upg_write_word addr 0x%x val 0x%x i %d failed ret %d.\n", addr, val, i, ret); + return -1; +} + +static int dfd_fpga_upg_read_word(dfd_pci_dev_priv_t *pci_priv, int addr, int *val) +{ + int ret; + int i; + int cnt; + + i = 0; + cnt = FPGA_UPG_PKT_RETRY_CNT; + while(i < cnt) { + ret = dfd_fpga_read_word(pci_priv, addr, val); + if (ret) { + i++; + DFD_VERBOS("dfd_fpga_read_word addr 0x%x i %d failed ret %d.\n", addr, i, + ret); + continue; + } else { + DFD_VERBOS("dfd_fpga_read_word addr 0x%x val 0x%x success.\n", addr, *val); + return 0; + } + } + + DFD_VERBOS("dfd_fpga_read_word addr 0x%x i %d failed ret %d.\n", addr, i, ret); + return -1; +} + +static int dfd_fpga_upg_buf_write(dfd_pci_dev_priv_t *pci_priv, int addr, uint8_t *buf, int wr_len) +{ + int ret; + int i; + int cnt; + + i = 0; + cnt = FPGA_UPG_PKT_RETRY_CNT; + while(i < cnt) { + ret = dfd_fpga_pci_write(pci_priv, addr, buf, wr_len); + if (ret) { + i++; + DFD_VERBOS("dfd_fpga_buf_write addr 0x%x wr_len %d i %d failed ret %d.\n", addr, wr_len, i, + ret); + continue; + } else { + DFD_VERBOS("dfd_fpga_buf_write addr 0x%x wr_len %d success.\n", addr, wr_len); + return 0; + } + } + + DFD_VERBOS("dfd_fpga_buf_write addr 0x%x wr_len %d i %d failed ret %d.\n", addr, wr_len, i, ret); + return -1; +} + +static int dfd_fpga_upg_buf_read(dfd_pci_dev_priv_t *pci_priv, int addr, uint8_t *buf, int rd_len) +{ + int ret; + int i; + int cnt; + + i = 0; + cnt = FPGA_UPG_PKT_RETRY_CNT; + while(i < cnt) { + ret = dfd_fpga_pci_read(pci_priv, addr, buf, rd_len); + if (ret) { + i++; + DFD_VERBOS("dfd_fpga_buf_read addr 0x%x rd_len %d i %d failed ret %d.\n", addr, rd_len, i, + ret); + continue; + } else { + DFD_VERBOS("dfd_fpga_buf_read addr 0x%x rd_len %d success.\n", addr, rd_len); + return 0; + } + } + + DFD_VERBOS("dfd_fpga_buf_read addr 0x%x rd_len %d i %d failed ret %d.\n", addr, rd_len, i, ret); + return -1; +} + + +/* Configuring boot Access */ +static int dfd_fpga_upg_set_access(dfd_pci_dev_priv_t *pci_priv, int cmd) +{ + int ret; + int val; + int addr; + + addr = pci_priv->fpga_upg_base + FPGA_UPG_INSTRUCTION_REG; + val = cmd; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -1; + } + + + addr = pci_priv->fpga_upg_base + FPGA_UPG_SPI_CTRL_REG; + val = FPGA_UPG_ACCESS_ENABLE; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -1; + } + + DFD_VERBOS("Success: cmd %d.\n", cmd); + return 0; +} + +static int dfd_fpga_upg_reset(dfd_pci_dev_priv_t *pci_priv) +{ + int ret; + int val; + int addr; + + addr = pci_priv->fpga_upg_base + FPGA_UPG_SPI_CTRL_REG; + val = FPGA_UPG_STATUS_RESET; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -1; + } + + DFD_VERBOS("Success: reset %d.\n", val); + return 0; +} + +/* Whether the SPI port is idle. 0 indicates idle, and 1 indicates busy */ +static int dfd_fpga_upg_get_status(dfd_pci_dev_priv_t *pci_priv, char *status) +{ + int ret; + int val; + int addr; + + addr = pci_priv->fpga_upg_base + FPGA_UPG_STATUS_REG; + ret = dfd_fpga_upg_read_word(pci_priv, addr, &val); + DFD_VERBOS("dfd_fpga_upg_read_word return.\n"); + if (ret) { + DFD_ERROR("dfd_fpga_upg_read_word addr 0x%x failed ret %d.\n", addr, ret); + return -1; + } + + *status = val & FPGA_UPG_STATUS_MASK; + DFD_VERBOS("Success: val %d status %d.\n", val, *status); + return 0; +} + +/* Wait for the SPI port to become idle */ +static int dfd_fpga_upg_wait_ready(dfd_pci_dev_priv_t *pci_priv) +{ + int timeout; + char status; + int ret; + + timeout = FPGA_UPG_RETRY_CNT; + while (timeout--) { + DFD_VERBOS("timeout %d.\n", timeout); + ret = dfd_fpga_upg_get_status(pci_priv, &status); + if (ret) { + DFD_ERROR("dfd_fpga_upg_get_status failed ret %d.\n", ret); + continue; + } + + DFD_VERBOS("timeout %d status %d.\n", timeout, status); + /* Determine whether to be idle */ + if (!status) { + DFD_VERBOS("FPGA SPI READY.\n"); + return 0; + } + usleep(FPGA_UPG_RETRY_SLEEP_TIME); + } + + return -2; +} + +/* Configure the FPGA upgrade write function */ +static int dfd_fpga_upg_set_wr_enable(dfd_pci_dev_priv_t *pci_priv) +{ + int ret; + int cmd; + + cmd = FPGA_UPG_INSTRUTION_WREN; + ret = dfd_fpga_upg_set_access(pci_priv, cmd); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_access cmd %d failed ret %d.\n", cmd, ret); + return -1; + } + + DFD_VERBOS("Success.\n"); + return 0; +} + +/* get SPI's STATUS register */ +static int dfd_fpga_upg_get_spi_status(dfd_pci_dev_priv_t *pci_priv, char *status) +{ + int ret; + int val; + int addr; + int cmd; + + cmd = FPGA_UPG_INSTRUTION_RDSR; + ret = dfd_fpga_upg_set_access(pci_priv, cmd); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_access cmd %d failed ret %d.\n", cmd, ret); + return -1; + } + + addr = pci_priv->fpga_upg_base + FPGA_UPG_RD_FLASH_STATUS_REG; + ret = dfd_fpga_upg_read_word(pci_priv, addr, &val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_read_word addr 0x%x failed ret %d.\n", addr, ret); + return -1; + } + + ret = dfd_fpga_upg_reset(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_reset failed ret %d.\n", ret); + return -1; + } + + *status = val & FPGA_UPG_SPI_STATUS_MASK; + DFD_VERBOS("Success: val %d spi_status %d.\n", val, *status); + return 0; +} + +/* waiting for SPI chip opreation to complete */ +static int dfd_fpga_wait_spi_ready(dfd_pci_dev_priv_t *pci_priv) +{ + int timeout; + char status; + int ret; + + timeout = FPGA_UPG_WAIT_SPI_RETRY_CNT; + while (timeout--) { + DFD_VERBOS("timeout %d.\n", timeout); + ret = dfd_fpga_upg_get_spi_status(pci_priv, &status); + if (ret) { + DFD_ERROR("dfd_fpga_upg_get_spi_status failed ret %d.\n", ret); + continue; + } + DFD_VERBOS("timeout %d status %d.\n", timeout, status); + /* assert whether it is free */ + if (!status) { + DFD_VERBOS("SPI CHIP READY.\n"); + return 0; + } + usleep(FPGA_UPG_RETRY_SLEEP_TIME); + } + + return -2; +} + +/* Erase the entire chip */ +static int dfd_fpga_upg_set_erase_all(dfd_pci_dev_priv_t *pci_priv) +{ + int ret; + int cmd; + + /* waiting for FPGA's SPI port to become free */ + ret = dfd_fpga_upg_wait_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -1; + } + + /* configure write enable */ + ret = dfd_fpga_upg_set_wr_enable(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_wr_enable failed ret %d.\n", ret); + return -1; + } + + cmd = FPGA_UPG_INSTRUTION_BE; + ret = dfd_fpga_upg_set_access(pci_priv, cmd); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_access cmd %d failed ret %d.\n", cmd, ret); + return -1; + } + + /* Hardware requirements, delay 1s */ + sleep(1); + + /* Waiting for the SPI chip operation to complete */ + ret = dfd_fpga_wait_spi_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready sslot %d unit %d failed ret %d.\n", ret); + return -1; + } + + ret = dfd_fpga_upg_reset(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_reset failed ret %d.\n", ret); + return -1; + } + + DFD_VERBOS("Success.\n"); + return 0; +} + +/* Erase sector (256 pages, 64k in total) */ +int dfd_fpga_upg_set_erase_sector(dfd_pci_dev_priv_t *pci_priv, int spi_addr) +{ + int ret; + int cmd, val, addr; + + DFD_VERBOS("Enter spi_addr 0x%x.\n", spi_addr); + + /* waiting for FPGA's SPI port to become free*/ + ret = dfd_fpga_upg_wait_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -1; + } + + /* Start write enable */ + ret = dfd_fpga_upg_set_wr_enable(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_wr_enable failed ret %d.\n", ret); + return -1; + } + + /* Write erase address */ + val = spi_addr; + addr = pci_priv->fpga_upg_base + FPGA_UPG_ADDR_REG; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -1; + } + + /* Start sector erase? */ + cmd = FPGA_UPG_INSTRUTION_SE; + ret = dfd_fpga_upg_set_access(pci_priv, cmd); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_access cmd %d failed ret %d.\n", cmd, ret); + return -1; + } + + /* hardware requirment ,delay 500ms */ + usleep(500 * 1000); + + /* waiting for SPI chip operation to complete */ + ret = dfd_fpga_wait_spi_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -1; + } + + ret = dfd_fpga_upg_reset(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_reset failed ret %d.\n", ret); + return -1; + } + + DFD_VERBOS("Success.\n"); + + return 0; +} + +/* eara 4k area */ +int dfd_fpga_upg_set_erase_p4e(dfd_pci_dev_priv_t *pci_priv, int spi_addr) +{ + int ret; + int cmd, val, addr; + + DFD_VERBOS("Enter spi_addr 0x%x.\n", spi_addr); + + /* waiting for FPGA's SPI port to become free */ + ret = dfd_fpga_upg_wait_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -1; + } + + /* start write enable */ + ret = dfd_fpga_upg_set_wr_enable(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_wr_enable failed ret %d.\n", ret); + return -1; + } + + /* write erase address */ + val = spi_addr; + addr = pci_priv->fpga_upg_base + FPGA_UPG_ADDR_REG; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -1; + } + + /* start 4k erase */ + cmd = FPGA_UPG_INSTRUTION_P4E; + ret = dfd_fpga_upg_set_access(pci_priv, cmd); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_access cmd %d failed ret %d.\n", cmd, ret); + return -1; + } + + /* hardware requirment,delay 200ms */ + usleep(200 * 1000); + + /* waiting for SPI chip operation to complete */ + ret = dfd_fpga_wait_spi_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -1; + } + + ret = dfd_fpga_upg_reset(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_reset failed ret %d.\n", ret); + return -1; + } + + DFD_VERBOS("Success.\n"); + + return 0; +} + +static int dfd_fpga_upg_program(dfd_pci_dev_priv_t *pci_priv, int spi_addr, char *buf, int len) +{ + int ret; + int addr; + int val; + int cmd; + int step; + int wr_len; + + /* Write data to upgrade content register */ + step = 1; + #if 0 + /* FPGA temporarily only supports 4 bytes of read and write */ + for (i = 0; i < len; i += 4) { + addr = pci_priv->fpga_upg_base + i; + wr_len = ((i + 4) <= len) ? (4) : (len - i); + DFD_VERBOS("dfd_fpga_buf_write sslot %d unit %d i %d addr 0x%x wr_len %d.\n", + dst->sslot, dst->unit, i, addr, wr_len); + ret = dfd_fpga_upg_buf_write(dst, addr, (uint8_t*)&buf[i], wr_len); + if (ret) { + DFD_ERROR("dfd_fpga_upg_buf_write addr 0x%x wr_len %d failed ret %d.\n", addr, len, ret); + return -1; + } + } + #else + addr = pci_priv->fpga_upg_base; + wr_len = len; + DFD_VERBOS("dfd_fpga_buf_write addr 0x%x wr_len %d.\n", addr, wr_len); + ret = dfd_fpga_upg_buf_write(pci_priv, addr, (uint8_t*)buf, wr_len); + if (ret) { + DFD_ERROR("dfd_fpga_upg_buf_write addr 0x%x wr_len %d failed ret %d.\n", addr, len, ret); + return -1; + } + #endif + + /* Write length register */ + step++; + val = FPGA_UPG_CONTENT_LENGTH;/* Fpga is always written in 256 length */ + addr = pci_priv->fpga_upg_base + FPGA_UPG_LENGTH_REG; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -step; + } + + /* write address register */ + step++; + val = spi_addr; + addr = pci_priv->fpga_upg_base + FPGA_UPG_ADDR_REG; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -step; + } + + /* Start writing upgrade data to SPI */ + step++; + cmd = FPGA_UPG_INSTRUTION_PP; + ret = dfd_fpga_upg_set_access(pci_priv, cmd); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_access cmd %d failed ret %d.\n", cmd, ret); + return -step; + } + + /* Wait for the SPI port of FPGA to recover from idle */ + step++; + ret = dfd_fpga_upg_wait_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -step; + } + + step++; + ret = dfd_fpga_upg_reset(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_reset failed ret %d.\n", ret); + return -step; + } + + return 0; +} + +/** + * dfd_fpga_upg_write -write operation interface provided to upgrade module + * @dst: the data structure of sslot and unit corresponding to the target chip to be upgraded + * @addr: write address (must ensure 256-byte alignment) + * @buf: write address buffer + * @len: Write length (when upgrading, 256 bytes of data must be written every time, only the last set of data can be less than 256) + * return: return 0 if success,else return failure + * + */ +int dfd_fpga_upg_write(dfd_pci_dev_priv_t *pci_priv, int addr, char *buf, int len) +{ + int ret; + int step; + + /* address must be 256-byte alignment */ + step = 1; + if ((pci_priv == NULL) || (buf == NULL) || (addr & 0xff) || (len > 256)) { + DFD_ERROR("Input para invalid pci_priv %p buf %p addr 0x%x len %d.\n", pci_priv, buf, addr, len); + return -step; + } + + DFD_VERBOS("Enter: addr 0x%x len %d.\n", addr, len); + + /* waiting for FPGA's SPI port to become free */ + step++; + ret = dfd_fpga_upg_wait_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -step; + } + + /* configure write enable */ + step++; + ret = dfd_fpga_upg_set_wr_enable(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_wr_enable failed ret %d.\n", ret); + return -step; + } + + /* write upgrade data */ + step++; + ret = dfd_fpga_upg_program(pci_priv, addr, buf, len); + if (ret) { + DFD_ERROR("dfd_fpga_upg_program addr 0x%x len %d failed ret %d.\n", addr, len, ret); + return -step; + } + + DFD_VERBOS("Success: addr 0x%x len %d.\n", addr, len); + return 0; +} + +static int dfd_fpga_upg_fast_read(dfd_pci_dev_priv_t *pci_priv, int spi_addr, char *buf, int len) +{ + int ret; + uint32_t val; + int addr; + int cmd; + int step; + + step = 0; + + /* clear register value */ + step++; + addr = pci_priv->fpga_upg_base; + ret = dfd_fpga_upg_buf_write(pci_priv, addr, buf, len); + if (ret) { + DFD_ERROR("dfd_fpga_upg_buf_write addr 0x%x len %d failed ret %d.\n", addr, len, ret); + return -step; + } + /* write length register */ + step++; + val = FPGA_UPG_CONTENT_LENGTH; + addr = pci_priv->fpga_upg_base + FPGA_UPG_LENGTH_REG; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -step; + } + + /* write address register */ + step++; + val = spi_addr; + addr = pci_priv->fpga_upg_base + FPGA_UPG_ADDR_REG; + ret = dfd_fpga_upg_write_word(pci_priv, addr, val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_write_word addr 0x%x val 0x%x failed ret %d.\n", addr, val, ret); + return -step; + } + + /* start reading SPI data */ + step++; + cmd = FPGA_UPG_INSTRUTION_FR; + ret = dfd_fpga_upg_set_access(pci_priv, cmd); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_access cmd %d failed ret %d.\n", cmd, ret); + return -step; + } + + /* waiting for FPGA's SPI port to become free */ + step++; + ret = dfd_fpga_upg_wait_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -step; + } + + + /* Read upgrade content register to buffer */ + step++; + + /* FPGA temporarily only supports 4 bytes of read and write */ + #if 1 + addr = pci_priv->fpga_upg_base; + ret = dfd_fpga_upg_buf_read(pci_priv, addr, (uint8_t*)buf, len); + if (ret) { + DFD_ERROR("dfd_fpga_upg_buf_read addr 0x%x len %d failed ret %d.\n", addr, len, ret); + return -step; + } + + step++; + ret = dfd_fpga_upg_reset(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_reset failed ret %d.\n", ret); + return -step; + } + + #else + for (i = 0; i < len; i += 4) { + addr = pci_priv->fpga_upg_base + i; + rd_len = ((i + 4) <= len) ? (4) : (len - i); + DFD_VERBOS("dfd_fpga_upg_buf_read sslot %d unit %d i %d addr 0x%x rd_len %d.\n", + dst->sslot, dst->unit, i, addr, rd_len); + ret = dfd_fpga_upg_buf_read(dst, addr, (uint8_t*)(&buf[i]), rd_len); + if (ret) { + DFD_ERROR("dfd_fpga_upg_buf_read addr 0x%x rd_len %d failed ret %d.\n", addr, rd_len, ret); + return -step; + } + + for (j = 0; j < rd_len; j++) { + DFD_VERBOS("buf[%d]: 0x%x.\n", i, buf[i]); + } + } + #endif + + return 0; +} + +/** + * dfd_fpga_upg_read -read operation interface provided to upgrade module + * @dst: the data structure of sslot and unit corresponding to the target chip + * @addr: read address (must ensure 256-byte alignment) + * @buf: buffer for reading data + * @len: read length (the data read each time must be 256 bytes, only the last time can be less than 256 bytes) + * return: return 0 if success,else return failure + * + */ +int dfd_fpga_upg_read(dfd_pci_dev_priv_t *pci_priv, int addr, char *buf, int len) +{ + int ret; + int step; + + /* address must be 256-byte alignment */ + step = 1; + if ((pci_priv == NULL) || (buf == NULL) || (addr & 0xff) || (len > 256)) { + DFD_ERROR("Input para invalid pci_priv %p buf %p addr 0x%x len %d.\n", pci_priv, buf, addr, len); + return -step; + } + + DFD_VERBOS("Enter: addr 0x%x len %d.\n", addr, len); + + /* waiting for FPGA's SPI port to become free */ + step++; + ret = dfd_fpga_upg_wait_ready(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_wait_ready failed ret %d.\n", ret); + return -step; + } + + /* configure write enable */ + step++; + ret = dfd_fpga_upg_set_wr_enable(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_wr_enable failed ret %d.\n", ret); + return -step; + } + + /* read upgrade data */ + step++; + ret = dfd_fpga_upg_fast_read(pci_priv, addr, buf, len); + if (ret) { + DFD_ERROR("dfd_fpga_upg_fast_read addr 0x%x len %d failed ret %d.\n", addr, len, ret); + return -step; + } + + DFD_VERBOS("Success: addr 0x%x len %d.\n", addr, len); + return 0; + +} + +/** + * dfd_fpga_upg_hw_init -upgrade initialization interface provided to the upgrade module (call before starting the upgrade) + * @dst: the data structure of sslot and unit corresponding to the target chip to be upgraded + * return: return 0 if success,else return failure + * Before the interface returns, it will actively delay 1s (required by FPGA) + */ +int dfd_fpga_upg_hw_init(dfd_pci_dev_priv_t *pci_priv) +{ + int ret; + + ret = dfd_fpga_upg_set_erase_all(pci_priv); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_wr_enable failed ret %d.\n", ret); + return -2; + } + + DFD_VERBOS("Success.\n"); + return 0; +} + +static int dfd_fpga_upgrade_get_fpga_version(dfd_pci_dev_priv_t *pci_priv, int *ver) +{ + int addr; + int ret; + int val; + + addr = DFD_FPGA_VERSION_REG; + ret = dfd_fpga_upg_read_word(pci_priv, addr, &val); + if (ret) { + DFD_ERROR("dfd_fpga_upg_read_word addr 0x%x failed ret %d.\n", addr, ret); + return -1; + } + + *ver = val; + DFD_VERBOS("ver 0x%x.\n", *ver); + return 0; +} + +unsigned long dfd_fpga_upg_get_file_size(const char *path) +{ + unsigned long filesize; + struct stat statbuff; + + if(stat(path, &statbuff) < 0){ + filesize = -1; + } else{ + filesize = statbuff.st_size; + } + + DFD_VERBOS("file %s size is %lu.\n", path, filesize); + return filesize; +} + +static int dfd_fpga_address_init(void) +{ + int fw_version; + int ret; + + ret = dfd_fpga_upg_read_word(current_pci_priv, FPGA_VER_ADDRESS, &fw_version); + switch (FPGA_VERSION(fw_version)) { + case FPGA_VER_00: + case FPGA_VER_02: + case FPGA_VER_03: + case FPGA_VER_06: + current_pci_priv->fpga_upg_base = FPGA_UPG_CONTENT_BASE_REG_A00; + break; + case FPGA_VER_05: + current_pci_priv->fpga_upg_base = FPGA_UPG_CONTENT_BASE_REG_E00; + break; + default: + current_pci_priv->fpga_upg_base = FPGA_UPG_CONTENT_BASE_REG_A00; + break; + } + return ret; +} + + +static int dfd_fpga_device_init(void) +{ + current_pci_priv = &default_pci_priv; + if (drv_get_my_dev_type() == 0x4075){ + current_pci_priv->pcibus = 1; /* ATS48's pcie channel is 1 */ + } + + return dfd_fpga_address_init(); +} + +/** + * dfd_fpga_pkt_init -DFD FPGA driver library initialization interface (if you need to use DFD FPGA driver, you must initialize first) + * return: return 0 if success,else return failure + */ + +int dfd_fpga_upg_init(void) +{ + int ret; + static int flag; + + if (flag) { + DFD_VERBOS("Already init.\n"); + return 0; + } + + /* debug initialization */ + dfd_fpga_debug_init(); + + ret = dfd_fpga_device_init(); + if (ret) { + DFD_ERROR("dfd_fpga_upg_init failed ret %d.\n", ret); + return ret; + } + + flag = 1; + return 0; +} + +int dfd_fpga_erase64_sector(dfd_pci_dev_priv_t *pci_priv, int offset) +{ + int ret; + ret = -1; + + if ((offset % DFD_FPGA_SPI_SECTOR_SIZE) == 0) { + DFD_VERBOS("erase 64k area, offset 0x%x.\n", offset); + ret = dfd_fpga_upg_set_erase_sector(pci_priv, offset); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_erase_sector offset 0x%x failed ret %d.\n", offset, ret); + return ret; + } + } + DFD_ERROR("Input para invalid, offset 0x%x.\n", offset); + return ret; +} + +int dfd_fpga_upgrade_test(void) +{ + int ret, i, j, offset, num, len, res, retry; + char wbuf[DFD_FPGA_SPI_SECTOR_SIZE]; + char rbuf[DFD_FPGA_UPGRADE_BUFF_SIZE]; + + offset = DFD_FPGA_BASE_TEST_ADD; + len = DFD_FPGA_UPGRADE_BUFF_SIZE; + dfd_pci_dev_priv_t *pci_priv; + dfd_fpga_upg_init(); + + if (current_pci_priv == NULL) { + printf("fpga test input para invalid pci_priv %p.\n", current_pci_priv); + return -DFD_RV_INIT_ERR; + } + pci_priv = current_pci_priv; + + memset(wbuf, 0, DFD_FPGA_SPI_SECTOR_SIZE); + /* get random data */ + for (j = 0; j < DFD_FPGA_SPI_SECTOR_SIZE; j++) { + num = rand() % 256; + wbuf[j] = num & 0xff; + } + ret = dfd_fpga_erase64_sector(pci_priv, offset); + if (ret) { + goto exit; + } + + for (i = 0; i < DFD_FPGA_UPGRADE_BUFF_SIZE; i++) { + memset(rbuf, 0, DFD_FPGA_UPGRADE_BUFF_SIZE); + /* write data first */ + ret = dfd_fpga_upg_write(pci_priv, offset, &wbuf[i * DFD_FPGA_UPGRADE_BUFF_SIZE], len); + if (ret) { + DFD_ERROR("fpga upg write offset 0x%x len %d failed ret %d.\n", offset, len, ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } else { + DFD_VERBOS("page %d upg write offset 0x%x len %d success.\n", i, offset, len); + } + + /* go back to read the data*/ + for (retry = 0; retry < FPGA_RETRY_TIMES; retry++) { /*retry 3 times*/ + ret = dfd_fpga_upg_read(pci_priv, offset, rbuf, len); + res = memcmp(rbuf, &wbuf[i * DFD_FPGA_UPGRADE_BUFF_SIZE], len); + if (ret || res) { + usleep(1000); + continue; + } + break; + } + if (ret) { + DFD_ERROR("fpga upg read offset 0x%x len %d failed ret %d.\n", offset, len, ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } else { + DFD_VERBOS("page %d upg read offset 0x%x len %d success.\n", i, offset, len); + } + + if (res) { + DFD_ERROR("rbuf wbuf not equal, len %d, check failed.\n", len); + DFD_ERROR("wbuf: \n"); + dfd_utest_printf_reg((uint8_t*)wbuf, len); + DFD_ERROR("rbuf: \n"); + dfd_utest_printf_reg((uint8_t*)rbuf, len); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + + offset += len; + } + + offset = DFD_FPGA_BASE_TEST_ADD; + ret = dfd_fpga_erase64_sector(pci_priv, offset); + if (ret) { + goto exit; + } +exit: + return ret; +} + +static int dfd_fpga_upgrade_do_upgrade_onetime(dfd_pci_dev_priv_t *pci_priv, int fd, unsigned long filesize) +{ + int ret, res; + int i, len, read_len, retry; + char wbuf[DFD_FPGA_UPGRADE_BUFF_SIZE]; + char rbuf[DFD_FPGA_UPGRADE_BUFF_SIZE]; + int offset; + + if (current_pci_priv == NULL) { + DFD_ERROR("Input para invalid pci_priv %p.\n", pci_priv); + return -DFD_RV_INDEX_INVALID; + } + +#if 0 + /* handle before upgrading */ + ret = dfd_fpga_upg_do_pre(dst, filesize); + if (ret) { + DFD_ERROR("fpga hw init failed ret %d.\n", ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } +#endif + + i = 0; + offset = DFD_FPGA_UPDATE_BOOT_ADDR; + ret = lseek(fd, 0, SEEK_SET); + if (ret == -1) { + DFD_ERROR("seek file failed ret %d.\n", ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + while(1) { + len = DFD_FPGA_UPGRADE_BUFF_SIZE; +#if 0 + if ((offset % DFD_FPGA_ERASE_P4E_SIZE) == 0) { + DFD_VERBOS("erase 4k area, offset 0x%x.\n", offset); + ret = dfd_fpga_upg_set_erase_p4e(dst, offset); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_erase_p4e offset 0x%x failed ret %d.\n", offset, ret); + goto exit; + } + } +#else + if ((offset % DFD_FPGA_SPI_SECTOR_SIZE) == 0) { + DFD_VERBOS("erase 64k area, offset 0x%x.\n", offset); + ret = dfd_fpga_upg_set_erase_sector(pci_priv, offset); + if (ret) { + DFD_ERROR("dfd_fpga_upg_set_erase_sector offset 0x%x failed ret %d.\n", offset, ret); + goto exit; + } + } +#endif + + memset(wbuf, 0, DFD_FPGA_UPGRADE_BUFF_SIZE); + read_len = read(fd, wbuf, len); + i++; + if ((read_len > 0) && (read_len <= len)) { + /* write data first */ + ret = dfd_fpga_upg_write(pci_priv, offset, wbuf, read_len); + if (ret) { + DFD_ERROR("fpga upg write offset 0x%x len %d failed ret %d.\n", offset, read_len, ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } else { + DFD_VERBOS("page %d upg write offset 0x%x len %d success.\n", i, offset, read_len); + } + + /* go back to read data */ + for (retry = 0; retry < FPGA_RETRY_TIMES; retry++) { /*retry 3 times*/ + memset(rbuf, 0, DFD_FPGA_UPGRADE_BUFF_SIZE); + ret = dfd_fpga_upg_read(pci_priv, offset, rbuf, read_len); + res = memcmp(rbuf, wbuf, read_len); + if (ret || res) { + usleep(1000); + continue; + } + break; + } + if (ret) { + DFD_ERROR("fpga upg read offset 0x%x len %d failed ret %d.\n", offset, read_len, ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } else { + DFD_VERBOS("page %d upg read offset 0x%x len %d success.\n", i, offset, read_len); + } + + if (res) { + DFD_ERROR("rbuf wbuf not equal, read_len %d, check failed.\n", read_len); + DFD_ERROR("wbuf: \n"); + dfd_utest_printf_reg((uint8_t*)wbuf, read_len); + DFD_ERROR("rbuf: \n"); + dfd_utest_printf_reg((uint8_t*)rbuf, read_len); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + + DFD_VERBOS("page %d upg check offset 0x%x len %d success.\n", i, offset, read_len); + offset += read_len; + if (read_len != len) { + DFD_VERBOS("page %d read_len %d len %d, last page exit.\n", i, read_len, len); + break; + } + } else if (read_len == 0) { + DFD_VERBOS("read_len %d exit.\n", read_len); + break; + } else { + DFD_ERROR("len %d read_len %d, read failed, errno(%s).\n", len, read_len, strerror(errno)); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + } + +#if 0 + ret = dfd_fpga_upg_do_post(dst); + if (ret) { + DFD_ERROR("dfd_fpga_upg_do_post dst->sslot %d dst->unit %d failed ret %d.\n", dst->sslot, + dst->unit, ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } +#endif + + ret = 0; + DFD_VERBOS("Update success.\n"); +exit: + return ret; +} + +/* external FPGA upgrade interface */ +int dfd_fpga_upgrade_do_upgrade(char* upg_file) +{ + int ret; + int i; + int cnt; + unsigned long filesize; + int fd; + + DFD_VERBOS("Enter.\n"); + + if (upg_file == NULL) { + DFD_ERROR("Input para invalid upg_file %p.\n", upg_file); + return -DFD_RV_INDEX_INVALID; + } + + dfd_fpga_upg_init(); + + filesize = dfd_fpga_upg_get_file_size(upg_file); + if (filesize <= 0) { + DFD_ERROR("invalid filesize %lu.\n", filesize); + return -DFD_RV_DEV_FAIL; + } + + fd = open(upg_file, O_RDONLY); + if (fd < 0) { + DFD_ERROR("open file[%s] fail.\n", upg_file); + return -DFD_RV_DEV_FAIL; + } + + i = 0; + cnt = DFD_FPGA_UPGADE_RETRY_CNT; + while(i < cnt) { + ret = dfd_fpga_upgrade_do_upgrade_onetime(current_pci_priv, fd, filesize); + if (ret) { + i++; + DFD_ERROR("dfd_fpga_upgrade_do_upgrade_onetime upg_file %s failed ret %d.\n", upg_file, ret); + continue; + } else { + DFD_ERROR("dfd_fpga_upgrade_do_upgrade_onetime upg_file %s success.\n", upg_file); + close(fd); + return 0; + } + } + + DFD_ERROR("upg_file %s failed ret %d.\n", upg_file, ret); + close(fd); + return ret; +} + +static int dfd_fpga_upgrade_do_upgrade_onetime_all(dfd_pci_dev_priv_t *pci_priv, char* upg_file) +{ + int ret; + int i, len, fd, read_len; + char wbuf[DFD_FPGA_UPGRADE_BUFF_SIZE]; + char rbuf[DFD_FPGA_UPGRADE_BUFF_SIZE]; + int offset; + + DFD_VERBOS("Update upg_file: %s.\n", upg_file); + + if ((current_pci_priv == NULL) || (upg_file == NULL)) { + DFD_ERROR("Input para invalid pci_priv %p upg_file %p.\n", pci_priv, upg_file); + return -DFD_RV_INDEX_INVALID; + } + + fd = open(upg_file, O_RDONLY); + if (fd < 0) { + DFD_ERROR("open file[%s] fail.\n", upg_file); + return -DFD_RV_DEV_FAIL; + } + + /* Before upgrading, first initialize the configuration and erase the entire SPI chip */ + ret = dfd_fpga_upg_hw_init(pci_priv); + if (ret) { + DFD_ERROR("fpga hw init failed ret %d.\n", ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + + i = 0; + offset = 0; + while(1) { + len = DFD_FPGA_UPGRADE_BUFF_SIZE; + memset(wbuf, 0, DFD_FPGA_UPGRADE_BUFF_SIZE); + read_len = read(fd, wbuf, len); + i++; + if ((read_len > 0) && (read_len <= len)) { + /* write data first */ + ret = dfd_fpga_upg_write(pci_priv, offset, wbuf, read_len); + if (ret) { + DFD_ERROR("fpga upg write offset 0x%x len %d failed ret %d.\n", offset, read_len, ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } else { + DFD_VERBOS("page %d upg write offset 0x%x len %d success.\n", i, offset, read_len); + } + + /* go back to read data */ + memset(rbuf, 0, DFD_FPGA_UPGRADE_BUFF_SIZE); + ret = dfd_fpga_upg_read(pci_priv, offset, rbuf, read_len); + if (ret) { + DFD_ERROR("fpga upg read offset 0x%x len %d failed ret %d.\n", offset, read_len, ret); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } else { + DFD_VERBOS("page %d upg read offset 0x%x len %d success.\n", i, offset, read_len); + } + + if (memcmp(rbuf, wbuf, read_len)) { + DFD_ERROR("rbuf wbuf not equal, read_len %d, check failed.\n", read_len); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + + DFD_VERBOS("page %d upg check offset 0x%x len %d success.\n", i, offset, read_len); + offset += read_len; + if (read_len != len) { + DFD_VERBOS("page %d read_len %d len %d, last page exit.\n", i, read_len, len); + break; + } + } else if (read_len == 0) { + DFD_VERBOS("read_len %d exit.\n", read_len); + break; + } else { + DFD_ERROR("len %d read_len %d, read failed.\n", len, read_len); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + } + + ret = 0; + DFD_VERBOS("Update upg_file: %s success.\n", upg_file); +exit: + close(fd); + return ret; +} + +int dfd_fpga_upgrade_do_upgrade_all(char* upg_file) +{ + int ret; + int i; + int cnt; + + DFD_VERBOS("Enter.\n"); + + if (upg_file == NULL) { + DFD_ERROR("Input para invalid upg_file %p.\n", upg_file); + return -DFD_RV_INDEX_INVALID; + } + + dfd_fpga_upg_init(); + + i = 0; + cnt = DFD_FPGA_UPGADE_RETRY_CNT; + while(i < cnt) { + ret = dfd_fpga_upgrade_do_upgrade_onetime_all(current_pci_priv, upg_file); + if (ret) { + i++; + DFD_ERROR("dfd_fpga_upgrade_do_upgrade_onetime upg_file %s failed ret %d.\n", upg_file, ret); + continue; + } else { + DFD_ERROR("dfd_fpga_upgrade_do_upgrade_onetime upg_file %s success.\n", upg_file); + return 0; + } + } + + DFD_ERROR("upg_file %s failed ret %d.\n", upg_file, ret); + return ret; +} + + + +/* External fpga dump interface */ +int dfd_fpga_upgrade_dump_flash(int argc, char* argv[]) +{ + int offset, addr, len, dlen; + int size, cnt, i; + char *stopstring; + int ret, fd; + char filename[DFD_FPGA_UPGRADE_BUFF_SIZE]; + char is_print; + char buf[DFD_FPGA_UPGRADE_BUFF_SIZE]; + dfd_pci_dev_priv_t *pci_priv; + + ret = DFD_RV_OK; + if (argc != 6) { + printf("fpga dump flash Input invalid.\n"); + return -DFD_RV_INDEX_INVALID; + } + + dfd_fpga_upg_init(); + + if (current_pci_priv == NULL) { + printf("fpga dump flash Input para invalid pci_priv %p.\n", current_pci_priv); + return -DFD_RV_INIT_ERR; + } + + offset = strtol(argv[3], &stopstring, 16); + size = strtol(argv[4], &stopstring, 16); + + if (strcmp(argv[5], "print") != 0) { + is_print = 0; + memset(filename, 0, DFD_FPGA_UPGRADE_BUFF_SIZE); + strncpy(filename, argv[5], (DFD_FPGA_UPGRADE_BUFF_SIZE - 1)); + fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXG|S_IRWXU|S_IRWXO); + if (fd < 0) { + printf("open file %s fail(err:%d)!\r\n", filename, errno); + ret = -DFD_RV_DEV_FAIL; + goto exit; + } + } else { + is_print = 1; + } + + pci_priv = current_pci_priv; + cnt = size / DFD_FPGA_UPGRADE_BUFF_SIZE; + if (size % DFD_FPGA_UPGRADE_BUFF_SIZE) { + cnt++; + } + len = DFD_FPGA_UPGRADE_BUFF_SIZE; + printf("cnt %d.\n", cnt); + for (i = 0; i < cnt; i++) { + memset(buf, 0, len); + addr = offset + i * DFD_FPGA_UPGRADE_BUFF_SIZE; + if (i == (cnt - 1)) { + dlen = size - len * i; + if (dlen > len) { + printf("dlen %d len %d error.\n", dlen, len); + } + } else { + dlen = len; + } + ret = dfd_fpga_upg_read(pci_priv, addr, buf, dlen); + if (ret < 0) { + printf("addr 0x%x failed ret %d\n", addr, ret); + goto exit_close; + } + if (is_print) { + dfd_utest_printf_reg((uint8_t*)buf, dlen); + } else { + ret = write(fd, buf, dlen); + if (ret < 0) { + printf("write failed (errno: %d).\n", errno); + ret = -DFD_RV_DEV_FAIL; + goto exit_close; + } + } + } + +exit_close: + if (!is_print) { + close(fd); + } +exit: + return ret; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/firmware_app_ispvme.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/firmware_app_ispvme.c new file mode 100644 index 000000000000..fc6e3cd9a9ec --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/firmware_app_ispvme.c @@ -0,0 +1,1870 @@ +/** + * Copyright(C) 2013 Ragile Network. All rights reserved. + */ +/* + * firmware_app.c + * Original Author : support@ragilenetworks.com, 2013-10-23 + * + * firmware upgrade + * + * History + * v1.0 chenwendai(support@ragilenetworks.com) 2013-10-23 Initial version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if 0 +#include +#include +#endif +#include +static firmware_card_info_t g_card_info[] = { + { + .dev_type = B6510_48VS8CQ, + .slot_num = 1, + .card_name = "B6510-48VS8CQ", + .gpio_info = { + /* slot 0 */ + { + .tdi = 32, + .tck = 65, + .tms = 6, + .tdo = 67, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = B6510_32CQ, + .slot_num = 1, + .card_name = "B6510_32CQ", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = B6520_64CQ, + .slot_num = 1, + .card_name = "B6520-64CQ", + .gpio_info = { + /* slot 0 */ + { + .tdi = 32, + .tck = 65, + .tms = 6, + .tdo = 67, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = AS13_48F8H, + .slot_num = 1, + .card_name = "as13_48f8h", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = AS13_32H, + .slot_num = 1, + .card_name = "as13_32h", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + { + .dev_type = AC51_48C2G, + .slot_num = 2, + .card_name = "ac51_48c2g", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 39, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + }, + { + .dev_type = AS14_128H, + .slot_num = 5, + .card_name = "as14_128h", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 39, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 69, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 70, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 71, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = AS23_128H, + .slot_num = 5, + .card_name = "as23_128h", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 39, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 69, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 70, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 71, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = AS14_32D, + .slot_num = 5, + .card_name = "AS14-32D", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 39, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 69, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 70, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 71, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 0,1) + .jtag_1 = GPIO(48, 1,1) + }, + }, + }, + + + { + .dev_type = AS14_40D, + .slot_num = 5, + .card_name = "AS14-40D", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 1,1) + .jtag_1 = GPIO(48, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 1,1) + .jtag_1 = GPIO(48, 0,1) + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 0,1) + .jtag_1 = GPIO(48, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 0,1) + .jtag_1 = GPIO(48, 0,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 0,1) + .jtag_1 = GPIO(48, 0,1) + }, + }, + }, + + { + .dev_type = AS24_128D, + .slot_num = 6, + .card_name = "AS24-128D", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 1,1) + .jtag_1 = GPIO(48, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 1,1) + .jtag_1 = GPIO(48, 0,1) + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 0,1) + .jtag_1 = GPIO(48, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 1,1) + .jtag_2 = GPIO(39, 0,1) + .jtag_1 = GPIO(48, 0,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 0,1) + .jtag_2 = GPIO(39, 1,1) + .jtag_1 = GPIO(48, 1,1) + }, + /* slot 5 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(71, 0,1) + .jtag_4 = GPIO(70, 0,1) + .jtag_3 = GPIO(69, 0,1) + .jtag_2 = GPIO(39, 1,1) + .jtag_1 = GPIO(48, 0,1) + }, + }, + }, + + { + .dev_type = B6920_4C, + .slot_num = 5, + .card_name = "B6920-4C", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 39, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 69, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 70, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 71, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + }, + + { + .dev_type = B6920_4C_V2, + .slot_num = 1, + .card_name = "B6920-4C-V2", + .gpio_info = { + { + .tdi = 7, + .tck = 10, + .tms = 5, + .tdo = 6, + .jtag_en = 9, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + }, + { + .dev_type = B6930_32CDQ2XS, + .slot_num = 1, + .card_name = "B6930-32CDQ2XS", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = BT2575, + .slot_num = 1, + .card_name = "BT2575", + .gpio_info = { + /* slot 0 */ + { + .tdi = 32, + .tck = 65, + .tms = 6, + .tdo = 67, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = BC10072, + .slot_num = 1, + .card_name = "BC10072", + .gpio_info = { + /* slot 0 */ + { + .tdi = 32, + .tck = 65, + .tms = 6, + .tdo = 67, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = TCS81_100F, + .slot_num = 1, + .card_name = "TCS81-100F", + .gpio_info = { + /* slot 0 */ + { + .tdi = 32, + .tck = 65, + .tms = 6, + .tdo = 67, + .jtag_en = 50, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = TCS82_100F, + .slot_num = 1, + .card_name = "TCS82_100F", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = TCS83_100F, + .slot_num = 5, + .card_name = "TCS83-100F", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 39, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 69, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 70, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 71, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + }, + + { + .dev_type = BS100R0, + .slot_num = 5, + .card_name = "BS100R0", + .gpio_info = { + /* slot 0 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 48, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 1 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 39, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 2 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 69, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 3 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 70, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + /* slot 4 */ + { + .tdi = 67, + .tck = 65, + .tms = 6, + .tdo = 32, + .jtag_en = 50, + .select = 71, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + },{ + .dev_type = AS61_48E4T, + .slot_num = 1, + .card_name = "AS61_48E4T", + .gpio_info = { + /* slot 0 */ + { + .tdi = 507, + .tck = 505, + .tms = 506, + .tdo = 508, + .jtag_en = 504, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + + { + .dev_type = AS61_48X4T, + .slot_num = 1, + .card_name = "AS61_48X4T", + .gpio_info = { + /* slot 0 */ + { + .tdi = 507, + .tck = 505, + .tms = 506, + .tdo = 508, + .jtag_en = 504, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + + }, + { + .dev_type = AS61_48E4T_LC, + .slot_num = 1, + .card_name = "AS61_48E4T_LC", + .gpio_info = { + /* slot 0 */ + { + .tdi = 507, + .tck = 505, + .tms = 506, + .tdo = 508, + .jtag_en = 504, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + }, + { + .dev_type = AS61_48E4T_LD, + .slot_num = 1, + .card_name = "AS61_48E4T_LD", + .gpio_info = { + /* slot 0 */ + { + .tdi = 507, + .tck = 505, + .tms = 506, + .tdo = 508, + .jtag_en = 504, + .select = -1, + .jtag_5 = GPIO(-1, 0,1) + .jtag_4 = GPIO(-1, 0,1) + .jtag_3 = GPIO(-1, 1,1) + .jtag_2 = GPIO(-1, 0,1) + .jtag_1 = GPIO(-1, 1,1) + }, + }, + }, +}; + +static int is_debug_on; +static int dfd_my_type = 0; + +#if 0 +#if defined(CONFIG_FRM_PRODUCT_NAME) +#define CONFIG_RAGILE_PRODUCT_NAME CONFIG_FRM_PRODUCT_NAME +#else +#define CONFIG_RAGILE_PRODUCT_NAME "card" +#endif +#endif + +#define DFD_TYPE_FILE "/sys/module/ragile_common/parameters/dfd_my_type" +#define DFD_TYPE_BUFF_SIZE (256) + +static int is_vme_file(char *file_name) +{ + char *tmp; + + tmp = strchr(file_name, '.'); + if (strcmp(tmp, ".bin") == 0) { + return 0; + } else if (strcmp(tmp, ".vme") == 0) { + return 1; + } else { + return -1; + } +} + +int drv_get_my_dev_type(void) +{ + int type; + int fd; + char rbuf[DFD_TYPE_BUFF_SIZE]; + int read_len; + + if (dfd_my_type != 0) { + dbg_print(is_debug_on, "my_type = 0x%x\r\n", dfd_my_type); + return dfd_my_type; + } + + fd = open(DFD_TYPE_FILE, O_RDONLY); + if (fd < 0) { + dbg_print(is_debug_on, "can't open device %s.\r\n", DFD_TYPE_FILE); + return B6510_48VS8CQ; /* Avoid B6510 to obtain different device types */ + } + + memset(rbuf, 0, DFD_TYPE_BUFF_SIZE); + type = 0; + read_len = read(fd, rbuf, DFD_TYPE_BUFF_SIZE - 1); + if (read_len > 0) { + type = strtoul(rbuf, NULL, 0); + } + close(fd); + + dfd_my_type = type; + + dbg_print(is_debug_on, "read dfd type file is %s read_len %d, dfd_my_type 0x%x\n", rbuf, read_len, dfd_my_type); + return dfd_my_type; +} + +firmware_card_info_t* firmware_get_card_info(int dev_type) +{ + int i; + int size; + + size = (sizeof(g_card_info) /sizeof((g_card_info)[0])); + + dbg_print(is_debug_on, "Enter dev_type 0x%x size %d.\n", dev_type, size); + for (i = 0; i < size; i++) { + if (g_card_info[i].dev_type == dev_type) { + dbg_print(is_debug_on, "match dev_type 0x%x.\n", dev_type); + return &g_card_info[i]; + } + } + + dbg_print(is_debug_on, "dismatch dev_type 0x%x.\n", dev_type); + return NULL; +} + +int firmware_get_card_name(char *name, int len) +{ + int dev_type; + firmware_card_info_t *info; + + dbg_print(is_debug_on, "Enter len %d.\n", len); + dev_type = drv_get_my_dev_type(); + if (dev_type < 0) { + dbg_print(is_debug_on, "drv_get_my_dev_type failed ret %d.\n", dev_type); + return FIRMWARE_FAILED; + } + + info = firmware_get_card_info(dev_type); + if (info == NULL) { + dbg_print(is_debug_on, "firmware_get_card_info dev_type %d failed.\n", dev_type ); + return FIRMWARE_FAILED; + } + + strncpy(name, info->card_name, len - 1); + dbg_print(is_debug_on, "Leave dev_type 0x%x name %s, info->name %s.\n", dev_type, + name, info->card_name); + return FIRMWARE_SUCCESS; +} + +int get_debug_value(void) +{ + return is_debug_on; +} + +#if 0 +/* each device implements its own corresponding interface */ +int __attribute__ ((weak)) firmware_get_card_name(char *name, int len) +{ + strncpy(name, CONFIG_RAGILE_PRODUCT_NAME, len - 1); + return FIRMWARE_SUCCESS; +} +#endif + +static int firmware_check_file_is_dir(char *dir, char *file_name) +{ + int ret; + struct stat buf; + char tmp[FIRMWARE_FILE_DIR_LEN]; + + if (strcmp(file_name, ".") == 0 || strcmp(file_name, "..") == 0) { + return -1; + } + + memset(tmp, 0, FIRMWARE_FILE_DIR_LEN); + snprintf(tmp, FIRMWARE_FILE_DIR_LEN - 1, "%s/%s", dir, file_name); + ret = stat(tmp, &buf); + if (ret < 0) { + return -1; + } + + if (S_ISDIR(buf.st_mode)) { + return 1; + } + + return 0; +} + +static inline int firmware_error_type(int action, name_info_t *info) +{ + if (info == NULL) { + return ERR_FW_UPGRADE; + } + if (info->type == FIRMWARE_CPLD) { + switch (action) { + case FIRMWARE_ACTION_CHECK: + return ERR_FW_CHECK_CPLD_UPGRADE; + case FIRMWARE_ACTION_UPGRADE: + return ERR_FW_DO_CPLD_UPGRADE; + default: + return ERR_FW_UPGRADE; + } + } else if (info->type == FIRMWARE_FPGA) { + switch (action) { + case FIRMWARE_ACTION_CHECK: + return ERR_FW_CHECK_FPGA_UPGRADE; + case FIRMWARE_ACTION_UPGRADE: + return ERR_FW_DO_FPGA_UPGRADE; + default: + return ERR_FW_UPGRADE; + } + } else { + return ERR_FW_UPGRADE; + } +} + +/* analyze file's name,Name rule: card name_firmware type_slot number_firmware chip name.bin*/ +static int firmware_parse_file_name(char *name, name_info_t *info) +{ + int i; + char *tmp, *start; + char slot[FIRMWARE_NAME_LEN]; + + dbg_print(is_debug_on, "Parse file name: %s\n", name); + + start = name; + /* card name */ + tmp = strchr(start, '_'); + if (tmp == NULL) { + dbg_print(is_debug_on, "Failed to get card name form file name: %s.\n", name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, NULL); + } + + strncpy(info->card_name, start, + (tmp - start > FIRMWARE_NAME_LEN - 1) ? (FIRMWARE_NAME_LEN - 1) : (tmp - start)); + + /* firmware type */ + start = tmp + 1; + tmp = strchr(start, '_'); + if (tmp == NULL) { + dbg_print(is_debug_on, "Failed to get upgrade type form file name: %s.\n", name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, NULL); + } + + if (strncmp(start, FIRMWARE_CPLD_NAME, tmp - start) == 0) { + info->type = FIRMWARE_CPLD; + } else if (strncmp(start, FIRMWARE_FPGA_NAME, tmp - start) == 0) { + info->type = FIRMWARE_FPGA; + } else { + info->type = FIRMWARE_OTHER; + } + + /* slot number */ + start = tmp + 1; + tmp = strchr(start, '_'); + if (tmp == NULL) { + dbg_print(is_debug_on, "Failed to get slot form file name: %s.\n", name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + + memset(slot, 0, FIRMWARE_NAME_LEN); + strncpy(slot, start, + ((tmp - start > FIRMWARE_NAME_LEN - 1) ? FIRMWARE_NAME_LEN - 1 : tmp - start)); + + for (i = 0; i < FIRMWARE_NAME_LEN && slot[i] != '\0'; i++) { + if (!isdigit(slot[i])) { + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + } + + dbg_print(is_debug_on, "get slot info: %s.\n", name); + info->slot = strtoul(slot, NULL, 10); + dbg_print(is_debug_on, "get slot info slot: %d.\n", info->slot); + + /* firmware chip name */ + start = tmp + 1; + tmp = strchr(start, '_'); + if (tmp == NULL) { + dbg_print(is_debug_on, "Failed to get chip name form file name: %s.\n", name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + strncpy(info->chip_name, start, + (tmp - start > FIRMWARE_NAME_LEN - 1) ? (FIRMWARE_NAME_LEN - 1) : (tmp - start)); + + /* version */ + start = tmp + 1; + tmp = strstr(start, ".vme"); + if (tmp == NULL) { + dbg_print(is_debug_on, "Failed to get chip version form file name: %s.\n", name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + strncpy(info->version, start, + (tmp - start > FIRMWARE_NAME_LEN - 1) ? (FIRMWARE_NAME_LEN - 1) : (tmp - start)); + + /* finish checking */ + if (strcmp(tmp, ".vme") != 0) { + dbg_print(is_debug_on, "The file format is wrong: %s.\n", name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + + return FIRMWARE_SUCCESS; +} + +/* check the file information to determine whether the file can be used in the device */ +static int firmware_check_file_info(name_info_t *info) +{ + int ret; + char card_name[FIRMWARE_NAME_LEN]; + + dbg_print(is_debug_on, "Check file info.\n"); + + /* get card name */ + memset(card_name, 0, FIRMWARE_NAME_LEN); + ret = firmware_get_card_name(card_name, FIRMWARE_NAME_LEN); + if (ret != FIRMWARE_SUCCESS) { + dbg_print(is_debug_on, "Failed to get card name.(%s)\n", info->card_name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + + /* check card name */ + dbg_print(is_debug_on, "The card name: %s, the file card name: %s.\n", + card_name, info->card_name); + if (strcmp(card_name, info->card_name) != 0) { + dbg_print(is_debug_on, "The file card name %s is wrong.(real: %s)\n", + info->card_name, card_name); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + + /* check type */ + if (info->type != FIRMWARE_CPLD && info->type != FIRMWARE_FPGA) { + dbg_print(is_debug_on, "The file type %d is wrong.(cpld %d, fpga %d)\n", + info->type, FIRMWARE_CPLD, FIRMWARE_FPGA); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + + /* check slot */ + if (info->slot < 1 || info->slot > FIRMWARE_MAX_SLOT_NUM) { + dbg_print(is_debug_on, "The file slot %d is wrong.\n", info->slot); + return firmware_error_type(FIRMWARE_ACTION_CHECK, info); + } + + dbg_print(is_debug_on, "Success check file info.\n"); + return FIRMWARE_SUCCESS; +} + +static void firmware_get_dev_file_name(name_info_t *info, char *file_name, int len) +{ + if (info->type == FIRMWARE_CPLD) { + snprintf(file_name, len, "/dev/firmware_cpld_ispvme%d", info->slot - 1); + } else if (info->type == FIRMWARE_FPGA) { + snprintf(file_name, len, "/dev/firmware_fpga_ispvme%d", info->slot - 1); + } else { + snprintf(file_name, len, "/dev/firmware_ispvme%d", info->slot - 1); + } +} + +static void firmware_set_driver_debug(int fd) +{ + int ret; + + if (is_debug_on == DEBUG_ALL_ON || is_debug_on == DEBUG_KERN_ON) { + ret = ioctl(fd, FIRMWARE_SET_DEBUG_ON, NULL); + if (ret < 0) { + dbg_print(is_debug_on, "Failed to set driver debug on.\n"); + } else { + dbg_print(is_debug_on, "Open driver debug.\n"); + } + } else if (is_debug_on == DEBUG_OFF) { + ret = ioctl(fd, FIRMWARE_SET_DEBUG_OFF, NULL); + if (ret < 0) { + dbg_print(is_debug_on, "Failed to set driver debug off.\n"); + } else { + dbg_print(is_debug_on, "OFF driver debug.\n"); + } + } else { + dbg_print(is_debug_on, "Ignore driver debug.\n"); + } +} + + +static int firmware_check_chip_name(int fd, name_info_t *info) +{ + return FIRMWARE_SUCCESS; +} + +static int firmware_check_chip_verison(int fd, name_info_t *info) +{ + return FIRMWARE_SUCCESS; +} + +static int firmware_get_file_size(char *file_name, int *size) +{ + int ret; + struct stat buf; + + ret = stat(file_name, &buf); + if (ret < 0) { + return FIRMWARE_FAILED; + } + + if (buf.st_size < 0) { + return FIRMWARE_FAILED; + } + + *size = buf.st_size; + + return FIRMWARE_SUCCESS; +} + +static int firmware_get_file_info(char *file_name, char *buf, int size) +{ + FILE *fp; + int len; + + fp = fopen(file_name, "r"); + if (fp == NULL) { + return FIRMWARE_FAILED; + } + + len = fread(buf, size, 1, fp); + if (len < 0) { + fclose(fp); + return FIRMWARE_FAILED; + } + + fclose(fp); + + return FIRMWARE_SUCCESS; +} + +static int firmware_upgrade_info(int fd, char *buf, int size) +{ + return FIRMWARE_SUCCESS; +} + +/* upgrade CPLD */ +static int firmware_upgrade(char *dir, char *file_name, name_info_t *info) +{ + return FIRMWARE_SUCCESS; +} + +static int firmware_upgrade_file(char *dir, char *file_name) +{ + int ret, argc; + name_info_t info; + char *argv[2]; + char tmp_file[FIRMWARE_FILE_DIR_LEN]; + + memset(&info, 0, sizeof(name_info_t)); + ret = firmware_parse_file_name(file_name, &info); + if (ret != FIRMWARE_SUCCESS) { + dbg_print(is_debug_on, "Failed to parse file name: %s\n", file_name); + return ret; + } + + dbg_print(is_debug_on, "The file name parse:(%s) \n" + " card name: %s, \n" + " type : %d, \n" + " slot : %d, \n" + " chip name: %s \n" + " version : %s \n", + file_name, info.card_name, info.type, info.slot, info.chip_name, info.version); + + ret = firmware_check_file_info(&info); + if (ret != FIRMWARE_SUCCESS) { + dbg_print(is_debug_on, "Failed to check file name: %s\n", file_name); + return ret; + } + + + /* get the information of upgrade file */ + memset(tmp_file, 0, FIRMWARE_FILE_DIR_LEN); + if (dir != NULL) { + snprintf(tmp_file, FIRMWARE_FILE_DIR_LEN - 1, "%s/%s", dir, file_name); + } else { + snprintf(tmp_file, FIRMWARE_FILE_DIR_LEN - 1, "%s", file_name); + } + + argc = 2; + argv[1] = tmp_file; + ret = ispvme_main(argc, (char **)&argv); + if (ret != FIRMWARE_SUCCESS){ + dbg_print(is_debug_on, "Failed to upgrade file name: %s\n", file_name); + } + + return ret; +} + +static int firmware_upgrade_set_gpio_info(int slot) +{ + firmware_card_info_t *hw_info; + cmd_info_t cmd_info; + firmware_upg_gpio_info_t *gpio_info; + int ret; + int fd; + int dev_type; + int my_slot; + + ret = 0; + + dev_type = drv_get_my_dev_type(); + fd = open("/dev/firmware_cpld_ispvme0", O_RDWR); + if (fd < 0) { + dbg_print(is_debug_on, "%s can't open device\r\n", __func__); + return -1; + } + + hw_info = firmware_get_card_info(dev_type); + + if (hw_info == NULL) { + dbg_print(is_debug_on, "card type 0x%x don't support firmware.\n", dev_type); + ret = -1; + goto gpio_info_err; + } + + if (slot >= hw_info->slot_num) { + dbg_print(is_debug_on, "slot %d is too large, support slot num %d.\n", slot, hw_info->slot_num); + ret = -1; + goto gpio_info_err; + } + + gpio_info = &(hw_info->gpio_info[slot]); + cmd_info.size = sizeof(firmware_upg_gpio_info_t); + cmd_info.data = (void *)gpio_info; + + dbg_print(is_debug_on, "slot = %d, gpio_info[jtag_en:%d select:%d tck:%d tdi:%d tdo=%d tms=%d]\n",slot, \ + gpio_info->jtag_en, gpio_info->select,gpio_info->tck,gpio_info->tdi,gpio_info->tdo,gpio_info->tms); + + ret = ioctl(fd, FIRMWARE_SET_GPIO_INFO, &cmd_info); + +gpio_info_err: + if (ret < 0) { + dbg_print(is_debug_on, "Failed due to:set gpio info.\n"); + } + + close(fd); + + return ret; +} + +/** + * argv[1]: file name + * argv[2]: type + * argv[3]: slot number + * argv[4]: chip name + */ +static int firmware_upgrade_one_file(int argc, char *argv[]) +{ + int ret; + name_info_t info; + char tmp[FIRMWARE_FILE_DIR_LEN]; + + memset(&info, 0, sizeof(name_info_t)); + + info.slot = strtoul(argv[3], NULL, 10); + strncpy(info.chip_name, argv[4], FIRMWARE_NAME_LEN - 1); + + if (strcmp(argv[2], FIRMWARE_CPLD_NAME) == 0) { /* CPLD upgrade */ + if(is_vme_file(argv[1]) == 1){ /* VME upgrade file */ + dbg_print(is_debug_on, "vme file\n"); + info.type = FIRMWARE_CPLD; + ret = firmware_upgrade_set_gpio_info(info.slot); + if (ret < 0) { + goto upgrade_err; + } + ret = ispvme_main(2, argv); + } + else if(is_vme_file(argv[1]) == 0){ /* bin upgrade file */ + dbg_print(is_debug_on, "bin file\n"); + memset(tmp, 0, FIRMWARE_FILE_DIR_LEN); + snprintf(tmp, FIRMWARE_FILE_DIR_LEN, "firmware_upgrade_bin %s %s %s %s", argv[1], argv[2], argv[3], argv[4]); + ret = system(tmp); + } + else{ + dbg_print(is_debug_on, "unknow file\n"); + return FIRMWARE_FAILED; + } + } + else if (strcmp(argv[2], FIRMWARE_FPGA_NAME) == 0) { /* FPGA upgrade */ + info.type = FIRMWARE_FPGA; + ret = dfd_fpga_upgrade_do_upgrade(argv[1]); + } else { + dbg_print(is_debug_on, "Failed to get upgrade type: %s.\n", argv[2]); + return ERR_FW_UPGRADE; + } + +upgrade_err: + if (ret != FIRMWARE_SUCCESS){ + dbg_print(is_debug_on, "Failed to upgrade: %s.\n", argv[1]); + } + + return ret; +} + +static void firmware_get_err_type(int err, int *real_err) +{ + int tmp_err; + + tmp_err = *real_err; + + if (tmp_err == err) { + return; + } + switch (err) { + case ERR_FW_DO_CPLD_UPGRADE: + case ERR_FW_DO_FPGA_UPGRADE: + if (tmp_err == ERR_FW_CHECK_CPLD_UPGRADE + || tmp_err == ERR_FW_CHECK_FPGA_UPGRADE + || tmp_err == FIRMWARE_SUCCESS || tmp_err == ERR_FW_UPGRADE) { + tmp_err = err; + } + break; + case ERR_FW_CHECK_CPLD_UPGRADE: + case ERR_FW_CHECK_FPGA_UPGRADE: + if (tmp_err == FIRMWARE_SUCCESS || tmp_err == ERR_FW_UPGRADE) { + tmp_err = err; + } + break; + case ERR_FW_UPGRADE: + if (tmp_err == FIRMWARE_SUCCESS) { + tmp_err = err; + } + break; + case FIRMWARE_SUCCESS: + break; + default: + return; + } + + *real_err = tmp_err; + + return; +} + +/* argv[1]: Pathname */ +static int firmware_upgrade_one_dir(int argc, char *argv[]) +{ + int ret, real_ret; + int flag; + DIR *dirp; + struct dirent *dp; + char *dir; + + dir = argv[1]; + dirp = opendir(dir); + if (dirp == NULL) { + dbg_print(is_debug_on, "Failed to open the dir: %s.\n", dir); + return ERR_FW_UPGRADE; + } + + ret = ERR_FW_UPGRADE; + real_ret = FIRMWARE_SUCCESS; + flag = 0; + for (;;) { + /* read the pathname of the file */ + dp = readdir(dirp); + if (dp == NULL) { + break; + } + + dbg_print(is_debug_on, "The file name: %s.\n", dp->d_name); + /* check whether it is a file */ + if (firmware_check_file_is_dir(dir, dp->d_name) != 0) { + continue; + } + + dbg_print(is_debug_on, "\n=========== Start: %s ===========\n", dp->d_name); + + /* upgrade a upgrade file */ + ret = firmware_upgrade_file(dir, dp->d_name); + if (ret != FIRMWARE_SUCCESS) { + firmware_get_err_type(ret, &real_ret); + dbg_print(is_debug_on, "Failed to upgrade the file: %s.(%d, %d)\n", dp->d_name, ret, real_ret); + } else { + flag = 1; + dbg_print(is_debug_on, "Upgrade the file: %s success.\n", dp->d_name); + } + + dbg_print(is_debug_on, "=========== End: %s ===========\n", dp->d_name); + } + + if (flag == 1 && (real_ret == ERR_FW_CHECK_CPLD_UPGRADE || real_ret == ERR_FW_CHECK_FPGA_UPGRADE)) { + real_ret = FIRMWARE_SUCCESS; + } + + if (real_ret != FIRMWARE_SUCCESS) { + dbg_print(is_debug_on, "Failed to upgrade: %s.\n", dir); + } else { + dbg_print(is_debug_on, "Upgrade success: %s.\n", dir); + } + + closedir(dirp); + return real_ret; +} + +/** + * argv[1]: file name + * argv[2]: type + * argv[3]: slot number + */ +static int firmware_upgrade_read_chip(int argc, char *argv[]) +{ + + return FIRMWARE_SUCCESS; +} + +static int firmware_upgrade_test_fpga(int argc, char *argv[]) +{ + int ret; + if ((strcmp(argv[1], FIRMWARE_FPGA_NAME) != 0) + || (strcmp(argv[2], FIRMWARE_FPGA_TEST) != 0)) { + printf( "fpga test:Failed to Input ERR Parm, argv[1]:%s, agrv[2]:%s\n", argv[1], argv[2]); + return FIRMWARE_FAILED; + } + ret = dfd_fpga_upgrade_test(); + return ret; +} + +static int firmware_upgrade_test_chip(int argc, char *argv[]) +{ + int ret,dev_type,slot; + int err_ret=0; + firmware_card_info_t *hw_info; + + if ((strcmp(argv[1], FIRMWARE_CPLD_NAME) != 0) + || (strcmp(argv[2], FIRMWARE_CPLD_TEST) != 0)) { + printf( "gpio test:Failed to Input ERR Parm, argv[1]:%s, agrv[2]:%s\n", argv[1], argv[2]); + return FIRMWARE_FAILED; + } + + dev_type = drv_get_my_dev_type(); /* get the type of card first */ + if (dev_type < 0) { + printf("gpio test:drv_get_my_dev_type failed ret 0x%x.\n", dev_type); + return FIRMWARE_FAILED; + } + + hw_info = firmware_get_card_info(dev_type); /* get the detail information of card */ + if (hw_info == NULL) { + printf( "gpio test:card type 0x%x don't support firmware.\n", dev_type); + return FIRMWARE_FAILED; + } + + for(slot = 0; slot < hw_info->slot_num; slot++){ + ret = firmware_upgrade_set_gpio_info(slot); /* set GPIO information */ + if(ret < 0){ + err_ret++; + printf( "gpio test:Failed to set gpio info,dev_type 0x%x,slot %d\n", dev_type, slot); + continue; + } + ret = ispvme_test(); /* GPIO path test */ + if(ret != 0){ + err_ret++; + printf("gpio test:ispvme_test failed,dev_type 0x%x,slot %d\n", dev_type, slot); + } + } + if(err_ret != 0) + return FIRMWARE_FAILED; + return FIRMWARE_SUCCESS; +} + +int main(int argc, char *argv[]) +{ + int ret; + + is_debug_on = firmware_upgrade_debug(); + + if (argc != 2 && argc != 5 && argc != 4 && argc != 3 && argc != 6) { + printf("Use:\n"); + printf(" upgrade dir : firmware_upgrade_ispvme dir\n"); + printf(" upgrade file : firmware_upgrade_ispvme file type slot chip_name\n"); + printf(" read chip : firmware_upgrade_ispvme file type slot\n"); + dbg_print(is_debug_on, "Failed to upgrade the number of argv: %d.\n", argc); + return ERR_FW_UPGRADE; + } +#if 0 + ret = dev_drv_init(); + if (ret) { + dbg_print(is_debug_on, "failed to init dfd ret %d.", ret); + return ERR_FW_UPGRADE; + } +#endif + /* dump fpga flash operation */ + if (argc == 6) { + if (strcmp(argv[1], "fpga_dump_flash") == 0) { + ret = dfd_fpga_upgrade_dump_flash(argc, argv); + printf("fpga_dump_flash ret %d.\n", ret); + return FIRMWARE_SUCCESS; + } else { + printf("Not support, please check your cmd.\n"); + return FIRMWARE_SUCCESS; + } + } + + /* upgrade individual files */ + if (argc == 5) { + printf("+================================+\n"); + printf("|Begin to upgrade, please wait...|\n"); + ret = firmware_upgrade_one_file(argc, argv); + if (ret != FIRMWARE_SUCCESS) { + if(strcmp(argv[2], FIRMWARE_CPLD_NAME) == 0) + printf("| CPLD Upgrade failed! |\n"); + else if(strcmp(argv[2], FIRMWARE_FPGA_NAME) == 0) + printf("| FPGA Upgrade failed! |\n"); + else + printf("| Failed to get upgrade type! |\n"); + printf("+================================+\n"); + dbg_print(is_debug_on, "Failed to upgrade a firmware file: %s.\n", argv[1]); + return ret; + } + if(strcmp(argv[2], FIRMWARE_CPLD_NAME) == 0) + printf("| CPLD Upgrade succeeded! |\n"); + else + printf("| FPGA Upgrade succeeded! |\n"); + printf("+================================+\n"); + return FIRMWARE_SUCCESS; + } + + if (argc == 2) { + printf("+================================+\n"); + printf("|Begin to upgrade, please wait...|\n"); + + ret = firmware_upgrade_one_dir(argc, argv); + if (ret != FIRMWARE_SUCCESS) { + printf("| Upgrade failed! |\n"); + printf("+================================+\n"); + dbg_print(is_debug_on, "Failed to upgrade a firmware dir: %s.\n", argv[1]); + return ret; + } + printf("| Upgrade succeeded! |\n"); + printf("+================================+\n"); + return FIRMWARE_SUCCESS; + } + + if (argc == 4) { + ret = firmware_upgrade_read_chip(argc, argv); + if (ret != FIRMWARE_SUCCESS) { + dbg_print(is_debug_on, "Failed to read chip: %s.\n", argv[1]); + return ret; + } + + return FIRMWARE_SUCCESS; + } + + if (argc == 3) { + if (strcmp(argv[1], FIRMWARE_FPGA_NAME) == 0) { + ret = firmware_upgrade_test_fpga(argc, argv); + if (ret != FIRMWARE_SUCCESS) { + printf("+=================+\n"); + printf("| FPGA TEST FAIL! |\n"); + printf("+=================+\n"); + return FIRMWARE_FAILED; + } else { + printf("+=================+\n"); + printf("| FPGA TEST PASS! |\n"); + printf("+=================+\n"); + return FIRMWARE_SUCCESS; + } + } else { + ret = firmware_upgrade_test_chip(argc, argv); + if (ret != FIRMWARE_SUCCESS) { + printf("+=================+\n"); + printf("| GPIO TEST FAIL! |\n"); + printf("+=================+\n"); + return FIRMWARE_FAILED; + } else { + printf("+=================+\n"); + printf("| GPIO TEST PASS! |\n"); + printf("+=================+\n"); + return FIRMWARE_SUCCESS; + } + } + } + + return ERR_FW_UPGRADE; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/hardware.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/hardware.c new file mode 100644 index 000000000000..debba5fa55ad --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/hardware.c @@ -0,0 +1,253 @@ +/********************************************************************************* +* Lattice Semiconductor Corp. Copyright 2000-2008 +* +* This is the hardware.c of ispVME V12.1 for JTAG programmable devices. +* All the functions requiring customization are organized into this file for +* the convinience of porting. +*********************************************************************************/ +/********************************************************************************* +* Revision History: +* +* 09/11/07 NN Type cast mismatch variables +* 09/24/07 NN Added calibration function. +* Calibration will help to determine the system clock frequency +* and the count value for one micro-second delay of the target +* specific hardware. +* Modified the ispVMDelay function +* Removed Delay Percent support +* Moved the sclock() function from ivm_core.c to hardware.c +*********************************************************************************/ + +/* #include */ +#include +#include +#include "common.h" + +/******************************************************************************** +* Declaration of global variables +* +*********************************************************************************/ + +unsigned char g_siIspPins = 0x00; /*Keeper of JTAG pin state*/ +unsigned short g_usInPort = 0x379; /*Address of the TDO pin*/ +unsigned short g_usOutPort = 0x378; /*Address of TDI, TMS, TCK pin*/ +unsigned short g_usCpu_Frequency = 1000; /*Enter your CPU frequency here, unit in MHz.*/ + + +/********************************************************************************* +* This is the definition of the bit locations of each respective +* signal in the global variable g_siIspPins. +* +* NOTE: Users must add their own implementation here to define +* the bit location of the signal to target their hardware. +* The example below is for the Lattice download cable on +* on the parallel port. +* +*********************************************************************************/ + + + +#if 0 +const unsigned char g_ucPinTDI = JTAG_TDI; /* Bit address of TDI */ +const unsigned char g_ucPinTCK = JTAG_TCK; /* Bit address of TCK */ +const unsigned char g_ucPinTMS = JTAG_TMS; /* Bit address of TMS */ +const unsigned char g_ucPinENABLE = JTAG_ENABLE; /* Bit address of ENABLE */ +const unsigned char g_ucPinTRST = JTAG_TRST; /* Bit address of TRST */ +const unsigned char g_ucPinTDO = JTAG_TDO; /* Bit address of TDO*/ +#endif +int g_file_fd; +/*************************************************************** +* +* Functions declared in hardware.c module. +* +***************************************************************/ +void writePort(unsigned char a_ucPins, unsigned char a_ucValue); +unsigned char readPort(); +void sclock(); +void ispVMDelay(unsigned short a_usTimeDelay); +void calibration(void); + +/******************************************************************************** +* writePort +* To apply the specified value to the pins indicated. This routine will +* be modified for specific systems. +* As an example, this code uses the IBM-PC standard Parallel port, along with the +* schematic shown in Lattice documentation, to apply the signals to the +* JTAG pins. +* +* PC Parallel port pin Signal name Port bit address +* 2 g_ucPinTDI 1 +* 3 g_ucPinTCK 2 +* 4 g_ucPinTMS 4 +* 5 g_ucPinENABLE 8 +* 6 g_ucPinTRST 16 +* 10 g_ucPinTDO 64 +* +* Parameters: +* - a_ucPins, which is actually a set of bit flags (defined above) +* that correspond to the bits of the data port. Each of the I/O port +* bits that drives an isp programming pin is assigned a flag +* (through a #define) corresponding to the signal it drives. To +* change the value of more than one pin at once, the flags are added +* together, much like file access flags are. +* +* The bit flags are only set if the pin is to be changed. Bits that +* do not have their flags set do not have their levels changed. The +* state of the port is always manintained in the static global +* variable g_siIspPins, so that each pin can be addressed individually +* without disturbing the others. +* +* - a_ucValue, which is either HIGH (0x01 ) or LOW (0x00 ). Only these two +* values are valid. Any non-zero number sets the pin(s) high. +* +*********************************************************************************/ + +void writePort(unsigned char a_ucPins, unsigned char a_ucValue) +{ + switch (a_ucPins) { + case JTAG_TCK: + ioctl(g_file_fd, FIRMWARE_JTAG_TCK, &a_ucValue); + break; + case JTAG_TDI: + ioctl(g_file_fd, FIRMWARE_JTAG_TDI, &a_ucValue); + break; + case JTAG_TMS: + ioctl(g_file_fd, FIRMWARE_JTAG_TMS, &a_ucValue); + break; + case JTAG_ENABLE: + ioctl(g_file_fd, FIRMWARE_JTAG_EN, &a_ucValue); + break; + case JTAG_TRST: + /* ioctl(g_file_fd, FIRMWARE_JTAG_TRST, &a_ucValue); */ + break; + default: + break; + } +} + +/********************************************************************************* +* +* readPort +* +* Returns the value of the TDO from the device. +* +**********************************************************************************/ +unsigned char readPort() +{ + unsigned char ucRet = 0; + + ioctl(g_file_fd, FIRMWARE_JTAG_TDO, &ucRet); + return (ucRet); +} + +/********************************************************************************* +* sclock +* +* Apply a pulse to TCK. +* +* This function is located here so that users can modify to slow down TCK if +* it is too fast (> 25MHZ). Users can change the IdleTime assignment from 0 to +* 1, 2... to effectively slowing down TCK by half, quarter... +* +*********************************************************************************/ +void sclock() +{ + unsigned short IdleTime = 0; /* change to > 0 if need to slow down TCK */ + unsigned short usIdleIndex = 0; + IdleTime++; + for (usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++) { + writePort(JTAG_TCK, 0x01); + } + for (usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++) { + writePort(JTAG_TCK, 0x00); + } +} +/******************************************************************************** +* +* ispVMDelay +* +* +* Users must implement a delay to observe a_usTimeDelay, where +* bit 15 of the a_usTimeDelay defines the unit. +* 1 = milliseconds +* 0 = microseconds +* Example: +* a_usTimeDelay = 0x0001 = 1 microsecond delay. +* a_usTimeDelay = 0x8001 = 1 millisecond delay. +* +* This subroutine is called upon to provide a delay from 1 millisecond to a few +* hundreds milliseconds each time. +* It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 bits +* integer, this function is restricted to produce a delay to 64000 micro-seconds +* or 32000 milli-second maximum. The VME file will never pass on to this function +* a delay time > those maximum number. If it needs more than those maximum, the VME +* file will launch the delay function several times to realize a larger delay time +* cummulatively. +* It is perfectly alright to provide a longer delay than required. It is not +* acceptable if the delay is shorter. +* +* Delay function example--using the machine clock signal of the native CPU------ +* When porting ispVME to a native CPU environment, the speed of CPU or +* the system clock that drives the CPU is usually known. +* The speed or the time it takes for the native CPU to execute one for loop +* then can be calculated as follows: +* The for loop usually is compiled into the ASSEMBLY code as shown below: +* LOOP: DEC RA; +* JNZ LOOP; +* If each line of assembly code needs 4 machine cycles to execute, +* the total number of machine cycles to execute the loop is 2 x 4 = 8. +* Usually system clock = machine clock (the internal CPU clock). +* Note: Some CPU has a clock multiplier to double the system clock for + the machine clock. +* +* Let the machine clock frequency of the CPU be F, or 1 machine cycle = 1/F. +* The time it takes to execute one for loop = (1/F ) x 8. +* Or one micro-second = F(MHz)/8; +* +* Example: The CPU internal clock is set to 100Mhz, then one micro-second = 100/8 = 12 +* +* The C code shown below can be used to create the milli-second accuracy. +* Users only need to enter the speed of the cpu. +* +**********************************************************************************/ +void ispVMDelay(unsigned short a_usTimeDelay) +{ + if (a_usTimeDelay & 0x8000) { + a_usTimeDelay &= ~0x8000; /* change it to ms */ + usleep(a_usTimeDelay * 1000); /* Use usleep to improve accuracy */ + } else + usleep(a_usTimeDelay); + return; +} + + +/********************************************************************************* +* +* calibration +* +* It is important to confirm if the delay function is indeed providing +* the accuracy required. Also one other important parameter needed +* checking is the clock frequency. +* Calibration will help to determine the system clock frequency +* and the loop_per_micro value for one micro-second delay of the target +* specific hardware. +* +**********************************************************************************/ +void calibration(void) +{ + /*Apply 2 pulses to TCK.*/ + writePort(JTAG_TCK, 0x00); + writePort(JTAG_TCK, 0x01); + writePort(JTAG_TCK, 0x00); + writePort(JTAG_TCK, 0x01); + writePort(JTAG_TCK, 0x00); + + /*Delay for 1 millisecond. Pass on 1000 or 0x8001 both = 1ms delay.*/ + ispVMDelay(0x8001); + + /*Apply 2 pulses to TCK*/ + writePort(JTAG_TCK, 0x01); + writePort(JTAG_TCK, 0x00); + writePort(JTAG_TCK, 0x01); + writePort(JTAG_TCK, 0x00); +} diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/debug_ispvme.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/debug_ispvme.h new file mode 100644 index 000000000000..d0ddab551c2c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/debug_ispvme.h @@ -0,0 +1,21 @@ +#ifndef __FIRMWARE_UPGRADE_DEBUG_H__ +#define __FIRMWARE_UPGRADE_DEBUG_H__ + +#define DEBUG_INFO_LEN 20 +#define DEBUG_FILE "/.firmware_upgrade_debug" +#define DEBUG_ON_ALL "3" +#define DEBUG_ON_KERN "2" +#define DEBUG_ON_INFO "1" +#define DEBUG_OFF_INFO "0" + +enum debug_s { + DEBUG_OFF = 0, /* debug off */ + DEBUG_APP_ON, /* debug app on */ + DEBUG_KERN_ON, /* kernel debug on */ + DEBUG_ALL_ON, /* debug app and kernel debug on */ + DEBUG_IGNORE, /* ignore debug */ +}; + +extern int firmware_upgrade_debug(void); + +#endif /* End of __FIRMWARE_UPGRADE_DEBUG_H__ */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/firmware_app_ispvme.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/firmware_app_ispvme.h new file mode 100644 index 000000000000..774ebd1c1a7d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/include/firmware_app_ispvme.h @@ -0,0 +1,142 @@ +#ifndef __FIRMWARE_APP_H__ +#define __FIRMWARE_APP_H__ + +#include +#include + +/* Agreement with PKG_MGMT module */ +#define ERR_FW_CHECK_CPLD_UPGRADE (440 - 256) +#define ERR_FW_CHECK_FPGA_UPGRADE (441 - 256) +#define ERR_FW_DO_CPLD_UPGRADE (442 - 256) +#define ERR_FW_DO_FPGA_UPGRADE (443 - 256) +#define ERR_FW_UPGRADE (444 - 256) + +#define FIRMWARE_FAILED -1 +#define FIRMWARE_SUCCESS 0 + +#define FIRMWARE_ACTION_CHECK 0 +#define FIRMWARE_ACTION_UPGRADE 1 + +#define dbg_print(debug, fmt, arg...) \ + if (debug == DEBUG_APP_ON || debug == DEBUG_ALL_ON) \ + { do{printf(fmt,##arg);} while(0); } + +#define FIRMWARE_FILE_DIR_LEN 128 +#define FIRMWARE_NAME_LEN 48 +#define FIRMWARE_MAX_SLOT_NUM 32 + +#define FIRMWARE_CPLD_NAME "cpld" +#define FIRMWARE_FPGA_NAME "fpga" + +#define FIRMWARE_CPLD_EPM1270F256 "EPM1270F256" +#define FIRMWARE_CPLD_5M1270 "5M1270" +#define FIRMWARE_CPLD_TEST "test" +#define FIRMWARE_FPGA_TEST "test" + +/* ioctl command */ +#define FIRMWARE_TYPE 'F' + +#define FIRMWARE_JTAG_TDI _IOR(FIRMWARE_TYPE, 0, char) +#define FIRMWARE_JTAG_TDO _IOR(FIRMWARE_TYPE, 1, char) +#define FIRMWARE_JTAG_TCK _IOR(FIRMWARE_TYPE, 2, char) +#define FIRMWARE_JTAG_TMS _IOR(FIRMWARE_TYPE, 3, char) +#define FIRMWARE_JTAG_EN _IOR(FIRMWARE_TYPE, 4, char) +#define FIRMWARE_SET_DEBUG_ON _IOW(FIRMWARE_TYPE, 5, int) /* debug on */ +#define FIRMWARE_SET_DEBUG_OFF _IOW(FIRMWARE_TYPE, 6, int) /* debug off */ +#define FIRMWARE_SET_GPIO_INFO _IOR(FIRMWARE_TYPE, 7, int) /* GPIO info */ + +#define FIRMWARE_MAX_SUB_SLOT_NUM (8) +#define FIRMWARE_MAX_CARD_SLOT_NUM ((FIRMWARE_MAX_SUB_SLOT_NUM) + (1))/* max slot num */ +#define FIRMWARE_CARD_NAME_MAX_LEN (64) +#define GPIO(p, v, d) { \ + .pin = p, \ + .val = v, \ + .dir = d, \ + }, + +enum firmware_type_s { + FIRMWARE_CPLD = 0, + FIRMWARE_FPGA, + FIRMWARE_OTHER, +}; + +typedef struct name_info_s { + char card_name[FIRMWARE_NAME_LEN]; /* card name */ + int type; /* upgrade file type */ + int slot; /* slot number correspoding to upgrade file */ + char chip_name[FIRMWARE_NAME_LEN]; /* chip name */ + char version[FIRMWARE_NAME_LEN]; /* version */ +} name_info_t; + +typedef struct cmd_info_s { + int size; + void *data; +} cmd_info_t; + +typedef struct gpio_group_s { + int pin; + int val; + int dir; +} gpio_group_t; + +typedef struct firmware_upg_gpio_info_s { + int tdi; + int tck; + int tms; + int tdo; + int jtag_en; + int select; + gpio_group_t jtag_5; + gpio_group_t jtag_4; + gpio_group_t jtag_3; + gpio_group_t jtag_2; + gpio_group_t jtag_1; +} firmware_upg_gpio_info_t; + +typedef struct firmware_card_info_s { + int dev_type; /* the type of card */ + int slot_num; + char card_name[FIRMWARE_CARD_NAME_MAX_LEN]; + firmware_upg_gpio_info_t gpio_info[FIRMWARE_MAX_CARD_SLOT_NUM]; /* private data */ +} firmware_card_info_t; + +typedef enum card_type_e { + B6510_48VS8CQ = 0x4040, + B6520_64CQ = 0x4041, + B6930_32CDQ2XS = 0x4043, + B6920_4C = 0x4044, + AS13_48F8H = 0x4050, + AS13_32H = 0x4051, + AS23_128H = 0x4052, + AS14_128H = 0x4057, + B6510_32CQ = 0x4058, + AS14_32D = 0x4060, + BT2575 = 0x4061, + BC10072 = 0x4062, + AS14_40D = 0X4063, + AS24_128D = 0x4064, + AS61_48E4T = 0X4065, + AS61_48X4T = 0X4066, + AC51_48C2G = 0x4075, + TCS81_100F = 0x4071, + TCS83_100F = 0x4072, + TCS82_100F = 0x4073, + B6920_4C_V2 = 0x4076, + BS100R0 = 0x4048, + AS61_48E4T_LC = 0x4087, + AS61_48E4T_LD = 0x4088, +} card_type_t; + +extern firmware_card_info_t* firmware_get_card_info(int dev_type); +extern int dfd_fpga_upgrade_do_upgrade(char* upg_file); +extern int dfd_fpga_upgrade_test(void); +extern int ispvme_test(void); +extern int ispvme_main(int argc, char *argv[]); +/* External fpga dump interface */ +extern int dfd_fpga_upgrade_dump_flash(int argc, char* argv[]); + + + + +#endif /* End of __FIRMWARE_APP_H__ */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ispvm_ui.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ispvm_ui.c new file mode 100644 index 000000000000..3bb17f196458 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ispvm_ui.c @@ -0,0 +1,851 @@ +/************************************************************** +* +* Lattice Semiconductor Corp. Copyright 2008 +* +* ispVME Embedded allows programming of Lattice's suite of FPGA +* devices on embedded systems through the JTAG port. The software +* is distributed in source code form and is open to re - distribution +* and modification where applicable. +* +* ispVME Embedded C Source comprised with 3 modules: +* ispvm_ui.c is the module provides input and output support. +* ivm_core.c is the module interpret the VME file(s). +* hardware.c is the module access the JTAG port of the device(s). +* +* The optional module cable.c is for supporting Lattice's parallel +* port ispDOWNLOAD cable on DOS and Windows 95/98 O/S. It can be +* requested from Lattice's ispVMSupport. +* +***************************************************************/ + + +/************************************************************** +* +* Revision History of ispvm_ui.c +* +* 3/6/07 ht Added functions vme_out_char(),vme_out_hex(), +* vme_out_string() to provide output resources. +* Consolidate all printf() calls into the added output +* functions. +* +* 09/11/07 NN Added Global variables initialization +* 09/24/07 NN Added a switch allowing users to do calibration. +* Calibration will help to determine the system clock frequency +* and the count value for one micro-second delay of the target +* specific hardware. +* Removed Delay Percent support +* 11/15/07 NN moved the checking of the File CRC to the end of processing +* 08/28/08 NN Added Calculate checksum support. +***************************************************************/ + + +#include +#include +#include +#include +#include +#include "vmopcode.h" +#include "common.h" + +#define dbg_print(debug, fmt, arg...) \ + if (debug == DEBUG_APP_ON || debug == DEBUG_ALL_ON) \ + { do{printf(fmt,##arg);} while(0); } + +/*************************************************************** +* +* File pointer to the VME file. +* +***************************************************************/ + +FILE *g_pVMEFile = NULL; + +/*************************************************************** +* +* Functions declared in this ispvm_ui.c module +* +***************************************************************/ +unsigned char GetByte(void); +void vme_out_char(unsigned char charOut); +void vme_out_hex(unsigned char hexOut); +void vme_out_string(char *stringOut); +void ispVMMemManager(signed char cTarget, unsigned short usSize); +void ispVMFreeMem(void); +void error_handler(short a_siRetCode, char *pszMessage); +signed char ispVM(const char *a_pszFilename); + +/*************************************************************** +* +* Global variables. +* +***************************************************************/ +unsigned short g_usPreviousSize = 0; +unsigned short g_usExpectedCRC = 0; + +/*************************************************************** +* +* External variables and functions declared in ivm_core.c module. +* +***************************************************************/ +extern signed char ispVMCode(); +extern void ispVMCalculateCRC32(unsigned char a_ucData); +extern void ispVMStart(); +extern void ispVMEnd(); +extern void ispVMStateMachine(signed char NextState); +extern void writePort(unsigned char a_ucPins, unsigned char a_ucValue); +extern void sclock(); +extern unsigned char readPort(); +extern unsigned short g_usCalculatedCRC; +extern unsigned short g_usDataType; +extern unsigned char *g_pucOutMaskData, +*g_pucInData, +*g_pucOutData, +*g_pucHIRData, +*g_pucTIRData, +*g_pucHDRData, +*g_pucTDRData, +*g_pucOutDMaskData, +*g_pucIntelBuffer; +extern unsigned char *g_pucHeapMemory; +extern unsigned short g_iHeapCounter; +extern unsigned short g_iHEAPSize; +extern unsigned short g_usIntelDataIndex; +extern unsigned short g_usIntelBufferSize; +extern LVDSPair *g_pLVDSList; +/* 08/28/08 NN Added Calculate checksum support. */ +extern unsigned long g_usChecksum; +extern unsigned int g_uiChecksumIndex; +/*************************************************************** +* +* External variables and functions declared in hardware.c module. +* +***************************************************************/ +extern void calibration(void); +extern unsigned short g_usCpu_Frequency; + +static int is_debug_on = -1; + +/*************************************************************** +* +* Supported VME versions. +* +***************************************************************/ + +const char *const g_szSupportedVersions[] = { "__VME2.0", "__VME3.0", "____12.0", "____12.1", 0 }; + +/*************************************************************** +* +* GetByte +* +* Returns a byte to the caller. The returned byte depends on the +* g_usDataType register. If the HEAP_IN bit is set, then the byte +* is returned from the HEAP. If the LHEAP_IN bit is set, then +* the byte is returned from the intelligent buffer. Otherwise, +* the byte is returned directly from the VME file. +* +***************************************************************/ + +char* strlwr(char *str) +{ + char *orig = str; + /* process the string */ + for (; *str != '\0'; str++) + *str = tolower(*str); + return orig; +} + + +unsigned char GetByte() +{ + unsigned char ucData = 0; + + if (g_usDataType & HEAP_IN) { + + /*************************************************************** + * + * Get data from repeat buffer. + * + ***************************************************************/ + + if (g_iHeapCounter > g_iHEAPSize) { + + /*************************************************************** + * + * Data over-run. + * + ***************************************************************/ + + return 0xFF; + } + + ucData = g_pucHeapMemory[g_iHeapCounter++]; + } + else if ( g_usDataType & LHEAP_IN ) { + + /*************************************************************** + * + * Get data from intel buffer. + * + ***************************************************************/ + + if (g_usIntelDataIndex >= g_usIntelBufferSize) { + + /*************************************************************** + * + * Data over-run. + * + ***************************************************************/ + + return 0xFF; + } + + ucData = g_pucIntelBuffer[g_usIntelDataIndex++]; + } + else { + + /*************************************************************** + * + * Get data from file. + * + ***************************************************************/ + + ucData = (unsigned char)fgetc(g_pVMEFile); + + + if (feof(g_pVMEFile)) { + + /*************************************************************** + * + * Reached EOF. + * + ***************************************************************/ + + return 0xFF; + } + /*************************************************************** + * + * Calculate the 32-bit CRC if the expected CRC exist. + * + ***************************************************************/ + if( g_usExpectedCRC != 0) + { + ispVMCalculateCRC32(ucData); + } + } + + return (ucData); +} + +/*************************************************************** +* +* vme_out_char +* +* Send a character out to the output resource if available. +* The monitor is the default output resource. +* +* +***************************************************************/ +void vme_out_char(unsigned char charOut) +{ + dbg_print(is_debug_on, "%c", charOut); +} +/*************************************************************** +* +* vme_out_hex +* +* Send a character out as in hex format to the output resource +* if available. The monitor is the default output resource. +* +* +***************************************************************/ +void vme_out_hex(unsigned char hexOut) +{ + dbg_print(is_debug_on, "%.2X", hexOut); +} +/*************************************************************** +* +* vme_out_string +* +* Send a text string out to the output resource if available. +* The monitor is the default output resource. +* +* +***************************************************************/ +void vme_out_string(char *stringOut) +{ + if (is_debug_on == -1) { + is_debug_on = firmware_upgrade_debug(); + } + + dbg_print(is_debug_on, stringOut); +} +/*************************************************************** +* +* ispVMMemManager +* +* Allocate memory based on cTarget. The memory size is specified +* by usSize. +* +***************************************************************/ + +void ispVMMemManager(signed char cTarget, unsigned short usSize) +{ + switch (cTarget) { + case XTDI: + case TDI: + if (g_pucInData != NULL) { + if (g_usPreviousSize == usSize) { /*memory exist*/ + break; + } + else { + free(g_pucInData); + g_pucInData = NULL; + } + } + g_pucInData = (unsigned char *)malloc(usSize / 8 + 2); + g_usPreviousSize = usSize; + case XTDO: + case TDO: + if (g_pucOutData != NULL) { + if (g_usPreviousSize == usSize) { /*already exist*/ + break; + } + else { + free(g_pucOutData); + g_pucOutData = NULL; + } + } + g_pucOutData = (unsigned char *)malloc(usSize / 8 + 2); + g_usPreviousSize = usSize; + break; + case MASK: + if (g_pucOutMaskData != NULL) { + if (g_usPreviousSize == usSize) { /*already allocated*/ + break; + } + else { + free(g_pucOutMaskData); + g_pucOutMaskData = NULL; + } + } + g_pucOutMaskData = (unsigned char *)malloc(usSize / 8 + 2); + g_usPreviousSize = usSize; + break; + case HIR: + if (g_pucHIRData != NULL) { + free(g_pucHIRData); + g_pucHIRData = NULL; + } + g_pucHIRData = (unsigned char *)malloc(usSize / 8 + 2); + break; + case TIR: + if (g_pucTIRData != NULL) { + free(g_pucTIRData); + g_pucTIRData = NULL; + } + g_pucTIRData = (unsigned char *)malloc(usSize / 8 + 2); + break; + case HDR: + if (g_pucHDRData != NULL) { + free(g_pucHDRData); + g_pucHDRData = NULL; + } + g_pucHDRData = (unsigned char *)malloc(usSize / 8 + 2); + break; + case TDR: + if (g_pucTDRData != NULL) { + free(g_pucTDRData); + g_pucTDRData = NULL; + } + g_pucTDRData = (unsigned char *)malloc(usSize / 8 + 2); + break; + case HEAP: + if (g_pucHeapMemory != NULL) { + free(g_pucHeapMemory); + g_pucHeapMemory = NULL; + } + g_pucHeapMemory = (unsigned char *)malloc(usSize + 2); + break; + case DMASK: + if (g_pucOutDMaskData != NULL) { + if (g_usPreviousSize == usSize) { /*already allocated*/ + break; + } + else { + free(g_pucOutDMaskData); + g_pucOutDMaskData = NULL; + } + } + g_pucOutDMaskData = (unsigned char *)malloc(usSize / 8 + 2); + g_usPreviousSize = usSize; + break; + case LHEAP: + if (g_pucIntelBuffer != NULL) { + free(g_pucIntelBuffer); + g_pucIntelBuffer = NULL; + } + g_pucIntelBuffer = (unsigned char *)malloc(usSize + 2); + break; + case LVDS: + if (g_pLVDSList != NULL) { + free(g_pLVDSList); + g_pLVDSList = NULL; + } + g_pLVDSList = (LVDSPair * )calloc(usSize, sizeof(LVDSPair)); + break; + default: + return; + } +} + +/*************************************************************** +* +* ispVMFreeMem +* +* Free memory that were dynamically allocated. +* +***************************************************************/ + +void ispVMFreeMem() +{ + if (g_pucHeapMemory != NULL) { + free(g_pucHeapMemory); + g_pucHeapMemory = NULL; + } + + if (g_pucOutMaskData != NULL) { + free(g_pucOutMaskData); + g_pucOutMaskData = NULL; + } + + if (g_pucInData != NULL) { + free(g_pucInData); + g_pucInData = NULL; + } + + if (g_pucOutData != NULL) { + free(g_pucOutData); + g_pucOutData = NULL; + } + + if (g_pucHIRData != NULL) { + free(g_pucHIRData); + g_pucHIRData = NULL; + } + + if (g_pucTIRData != NULL) { + free(g_pucTIRData); + g_pucTIRData = NULL; + } + + if (g_pucHDRData != NULL) { + free(g_pucHDRData); + g_pucHDRData = NULL; + } + + if (g_pucTDRData != NULL) { + free(g_pucTDRData); + g_pucTDRData = NULL; + } + + if (g_pucOutDMaskData != NULL) { + free(g_pucOutDMaskData); + g_pucOutDMaskData = NULL; + } + + if (g_pucIntelBuffer != NULL) { + free(g_pucIntelBuffer); + g_pucIntelBuffer = NULL; + } + + if (g_pLVDSList != NULL) { + free(g_pLVDSList); + g_pLVDSList = NULL; + } +} + +/*************************************************************** +* +* error_handler +* +* Reports the error message. +* +***************************************************************/ + +void error_handler(short a_siRetCode, char *pszMessage) +{ + const char *pszErrorMessage[] = { "pass", + "verification fail", + "can't find the file", + "wrong file type", + "file error", + "option error", + "crc verification error" }; + + strcpy(pszMessage, pszErrorMessage[-a_siRetCode]); +} +/*************************************************************** +* +* ispVM +* +* The entry point of the ispVM embedded. If the version and CRC +* are verified, then the VME will be processed. +* +***************************************************************/ + +signed char ispVM(const char *a_pszFilename) +{ + char szFileVersion[9] = { 0 }; + signed char cRetCode = 0; + signed char cIndex = 0; + signed char cVersionIndex = 0; + unsigned char ucReadByte = 0; + + /*************************************************************** + * + * Global variables initialization. + * + * 09/11/07 NN Added + ***************************************************************/ + g_pucHeapMemory = NULL; + g_iHeapCounter = 0; + g_iHEAPSize = 0; + g_usIntelDataIndex = 0; + g_usIntelBufferSize = 0; + g_usPreviousSize = 0; + + /*************************************************************** + * + * Open a file pointer to the VME file. + * + ***************************************************************/ + + + + if ((g_pVMEFile = fopen(a_pszFilename, "rb")) == NULL) { + return VME_FILE_READ_FAILURE; + } + g_usCalculatedCRC = 0; + g_usExpectedCRC = 0; + ucReadByte = GetByte(); + //dbg_print(is_debug_on, "data: 0x%x.\n", ucReadByte); + switch (ucReadByte) { + case FILE_CRC: + + /*************************************************************** + * + * Read and store the expected CRC to do the comparison at the end. + * Only versions 3.0 and higher support CRC protection. + * + ***************************************************************/ + + g_usExpectedCRC = (unsigned char)fgetc(g_pVMEFile); + g_usExpectedCRC <<= 8; + g_usExpectedCRC |= fgetc(g_pVMEFile); + + + /*************************************************************** + * + * Read and store the version of the VME file. + * + ***************************************************************/ + + + for (cIndex = 0; cIndex < 8; cIndex++) { + szFileVersion[cIndex] = GetByte(); + } + break; + default: + + /*************************************************************** + * + * Read and store the version of the VME file. Must be version 2.0. + * + ***************************************************************/ + + szFileVersion[0] = (signed char)ucReadByte; + for (cIndex = 1; cIndex < 8; cIndex++) { + szFileVersion[cIndex] = GetByte(); + } + + break; + } + + /*************************************************************** + * + * Compare the VME file version against the supported version. + * + ***************************************************************/ + /* check the file version: the value of 0x03-0x0a */ + for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0; cVersionIndex++) { + for (cIndex = 0; cIndex < 8; cIndex++) { + if (szFileVersion[cIndex] != g_szSupportedVersions[cVersionIndex][cIndex]) { + cRetCode = VME_VERSION_FAILURE; + break; + } + cRetCode = 0; + } + + if (cRetCode == 0) { + + /*************************************************************** + * + * Found matching version, break. + * + ***************************************************************/ + + break; + } + } + + if (cRetCode < 0) { + + /*************************************************************** + * + * VME file version failed to match the supported versions. + * + ***************************************************************/ + + fclose(g_pVMEFile); + g_pVMEFile = NULL; + return VME_VERSION_FAILURE; + } + + /*************************************************************** + * + * Enable the JTAG port to communicate with the device. + * Set the JTAG state machine to the Test-Logic/Reset State. + * + ***************************************************************/ + ispVMStart(); + + + /*************************************************************** + * + * Process the VME file. + * + ***************************************************************/ + + cRetCode = ispVMCode(); + + /*************************************************************** + * + * Set the JTAG State Machine to Test-Logic/Reset state then disable + * the communication with the JTAG port. + * + ***************************************************************/ + + ispVMEnd(); + + fclose(g_pVMEFile); + g_pVMEFile = NULL; + + + ispVMFreeMem(); + + /*************************************************************** + * + * Compare the expected CRC versus the calculated CRC. + * + ***************************************************************/ + + if (cRetCode == 0 && g_usExpectedCRC != 0 && (g_usExpectedCRC != g_usCalculatedCRC)) { + printf("Expected CRC: 0x%.4X\n", g_usExpectedCRC); + printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC); + return VME_CRC_FAILURE; + } + + return (cRetCode); +} + +/*************************************************************** +* +* main +* +***************************************************************/ +extern int g_file_fd; +int ispvme_main(int argc, char *argv[]) +{ + unsigned short iCommandLineIndex = 0; + short siRetCode = 0; + char szExtension[5] = { 0 }; + char szCommandLineArg[300] = { 0 }; + short sicalibrate = 0; + + /* 08/28/08 NN Added Calculate checksum support. */ + g_usChecksum = 0; + g_uiChecksumIndex = 0; + + g_file_fd = open("/dev/firmware_cpld_ispvme0", O_RDWR); + if (g_file_fd < 0) { + printf("can't open device\r\n"); + return -1; + } + + vme_out_string(" Lattice Semiconductor Corp.\n"); + vme_out_string("\n ispVME(tm) V"); + vme_out_string(VME_VERSION_NUMBER); + vme_out_string(" Copyright 1998-2011.\n"); + vme_out_string("\nFor daisy chain programming of all in-system programmable devices\n\n"); + + if (argc < 2) { + vme_out_string("\nUsage: vme [option] vme_file [vme_file]\n"); + vme_out_string("Example: vme vme_file1.vme vme_file2.vme\n"); + vme_out_string("option -c: do the calibration.\n"); + vme_out_string("Example: vme -c\n"); + vme_out_string("Example: vme -c vme_file1.vme vme_file2.vme\n"); + vme_out_string("\n\n"); + close(g_file_fd); + return -1; /* Used by superiors to judge whether the upgrade is successful */ + //exit(1); + } + for (iCommandLineIndex = 1; iCommandLineIndex < argc; iCommandLineIndex++) { + strcpy(szCommandLineArg, argv[iCommandLineIndex]); + if (!strcmp(strlwr(szCommandLineArg), "-c") && (iCommandLineIndex == 1)) { + sicalibrate = 1; + } else if (!strcmp(strlwr(szCommandLineArg), "-c") && (iCommandLineIndex != 1)) { + vme_out_string("Error: calibrate option -c must be the first argument\n\n"); + close(g_file_fd); + return -1; /* Used by superiors to judge whether the upgrade is successful */ + //exit(1); + } else { + strcpy(szExtension, &szCommandLineArg[strlen(szCommandLineArg) - 4]); + strlwr(szExtension); + if (strcmp(szExtension, ".vme")) { + vme_out_string("Error: VME files must end with the extension *.vme\n\n"); + close(g_file_fd); + return -1; /* Used by superiors to judge whether the upgrade is successful */ + //exit(1); + } + } + } + siRetCode = 0; + + if (sicalibrate) { + calibration(); + } + for (iCommandLineIndex = 1; iCommandLineIndex < argc; iCommandLineIndex++) { /* Process all VME files sequentially */ + strcpy(szCommandLineArg, argv[iCommandLineIndex]); + if (!strcmp(strlwr(szCommandLineArg), "-c") && (iCommandLineIndex == 1)) { + + } else if (!strcmp(strlwr(szCommandLineArg), "-checksum")) { + + } else { + vme_out_string("Processing virtual machine file ("); + vme_out_string(szCommandLineArg); + vme_out_string(")......\n\n"); + siRetCode = ispVM(szCommandLineArg); + if (siRetCode < 0) { + break; + } + } + } + + if (siRetCode < 0) { + error_handler(siRetCode, szCommandLineArg); + vme_out_string("Failed due to "); + vme_out_string(szCommandLineArg); + vme_out_string("\n\n"); + vme_out_string("+=======+\n"); + vme_out_string("| FAIL! |\n"); + vme_out_string("+=======+\n\n"); + } else { + vme_out_string("+=======+\n"); + vme_out_string("| PASS! |\n"); + vme_out_string("+=======+\n\n"); + /* 08/28/08 NN Added Calculate checksum support. */ + if (g_usChecksum != 0) { + g_usChecksum &= 0xFFFF; + printf("Data Checksum: %.4X\n\n", (unsigned int)g_usChecksum); + g_usChecksum = 0; + } + } + close(g_file_fd); + return siRetCode; /* Used by superiors to judge whether the upgrade is successful */ + //exit(siRetCode); +} + +/** +* function:CPLD online upgrade channel test program +* input parameters: None +* output parameters:None +* return: 0 means test successfully -1 means test failed +*/ +int ispvme_test(void) +{ + int ret = 0; + unsigned char index = 0; + unsigned char indata = 0,outdata = 0; + unsigned char datasize = 8; + unsigned int tmpdata = 0; + char curbit = 0; + int nDevices = 0; + + g_file_fd = open("/dev/firmware_cpld_ispvme0", O_RDWR); + if (g_file_fd < 0) { + printf("can't open device\r\n"); + return -1; + } + + /* go to Shift-IR */ + ispVMStart(); + ispVMStateMachine(IDLE); + ispVMStateMachine(IRPAUSE); + ispVMStateMachine(SHIFTIR); + + /* Send plenty of ones into the IR registers,that makes sure all devices are in BYPASS! */ + for (index = 0; index < 100; index++) { + writePort(JTAG_TDI, 1); + sclock(); + } + + /* exit Shift-IR,and go to Shift-DR */ + ispVMStateMachine(IRPAUSE); + ispVMStateMachine(DRPAUSE); + ispVMStateMachine(SHIFTDR); + + /* Send plenty of zeros into the DR registers to flush them */ + for (index = 0; index < 100; index++) { + writePort(JTAG_TDI, 0); + sclock(); + } + + /* now send ones until we receive one back,to find out number of device(s) */ + for(index = 0; index < 100; index++){ + writePort(JTAG_TDI, 1); + sclock(); + curbit = readPort(); + if(1 == curbit){ + nDevices = index + 1; + break; + } + } + + /*flush again */ + for (index = 0; index < 100; index++) { + writePort(JTAG_TDI, 0); + sclock(); + } + + /* test data probe */ + indata = 0x5a; + for (index = 0; index < datasize + nDevices; index++) { + tmpdata <<= 1; + curbit = readPort(); + tmpdata |= curbit; + writePort(JTAG_TDI, ((indata << index) & 0x80) ? 0x01:0x00); + sclock(); + } + outdata = (tmpdata & 0xFF); + if(outdata != indata){ + ret = -1; + } + + /* go to Test-Logic-Reset */ + ispVMStateMachine(IDLE); + ispVMStart(); + + /* close ispvme */ + close(g_file_fd); + return ret; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ivm_core.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ivm_core.c new file mode 100644 index 000000000000..c6247f6ffa66 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/ivm_core.c @@ -0,0 +1,3035 @@ +/*************************************************************** +* +* Lattice Semiconductor Corp. Copyright 2009 +* +* ispVME Embedded allows programming of Lattice's suite of FPGA +* devices on embedded systems through the JTAG port. The software +* is distributed in source code form and is open to re - distribution +* and modification where applicable. +* +* Revision History of ivm_core.c module: +* 4/25/06 ht Change some variables from unsigned short or int +* to long int to make the code compiler independent. +* 5/24/06 ht Support using RESET (TRST) pin as a special purpose +* control pin such as triggering the loading of known +* state exit. +* 3/6/07 ht added functions to support output to terminals +* +* 09/24/07 NN Type cast mismatch variables +* Moved the sclock() function to hardware.c +* 08/28/08 NN Added Calculate checksum support. +* 4/1/09 Nguyen replaced the recursive function call codes on +* the ispVMLCOUNT function +* +***************************************************************/ + +#include +#include +#include "vmopcode.h" +#include "common.h" + +/*************************************************************** +* +* Global variables used to specify the flow control and data type. +* +* g_usFlowControl: flow control register. Each bit in the +* register can potentially change the +* personality of the embedded engine. +* g_usDataType: holds the data type of the current row. +* +***************************************************************/ + +unsigned short g_usFlowControl = 0x0000; +unsigned short g_usDataType = 0x0000; + +/*************************************************************** +* +* Global variables used to specify the ENDDR and ENDIR. +* +* g_ucEndDR: the state that the device goes to after SDR. +* g_ucEndIR: the state that the device goes to after SIR. +* +***************************************************************/ + +unsigned char g_ucEndDR = DRPAUSE; +unsigned char g_ucEndIR = IRPAUSE; + +/*************************************************************** +* +* Global variables used to support header/trailer. +* +* g_usHeadDR: the number of lead devices in bypass. +* g_usHeadIR: the sum of IR length of lead devices. +* g_usTailDR: the number of tail devices in bypass. +* g_usTailIR: the sum of IR length of tail devices. +* +***************************************************************/ + +unsigned short g_usHeadDR = 0; +unsigned short g_usHeadIR = 0; +unsigned short g_usTailDR = 0; +unsigned short g_usTailIR = 0; + +/*************************************************************** +* +* Global variable to store the number of bits of data or instruction +* to be shifted into or out from the device. +* +***************************************************************/ + +unsigned short g_usiDataSize = 0; + +/*************************************************************** +* +* Stores the frequency. Default to 1 MHz. +* +***************************************************************/ + +int g_iFrequency = 1000; + +/*************************************************************** +* +* Stores the maximum amount of ram needed to hold a row of data. +* +***************************************************************/ + +unsigned short g_usMaxSize = 0; + +/*************************************************************** +* +* Stores the LSH or RSH value. +* +***************************************************************/ + +unsigned short g_usShiftValue = 0; + +/*************************************************************** +* +* Stores the current repeat loop value. +* +***************************************************************/ + +unsigned short g_usRepeatLoops = 0; + +/*************************************************************** +* +* Stores the current vendor. +* +***************************************************************/ + +signed char g_cVendor = LATTICE; + +/*************************************************************** +* +* Stores the VME file CRC. +* +***************************************************************/ + +unsigned short g_usCalculatedCRC = 0; + +/*************************************************************** +* +* Stores the Device Checksum. +* +***************************************************************/ +//08/28/08 NN Added Calculate checksum support. +unsigned long g_usChecksum = 0; +unsigned int g_uiChecksumIndex = 0; + +/*************************************************************** +* +* Stores the current state of the JTAG state machine. +* +***************************************************************/ + +signed char g_cCurrentJTAGState = 0; + +/*************************************************************** +* +* Global variables used to support looping. +* +* g_pucHeapMemory: holds the entire repeat loop. +* g_iHeapCounter: points to the current byte in the repeat loop. +* g_iHEAPSize: the current size of the repeat in bytes. +* +***************************************************************/ + +unsigned char *g_pucHeapMemory = NULL; +unsigned short g_iHeapCounter = 0; +unsigned short g_iHEAPSize = 0; + +/*************************************************************** +* +* Global variables used to support intelligent programming. +* +* g_usIntelDataIndex: points to the current byte of the +* intelligent buffer. +* g_usIntelBufferSize: holds the size of the intelligent +* buffer. +* +***************************************************************/ + +unsigned short g_usIntelDataIndex = 0; +unsigned short g_usIntelBufferSize = 0; + +/**************************************************************************** +* +* Holds the maximum size of each respective buffer. These variables are used +* to write the HEX files when converting VME to HEX. +* +*****************************************************************************/ + +unsigned short g_usTDOSize = 0; +unsigned short g_usMASKSize = 0; +unsigned short g_usTDISize = 0; +unsigned short g_usDMASKSize = 0; +unsigned short g_usLCOUNTSize = 0; +unsigned short g_usHDRSize = 0; +unsigned short g_usTDRSize = 0; +unsigned short g_usHIRSize = 0; +unsigned short g_usTIRSize = 0; +unsigned short g_usHeapSize = 0; + +/*************************************************************** +* +* Global variables used to store data. +* +* g_pucOutMaskData: local RAM to hold one row of MASK data. +* g_pucInData: local RAM to hold one row of TDI data. +* g_pucOutData: local RAM to hold one row of TDO data. +* g_pucHIRData: local RAM to hold the current SIR header. +* g_pucTIRData: local RAM to hold the current SIR trailer. +* g_pucHDRData: local RAM to hold the current SDR header. +* g_pucTDRData: local RAM to hold the current SDR trailer. +* g_pucIntelBuffer: local RAM to hold the current intelligent buffer. +* g_pucOutDMaskData: local RAM to hold one row of DMASK data. +* +***************************************************************/ + +unsigned char *g_pucOutMaskData = NULL, +*g_pucInData = NULL, +*g_pucOutData = NULL, +*g_pucHIRData = NULL, +*g_pucTIRData = NULL, +*g_pucHDRData = NULL, +*g_pucTDRData = NULL, +*g_pucIntelBuffer = NULL, +*g_pucOutDMaskData = NULL; + +/*************************************************************** +* +* JTAG state machine transition table. +* +***************************************************************/ + +struct { + unsigned char CurState; /* From this state */ + unsigned char NextState; /* Step to this state */ + unsigned char Pattern; /* The tragetory of TMS */ + unsigned char Pulses; /* The number of steps */ +} g_JTAGTransistions[25] = { + { RESET, RESET, 0xFC, 6 }, /* Transitions from RESET */ + { RESET, IDLE, 0x00, 1 }, + { RESET, DRPAUSE, 0x50, 5 }, + { RESET, IRPAUSE, 0x68, 6 }, + { IDLE, RESET, 0xE0, 3 }, /* Transitions from IDLE */ + { IDLE, DRPAUSE, 0xA0, 4 }, + { IDLE, IRPAUSE, 0xD0, 5 }, + { DRPAUSE, RESET, 0xF8, 5 }, /* Transitions from DRPAUSE */ + { DRPAUSE, IDLE, 0xC0, 3 }, + { DRPAUSE, IRPAUSE, 0xF4, 7 }, + { DRPAUSE, DRPAUSE, 0xE8, 6 }, /* 06/14/06 Support POLING STATUS LOOP*/ + { IRPAUSE, RESET, 0xF8, 5 }, /* Transitions from IRPAUSE */ + { IRPAUSE, IDLE, 0xC0, 3 }, + { IRPAUSE, DRPAUSE, 0xE8, 6 }, + { DRPAUSE, SHIFTDR, 0x80, 2 }, /* Extra transitions using SHIFTDR */ + { IRPAUSE, SHIFTDR, 0xE0, 5 }, + { SHIFTDR, DRPAUSE, 0x80, 2 }, + { SHIFTDR, IDLE, 0xC0, 3 }, + { IRPAUSE, SHIFTIR, 0x80, 2 }, /* Extra transitions using SHIFTIR */ + { SHIFTIR, IRPAUSE, 0x80, 2 }, + { SHIFTIR, IDLE, 0xC0, 3 }, + { DRPAUSE, DRCAPTURE, 0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/ + { DRCAPTURE, DRPAUSE, 0x80, 2 }, + { IDLE, DRCAPTURE, 0x80, 2 }, + { IRPAUSE, DRCAPTURE, 0xE0, 4 } +}; + +/*************************************************************** +* +* List to hold all LVDS pairs. +* +***************************************************************/ + +LVDSPair *g_pLVDSList = NULL; +unsigned short g_usLVDSPairCount = 0; + +/*************************************************************** +* +* Function prototypes. +* +***************************************************************/ + +signed char ispVMCode(); +signed char ispVMDataCode(); +long int ispVMDataSize(); +void ispVMData(unsigned char *Data); +signed char ispVMShift(signed char Code); +signed char ispVMAmble(signed char Code); +signed char ispVMLoop(unsigned short a_usLoopCount); +signed char ispVMBitShift(signed char mode, unsigned short bits); +void ispVMComment(unsigned short a_usCommentSize); +void ispVMHeader(unsigned short a_usHeaderSize); +signed char ispVMLCOUNT(unsigned short a_usCountSize); +void ispVMClocks(unsigned short Clocks); +void ispVMBypass(signed char ScanType, unsigned short Bits); +void ispVMStateMachine(signed char NextState); +void ispVMStart(); +void ispVMEnd(); +signed char ispVMSend(unsigned short int); +signed char ispVMRead(unsigned short int); +signed char ispVMReadandSave(unsigned short int); +signed char ispVMProcessLVDS(unsigned short a_usLVDSCount); + + +/*************************************************************** +* +* External variables and functions in ispvm_ui.c module +* +***************************************************************/ +extern void vme_out_char(unsigned char charOut); +extern void vme_out_hex(unsigned char hexOut); +extern void vme_out_string(char *stringOut); +extern unsigned char GetByte(); +extern void ispVMMemManager(signed char types, unsigned short size); + +/*************************************************************** +* +* External variables and functions in hardware.c module +* +***************************************************************/ +extern void ispVMDelay(unsigned short int a_usMicroSecondDelay); +extern unsigned char readPort(); +extern void writePort(unsigned char pins, unsigned char value); +extern void sclock(); +extern signed char g_cCurrentJTAGState; +#ifdef VME_DEBUG + +/*************************************************************** +* +* GetState +* +* Returns the state as a string based on the opcode. Only used +* for debugging purposes. +* +***************************************************************/ + +const char* GetState(unsigned char a_ucState) +{ + switch (a_ucState) { + case RESET: + return ("RESET"); + case IDLE: + return ("IDLE"); + case IRPAUSE: + return ("IRPAUSE"); + case DRPAUSE: + return ("DRPAUSE"); + case SHIFTIR: + return ("SHIFTIR"); + case SHIFTDR: + return ("SHIFTDR"); + case DRCAPTURE: /* 11/15/05 support DRCAPTURE*/ + return ("DRCAPTURE"); + default: + break; + } + + return 0; +} + +/*************************************************************** +* +* PrintData +* +* Prints the data. Only used for debugging purposes. +* +***************************************************************/ + +void PrintData(unsigned short a_iDataSize, unsigned char *a_pucData) +{ + //09/11/07 NN added local variables initialization + unsigned short usByteSize = 0; + unsigned short usBitIndex = 0; + signed short usByteIndex = 0; + unsigned char ucByte = 0; + unsigned char ucFlipByte = 0; + + if (a_iDataSize % 8) { + //09/11/07 NN Type cast mismatch variables + usByteSize = (unsigned short)(a_iDataSize / 8 + 1); + } else { + //09/11/07 NN Type cast mismatch variables + usByteSize = (unsigned short)(a_iDataSize / 8);// 4 + } + printf("("); + //09/11/07 NN Type cast mismatch variables + for (usByteIndex = (signed short)(usByteSize - 1); usByteIndex >= 0; usByteIndex--) { + ucByte = a_pucData[usByteIndex]; + ucFlipByte = 0x00; + + /*************************************************************** + * + * Flip each byte. + * + ***************************************************************/ + + for (usBitIndex = 0; usBitIndex < 8; usBitIndex++) { + ucFlipByte <<= 1; + if (ucByte & 0x1) { + ucFlipByte |= 0x1; + } + + ucByte >>= 1; + } + + /*************************************************************** + * + * Print the flipped byte. + * + ***************************************************************/ + + printf("%.02X", ucFlipByte); + if ((usByteSize - usByteIndex) % 40 == 39) { + printf("\n\t\t"); + } + if (usByteIndex < 0) + break; + } + printf(")"); +} +#endif /* VME_DEBUG */ + +/*************************************************************** +* +* ispVMDataSize +* +* Returns a VME-encoded number, usually used to indicate the +* bit length of an SIR/SDR command. +* +***************************************************************/ + +long int ispVMDataSize() +{ + /* 09/11/07 NN added local variables initialization */ + long int iSize = 0; + signed char cCurrentByte = 0; + signed char cIndex = 0; + cIndex = 0; + + while ((cCurrentByte = GetByte()) & 0x80) { + iSize |= ((long int)(cCurrentByte & 0x7F)) << cIndex; + cIndex += 7; + } + iSize |= ((long int)(cCurrentByte & 0x7F)) << cIndex; + + return iSize; +} + +/*************************************************************** +* +* ispVMCode +* +* This is the heart of the embedded engine. All the high-level opcodes +* are extracted here. Once they have been identified, then it +* will call other functions to handle the processing. +* +***************************************************************/ + +signed char ispVMCode() +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short iRepeatSize = 0; + signed char cOpcode = 0; + signed char cRetCode = 0; + unsigned char ucState = 0; + unsigned short usDelay = 0; + unsigned short usToggle = 0; + unsigned char usByte = 0; + + /*************************************************************** + * + * Check the compression flag only if this is the first time + * this function is entered. Do not check the compression flag if + * it is being called recursively from other functions within + * the embedded engine. + * + ***************************************************************/ + + if (!(g_usDataType & LHEAP_IN) && !(g_usDataType & HEAP_IN)) { + usByte = GetByte(); + if (usByte == 0xf1) { + g_usDataType |= COMPRESS; + } else if (usByte == 0xf2) { + g_usDataType &= ~COMPRESS; + } else { + return VME_INVALID_FILE; + } + } + + + /*************************************************************** + * + * Begin looping through all the VME opcodes. + * + ***************************************************************/ + while ((cOpcode = GetByte()) >= 0) { + switch (cOpcode) { + case STATE: + + /*************************************************************** + * + * Step the JTAG state machine. + * + ***************************************************************/ + + ucState = GetByte(); + /*************************************************************** + * + * Step the JTAG state machine to DRCAPTURE to support Looping. + * + ***************************************************************/ + + if ((g_usDataType & LHEAP_IN) && + (ucState == DRPAUSE) && + (g_cCurrentJTAGState == ucState)) { + ispVMStateMachine(DRCAPTURE); + } + + ispVMStateMachine(ucState); + +#ifdef VME_DEBUG + if (g_usDataType & LHEAP_IN) { + printf("LDELAY %s ", GetState(ucState)); + } else { + printf("STATE %s;\n", GetState(ucState)); + } +#endif /* VME_DEBUG */ + break; + case SIR: + case SDR: + case XSDR: + +#ifdef VME_DEBUG + switch (cOpcode) { + case SIR: + printf("SIR "); + break; + case SDR: + case XSDR: + if (g_usDataType & LHEAP_IN) { + printf("LSDR "); + } else { + printf("SDR "); + } + break; + } +#endif /* VME_DEBUG */ + /*************************************************************** + * + * Shift in data into the device. + * + ***************************************************************/ + cRetCode = ispVMShift(cOpcode); + if (cRetCode != 0) { + return (cRetCode); + } + break; + case WAIT: + + /*************************************************************** + * + * Observe delay. + * + ***************************************************************/ + + /* 9/11/07 NN Type cast mismatch variables */ + usDelay = (unsigned short)ispVMDataSize(); + ispVMDelay(usDelay); + +#ifdef VME_DEBUG + if (usDelay & 0x8000) { + + /*************************************************************** + * + * Since MSB is set, the delay time must be decoded to + * millisecond. The SVF2VME encodes the MSB to represent + * millisecond. + * + ***************************************************************/ + + usDelay &= ~0x8000; + if (g_usDataType & LHEAP_IN) { + printf("%.2E SEC;\n", (float)usDelay / 1000); + } else { + printf("RUNTEST %.2E SEC;\n", (float)usDelay / 1000); + } + } else { + + /*************************************************************** + * + * Since MSB is not set, the delay time is given as microseconds. + * + ***************************************************************/ + + if (g_usDataType & LHEAP_IN) { + printf("%.2E SEC;\n", (float)usDelay / 1000000); + } else { + printf("RUNTEST %.2E SEC;\n", (float)usDelay / 1000000); + } + } +#endif /* VME_DEBUG */ + break; + case TCK: + + /*************************************************************** + * + * Issue clock toggles. + * + ***************************************************************/ + + /* 09/11/07 NN Type cast mismatch variables */ + usToggle = (unsigned short)ispVMDataSize(); + ispVMClocks(usToggle); + +#ifdef VME_DEBUG + printf("RUNTEST %d TCK;\n", usToggle); +#endif /* VME_DEBUG */ + break; + case ENDDR: + + /*************************************************************** + * + * Set the ENDDR. + * + ***************************************************************/ + + g_ucEndDR = GetByte(); + +#ifdef VME_DEBUG + printf("ENDDR %s;\n", GetState(g_ucEndDR)); +#endif /* VME_DEBUG */ + break; + case ENDIR: + + /*************************************************************** + * + * Set the ENDIR. + * + ***************************************************************/ + + g_ucEndIR = GetByte(); + +#ifdef VME_DEBUG + printf("ENDIR %s;\n", GetState(g_ucEndIR)); +#endif /* VME_DEBUG */ + break; + case HIR: + case TIR: + case HDR: + case TDR: + +#ifdef VME_DEBUG + switch (cOpcode) { + case HIR: + printf("HIR "); + break; + case TIR: + printf("TIR "); + break; + case HDR: + printf("HDR "); + break; + case TDR: + printf("TDR "); + break; + } +#endif /* VME_DEBUG */ + + /*************************************************************** + * + * Set the header/trailer of the device in order to bypass + * successfully. + * + ***************************************************************/ + + cRetCode = ispVMAmble(cOpcode); + if (cRetCode != 0) { + return (cRetCode); + } + +#ifdef VME_DEBUG + printf(";\n"); +#endif /* VME_DEBUG */ + break; + case MEM: + + /*************************************************************** + * + * The maximum RAM required to support processing one row of the + * VME file. + * + ***************************************************************/ + + //09/11/07 NN Type cast mismatch variables + g_usMaxSize = (unsigned short)ispVMDataSize(); + +#ifdef VME_DEBUG + printf("// MEMSIZE %d\n", g_usMaxSize); +#endif /* VME_DEBUG */ + break; + case VENDOR: + + /*************************************************************** + * + * Set the VENDOR type. + * + ***************************************************************/ + + cOpcode = GetByte(); + switch (cOpcode) { + case LATTICE: +#ifdef VME_DEBUG + printf("// VENDOR LATTICE\n"); +#endif /* VME_DEBUG */ + g_cVendor = LATTICE; + break; + case ALTERA: +#ifdef VME_DEBUG + printf("// VENDOR ALTERA\n"); +#endif /* VME_DEBUG */ + g_cVendor = ALTERA; + break; + case XILINX: +#ifdef VME_DEBUG + printf("// VENDOR XILINX\n"); +#endif /* VME_DEBUG */ + g_cVendor = XILINX; + break; + default: + break; + } + break; + case SETFLOW: + + /*************************************************************** + * + * Set the flow control. Flow control determines the personality + * of the embedded engine. + * + ***************************************************************/ + + /* 09/11/07 NN Type cast mismatch variables */ + g_usFlowControl |= (unsigned short)ispVMDataSize(); + break; + case RESETFLOW: + + /*************************************************************** + * + * Unset the flow control. + * + ***************************************************************/ + + /* 09/11/07 NN Type cast mismatch variables */ + g_usFlowControl &= (unsigned short)~(ispVMDataSize()); + break; + case HEAP: + + /*************************************************************** + * + * Allocate heap size to store loops. + * + ***************************************************************/ + + cRetCode = GetByte(); + if (cRetCode != SECUREHEAP) { + return VME_INVALID_FILE; + } + /* 09/11/07 NN Type cast mismatch variables */ + g_iHEAPSize = (unsigned short)ispVMDataSize(); + + /**************************************************************************** + * + * Store the maximum size of the HEAP buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_iHEAPSize > g_usHeapSize) { + g_usHeapSize = g_iHEAPSize; + } + + ispVMMemManager(HEAP, (unsigned short)g_iHEAPSize); + break; + case REPEAT: + + /*************************************************************** + * + * Execute loops. + * + ***************************************************************/ + + g_usRepeatLoops = 0; + + /* 09/11/07 NN Type cast mismatch variables */ + iRepeatSize = (unsigned short)ispVMDataSize(); + + cRetCode = ispVMLoop((unsigned short)iRepeatSize); + if (cRetCode != 0) { + return (cRetCode); + } + break; + case ENDLOOP: + + /*************************************************************** + * + * Exit point from processing loops. + * + ***************************************************************/ + + return (cRetCode); + case ENDVME: + + /*************************************************************** + * + * The only valid exit point that indicates end of programming. + * + ***************************************************************/ + + return (cRetCode); + case SHR: + + /*************************************************************** + * + * Right-shift address. + * + ***************************************************************/ + + g_usFlowControl |= SHIFTRIGHT; + + /* 09/11/07 NN Type cast mismatch variables */ + g_usShiftValue = (unsigned short)(g_usRepeatLoops * (unsigned short)GetByte()); + break; + case SHL: + + /*************************************************************** + * + * Left-shift address. + * + ***************************************************************/ + + g_usFlowControl |= SHIFTLEFT; + + /* 09/11/07 NN Type cast mismatch variables */ + g_usShiftValue = (unsigned short)(g_usRepeatLoops * (unsigned short)GetByte()); + break; + case FREQUENCY: + + /*************************************************************** + * + * Set the frequency. + * + ***************************************************************/ + + /* 09/11/07 NN Type cast mismatch variables */ + g_iFrequency = (int)(ispVMDataSize()); + /* 10/23/08 NN changed to check if the frequency smaller than 1000 */ + if (g_iFrequency >= 1000) { + g_iFrequency = g_iFrequency / 1000; + if (g_iFrequency == 1) + g_iFrequency = 1000; +#ifdef VME_DEBUG + printf("FREQUENCY %.2E HZ;\n", (float)g_iFrequency * 1000); +#endif /* VME_DEBUG */ + } else { + if (g_iFrequency == 0) + g_iFrequency = 1000; +#ifdef VME_DEBUG + printf("FREQUENCY %.2E HZ;\n", (float)g_iFrequency); +#endif /* VME_DEBUG */ + } + break; + case LCOUNT: + + /*************************************************************** + * + * Process LCOUNT command. + * + ***************************************************************/ + + cRetCode = ispVMLCOUNT((unsigned short)ispVMDataSize()); + if (cRetCode != 0) { + return (cRetCode); + } + break; + case VUES: + + /*************************************************************** + * + * Set the flow control to verify USERCODE. + * + ***************************************************************/ + + g_usFlowControl |= VERIFYUES; + break; + case COMMENT: + + /*************************************************************** + * + * Display comment. + * + ***************************************************************/ + + ispVMComment((unsigned short)ispVMDataSize()); + break; + case LVDS: + + /*************************************************************** + * + * Process LVDS command. + * + ***************************************************************/ + + ispVMProcessLVDS((unsigned short)ispVMDataSize()); + break; + case HEADER: + + /*************************************************************** + * + * Discard header. + * + ***************************************************************/ + + ispVMHeader((unsigned short)ispVMDataSize()); + break; + /* 03/14/06 Support Toggle ispENABLE signal */ + case ispEN: + ucState = GetByte(); + if ((ucState == ON) || (ucState == 0x01)) + writePort(JTAG_ENABLE, 0x01); + else + writePort(JTAG_ENABLE, 0x00); + ispVMDelay(1); + break; + /* 05/24/06 support Toggle TRST pin */ + case TRST: + ucState = GetByte(); + if (ucState == 0x01) + writePort(JTAG_TRST, 0x01); + else + writePort(JTAG_TRST, 0x00); + ispVMDelay(1); + break; + default: + + /*************************************************************** + * + * Invalid opcode encountered. + * + ***************************************************************/ + +#ifdef VME_DEBUG + printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode); +#endif /* VME_DEBUG */ + + return VME_INVALID_FILE; + } + } + + /*************************************************************** + * + * Invalid exit point. Processing the token 'ENDVME' is the only + * valid way to exit the embedded engine. + * + ***************************************************************/ + + return (VME_INVALID_FILE); +} + +/*************************************************************** +* +* ispVMDataCode +* +* Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command. +* +***************************************************************/ + +signed char ispVMDataCode() +{ + /* 09/11/07 NN added local variables initialization */ + signed char cDataByte = 0; + signed char siDataSource = 0; /* source of data from file by default */ + + if (g_usDataType & HEAP_IN) { + siDataSource = 1; /* the source of data from memory */ + } + + /**************************************************************************** + * + * Clear the data type register. + * + *****************************************************************************/ + + g_usDataType &= ~(MASK_DATA + TDI_DATA + TDO_DATA + DMASK_DATA + CMASK_DATA); + + /**************************************************************************** + * + * Iterate through SIR/SDR command and look for TDI, TDO, MASK, etc. + * + *****************************************************************************/ + + while ((cDataByte = GetByte()) >= 0) { + + ispVMMemManager(cDataByte, g_usMaxSize); + switch (cDataByte) { + case TDI: + + /**************************************************************************** + * + * Store the maximum size of the TDI buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usTDISize) { + g_usTDISize = g_usiDataSize; + } + /**************************************************************************** + * + * Updated data type register to indicate that TDI data is currently being + * used. Process the data in the VME file into the TDI buffer. + * + *****************************************************************************/ + + g_usDataType |= TDI_DATA; + ispVMData(g_pucInData); + break; + case XTDO: + + /**************************************************************************** + * + * Store the maximum size of the TDO buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usTDOSize) { + g_usTDOSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Updated data type register to indicate that TDO data is currently being + * used. + * + *****************************************************************************/ + + g_usDataType |= TDO_DATA; + break; + case TDO: + + /**************************************************************************** + * + * Store the maximum size of the TDO buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usTDOSize) { + g_usTDOSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Updated data type register to indicate that TDO data is currently being + * used. Process the data in the VME file into the TDO buffer. + * + *****************************************************************************/ + + g_usDataType |= TDO_DATA; + ispVMData(g_pucOutData); + break; + case MASK: + + /**************************************************************************** + * + * Store the maximum size of the MASK buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usMASKSize) { + g_usMASKSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Updated data type register to indicate that MASK data is currently being + * used. Process the data in the VME file into the MASK buffer. + * + *****************************************************************************/ + + g_usDataType |= MASK_DATA; + ispVMData(g_pucOutMaskData); + break; + case DMASK: + + /**************************************************************************** + * + * Store the maximum size of the DMASK buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usDMASKSize) { + g_usDMASKSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Updated data type register to indicate that DMASK data is currently being + * used. Process the data in the VME file into the DMASK buffer. + * + *****************************************************************************/ + + g_usDataType |= DMASK_DATA; + ispVMData(g_pucOutDMaskData); + break; + case CMASK: + + /**************************************************************************** + * + * Updated data type register to indicate that CMASK data is currently being + * used. Process the data in the VME file into the CMASK buffer. + * + *****************************************************************************/ + + g_usDataType |= CMASK_DATA; + ispVMData(g_pucOutMaskData); + break; + case CONTINUE: + return (0); + default: + + /**************************************************************************** + * + * Encountered invalid opcode. + * + *****************************************************************************/ + + return (VME_INVALID_FILE); + } + + switch (cDataByte) { + case TDI: + + /**************************************************************************** + * + * Left bit shift. Used when performing algorithm looping. + * + *****************************************************************************/ + + if (g_usFlowControl & SHIFTLEFT) { + ispVMBitShift(SHL, g_usShiftValue); + g_usFlowControl &= ~SHIFTLEFT; + } + + /**************************************************************************** + * + * Right bit shift. Used when performing algorithm looping. + * + *****************************************************************************/ + + if (g_usFlowControl & SHIFTRIGHT) { + ispVMBitShift(SHR, g_usShiftValue); + g_usFlowControl &= ~SHIFTRIGHT; + } + default: + break; + } + + if (siDataSource) { + g_usDataType |= HEAP_IN; /*restore data from memory*/ + } + } + + if (siDataSource) { /*fetch data from heap memory upon return*/ + g_usDataType |= HEAP_IN; + } + + if (cDataByte < 0) { + + /**************************************************************************** + * + * Encountered invalid opcode. + * + *****************************************************************************/ + + return (VME_INVALID_FILE); + } else { + return (0); + } +} + +/*************************************************************** +* +* ispVMData +* Extract one row of data operand from the current data type opcode. Perform +* the decompression if necessary. Extra RAM is not required for the +* decompression process. The decompression scheme employed in this module +* is on row by row basis. The format of the data stream: +* [compression code][compressed data stream] +* 0x00 --No compression +* 0x01 --Compress by 0x00. +* Example: +* Original stream: 0x000000000000000000000001 +* Compressed stream: 0x01000901 +* Detail: 0x01 is the code, 0x00 is the key, +* 0x09 is the count of 0x00 bytes, +* 0x01 is the uncompressed byte. +* 0x02 --Compress by 0xFF. +* Example: +* Original stream: 0xFFFFFFFFFFFFFFFFFFFFFF01 +* Compressed stream: 0x02FF0901 +* Detail: 0x02 is the code, 0xFF is the key, +* 0x09 is the count of 0xFF bytes, +* 0x01 is the uncompressed byte. +* 0x03 +* : : +* 0xFE -- Compress by nibble blocks. +* Example: +* Original stream: 0x84210842108421084210 +* Compressed stream: 0x0584210 +* Detail: 0x05 is the code, means 5 nibbles block. +* 0x84210 is the 5 nibble blocks. +* The whole row is 80 bits given by g_usiDataSize. +* The number of times the block repeat itself +* is found by g_usiDataSize/(4*0x05) which is 4. +* 0xFF -- Compress by the most frequently happen byte. +* Example: +* Original stream: 0x04020401030904040404 +* Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0) +* or: 0xFF044090181C240 +* Detail: 0xFF is the code, 0x04 is the key. +* a bit of 0 represent the key shall be put into +* the current bit position and a bit of 1 +* represent copying the next of 8 bits of data +* in. +* +***************************************************************/ + +void ispVMData(unsigned char *ByteData) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short size = 0; + unsigned short i, j, m, getData = 0; + unsigned char cDataByte = 0; + unsigned char compress = 0; + unsigned short FFcount = 0; + unsigned char compr_char = 0xFF; + unsigned short index = 0; + signed char compression = 0; + + /* convert number in bits to bytes */ + if (g_usiDataSize % 8 > 0) { + /* 09/11/07 NN Type cast mismatch variables */ + size = (unsigned short)(g_usiDataSize / 8 + 1); + } else { + /* 09/11/07 NN Type cast mismatch variables */ + size = (unsigned short)(g_usiDataSize / 8); + } + + /* If there is compression, then check if compress by key of 0x00 or 0xFF + or by other keys or by nibble blocks*/ + + if (g_usDataType & COMPRESS) { + compression = 1; + if (((compress = GetByte()) == VAR) && (g_usDataType & HEAP_IN)) { + getData = 1; + g_usDataType &= ~(HEAP_IN); + compress = GetByte(); + } + + switch (compress) { + case 0x00: + /* No compression */ + compression = 0; + break; + case 0x01: + /* Compress by byte 0x00 */ + compr_char = 0x00; + break; + case 0x02: + /* Compress by byte 0xFF */ + compr_char = 0xFF; + break; + case 0xFF: + /* Huffman encoding */ + compr_char = GetByte(); + i = 8; + for (index = 0; index < size; index++) { + ByteData[index] = 0x00; + if (i > 7) { + cDataByte = GetByte(); + i = 0; + } + if ((cDataByte << i++) & 0x80) + m = 8; + else { + ByteData[index] = compr_char; + m = 0; + } + + for (j = 0; j < m; j++) { + if (i > 7) { + cDataByte = GetByte(); + i = 0; + } + ByteData[index] |= ((cDataByte << i++) & 0x80) >> j; + } + } + size = 0; + break; + default: + for (index = 0; index < size; index++) + ByteData[index] = 0x00; + for (index = 0; index < compress; index++) { + if (index % 2 == 0) + cDataByte = GetByte(); + for (i = 0; i < size * 2 / compress; i++) { + /* 09/11/07 NN Type cast mismatch variables */ + j = (unsigned short)(index + (i * (unsigned short)compress)); + /* clear the nibble to zero first */ + if (j % 2) { + if (index % 2) + ByteData[j / 2] |= cDataByte & 0x0F; + else + ByteData[j / 2] |= cDataByte >> 4; + } else { + if (index % 2) + ByteData[j / 2] |= cDataByte << 4; + else + ByteData[j / 2] |= cDataByte & 0xF0; + } + } + } + size = 0; + break; + } + } + + FFcount = 0; + + /* Decompress by byte 0x00 or 0xFF */ + for (index = 0; index < size; index++) { + if (FFcount <= 0) { + cDataByte = GetByte(); + if ((cDataByte == VAR) && (g_usDataType & HEAP_IN) && !getData && !(g_usDataType & COMPRESS)) { + getData = 1; + g_usDataType &= ~(HEAP_IN); + cDataByte = GetByte(); + } + ByteData[index] = cDataByte; + if ((compression) && (cDataByte == compr_char)) /* decompression is on */ + /* 09/11/07 NN Type cast mismatch variables */ + FFcount = (unsigned short)ispVMDataSize(); /* The number of 0xFF or 0x00 bytes */ + } else { + FFcount--; /* Use up the 0xFF chain first */ + ByteData[index] = compr_char; + } + } + + if (getData) { + g_usDataType |= HEAP_IN; + getData = 0; + } +} + +/*************************************************************** +* +* ispVMShift +* +* Processes the SDR/XSDR/SIR commands. +* +***************************************************************/ + +signed char ispVMShift(signed char a_cCode) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short iDataIndex = 0; + unsigned short iReadLoop = 0; + signed char cRetCode = 0; + + cRetCode = 0; + /* 09/11/07 NN Type cast mismatch variables */ + g_usiDataSize = (unsigned short)ispVMDataSize(); + + g_usDataType &= ~(SIR_DATA + EXPRESS + SDR_DATA); /* clear the flags first */ + + switch (a_cCode) { + case SIR: + g_usDataType |= SIR_DATA; + /* 1/15/04 If performing cascading, then go directly to SHIFTIR. Else, + go to IRPAUSE before going to SHIFTIR */ + if (g_usFlowControl & CASCADE) { + ispVMStateMachine(SHIFTIR); + } else { + ispVMStateMachine(IRPAUSE); + ispVMStateMachine(SHIFTIR); + if (g_usHeadIR > 0) { + ispVMBypass(HIR, g_usHeadIR); + sclock(); + } + } + break; + case XSDR: + g_usDataType |= EXPRESS; /* mark simultaneous in and out */ + case SDR: + g_usDataType |= SDR_DATA; + /* 1/15/04 If already in SHIFTDR, then do not move state or shift in header. + This would imply that the previously shifted frame was a cascaded frame. */ + if (g_cCurrentJTAGState != SHIFTDR) { + /* 1/15/04 If performing cascading, then go directly to SHIFTDR. Else, + go to DRPAUSE before going to SHIFTDR */ + if (g_usFlowControl & CASCADE) { + if (g_cCurrentJTAGState == DRPAUSE) { + ispVMStateMachine(SHIFTDR); + /* 1/15/04 If cascade flag has been set and the current state is + DRPAUSE, this implies that the first cascaded frame is about to + be shifted in. The header must be shifted prior to shifting + the first cascaded frame. */ + if (g_usHeadDR > 0) { + ispVMBypass(HDR, g_usHeadDR); + sclock(); + } + } else { + ispVMStateMachine(SHIFTDR); + } + } else { + ispVMStateMachine(DRPAUSE); + ispVMStateMachine(SHIFTDR); + if (g_usHeadDR > 0) { + ispVMBypass(HDR, g_usHeadDR); + sclock(); + } + } + } + break; + default: + return (VME_INVALID_FILE); + } + + cRetCode = ispVMDataCode(); + if (cRetCode != 0) { + return (VME_INVALID_FILE); + } + +#ifdef VME_DEBUG + if (g_usDataType & TDI_DATA) { + printf("\n\t\tTDI "); + PrintData(g_usiDataSize, g_pucInData); + } + + if (g_usDataType & TDO_DATA) { + printf("\n\t\tTDO "); + PrintData(g_usiDataSize, g_pucOutData); + } + + if (g_usDataType & MASK_DATA) { + printf("\n\t\tMASK "); + PrintData(g_usiDataSize, g_pucOutMaskData); + } + + if (g_usDataType & DMASK_DATA) { + printf("\n\t\tDMASK "); + PrintData(g_usiDataSize, g_pucOutDMaskData); + } + + printf(";\n"); +#endif /* VME_DEBUG */ + if (g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA) { + if (g_usDataType & DMASK_DATA) { + + cRetCode = ispVMReadandSave(g_usiDataSize); + + if (!cRetCode) { + if (g_usTailDR > 0) { + sclock(); + ispVMBypass(TDR, g_usTailDR); + } + ispVMStateMachine(DRPAUSE); + ispVMStateMachine(SHIFTDR); + if (g_usHeadDR > 0) { + ispVMBypass(HDR, g_usHeadDR); + sclock(); + } + for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1; iDataIndex++) + g_pucInData[iDataIndex] = g_pucOutData[iDataIndex]; + g_usDataType &= ~(TDO_DATA + DMASK_DATA); + cRetCode = ispVMSend(g_usiDataSize); + } + } else { + + cRetCode = ispVMRead(g_usiDataSize); + if (cRetCode == -1 && g_cVendor == XILINX) { + for (iReadLoop = 0; iReadLoop < 30; iReadLoop++) { + cRetCode = ispVMRead(g_usiDataSize); + if (!cRetCode) { + break; + } else { + ispVMStateMachine(DRPAUSE); /*Always DRPAUSE*/ + /*Bypass other devices when appropriate*/ + ispVMBypass(TDR, g_usTailDR); + ispVMStateMachine(g_ucEndDR); + ispVMStateMachine(IDLE); + ispVMDelay(1000); + } + } + } + } + } else { /* TDI only */ + cRetCode = ispVMSend(g_usiDataSize); + + } + + /* transfer the input data to the output buffer for the next verify */ + if ((g_usDataType & EXPRESS) || (a_cCode == SDR)) { + if (g_pucOutData) { + for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1; iDataIndex++) + g_pucOutData[iDataIndex] = g_pucInData[iDataIndex]; + } + } + + switch (a_cCode) { + case SIR: + /* 1/15/04 If not performing cascading, then shift ENDIR */ + if (!(g_usFlowControl & CASCADE)) { + if (g_usTailIR > 0) { + sclock(); + ispVMBypass(TIR, g_usTailIR); + } + ispVMStateMachine(g_ucEndIR); + } + break; + case XSDR: + case SDR: + /* 1/15/04 If not performing cascading, then shift ENDDR */ + if (!(g_usFlowControl & CASCADE)) { + if (g_usTailDR > 0) { + sclock(); + ispVMBypass(TDR, g_usTailDR); + } + ispVMStateMachine(g_ucEndDR); + } + break; + default: + break; + } + + return (cRetCode); +} + +/*************************************************************** +* +* ispVMAmble +* +* This routine is to extract Header and Trailer parameter for SIR and +* SDR operations. +* +* The Header and Trailer parameter are the pre-amble and post-amble bit +* stream need to be shifted into TDI or out of TDO of the devices. Mostly +* is for the purpose of bypassing the leading or trailing devices. ispVM +* supports only shifting data into TDI to bypass the devices. +* +* For a single device, the header and trailer parameters are all set to 0 +* as default by ispVM. If it is for multiple devices, the header and trailer +* value will change as specified by the VME file. +* +***************************************************************/ + +signed char ispVMAmble(signed char Code) +{ + signed char compress = 0; + /* 09/11/07 NN Type cast mismatch variables */ + g_usiDataSize = (unsigned short)ispVMDataSize(); + +#ifdef VME_DEBUG + printf("%d", g_usiDataSize); +#endif /* VME_DEBUG */ + + if (g_usiDataSize) { + + /**************************************************************************** + * + * Discard the TDI byte and set the compression bit in the data type register + * to false if compression is set because TDI data after HIR/HDR/TIR/TDR is not + * compressed. + * + *****************************************************************************/ + + GetByte(); + if (g_usDataType & COMPRESS) { + g_usDataType &= ~(COMPRESS); + compress = 1; + } + } + + switch (Code) { + case HIR: + + /**************************************************************************** + * + * Store the maximum size of the HIR buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usHIRSize) { + g_usHIRSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Assign the HIR value and allocate memory. + * + *****************************************************************************/ + + g_usHeadIR = g_usiDataSize; + if (g_usHeadIR) { + ispVMMemManager(HIR, g_usHeadIR); + ispVMData(g_pucHIRData); + +#ifdef VME_DEBUG + printf(" TDI "); + PrintData(g_usHeadIR, g_pucHIRData); +#endif /* VME_DEBUG */ + } + break; + case TIR: + + /**************************************************************************** + * + * Store the maximum size of the TIR buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usTIRSize) { + g_usTIRSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Assign the TIR value and allocate memory. + * + *****************************************************************************/ + + g_usTailIR = g_usiDataSize; + if (g_usTailIR) { + ispVMMemManager(TIR, g_usTailIR); + ispVMData(g_pucTIRData); + +#ifdef VME_DEBUG + printf(" TDI "); + PrintData(g_usTailIR, g_pucTIRData); +#endif /* VME_DEBUG */ + } + break; + case HDR: + + /**************************************************************************** + * + * Store the maximum size of the HDR buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usHDRSize) { + g_usHDRSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Assign the HDR value and allocate memory. + * + *****************************************************************************/ + + g_usHeadDR = g_usiDataSize; + if (g_usHeadDR) { + ispVMMemManager(HDR, g_usHeadDR); + ispVMData(g_pucHDRData); + +#ifdef VME_DEBUG + printf(" TDI "); + PrintData(g_usHeadDR, g_pucHDRData); +#endif /* VME_DEBUG */ + } + break; + case TDR: + + /**************************************************************************** + * + * Store the maximum size of the TDR buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usiDataSize > g_usTDRSize) { + g_usTDRSize = g_usiDataSize; + } + + /**************************************************************************** + * + * Assign the TDR value and allocate memory. + * + *****************************************************************************/ + + g_usTailDR = g_usiDataSize; + if (g_usTailDR) { + ispVMMemManager(TDR, g_usTailDR); + ispVMData(g_pucTDRData); + +#ifdef VME_DEBUG + printf(" TDI "); + PrintData(g_usTailDR, g_pucTDRData); +#endif /* VME_DEBUG */ + } + break; + default: + break; + } + + /**************************************************************************** + * + * Re-enable compression if it was previously set. + * + *****************************************************************************/ + + if (compress) { + g_usDataType |= COMPRESS; + } + + if (g_usiDataSize) { + Code = GetByte(); + if (Code == CONTINUE) { + return 0; + } else { + + /**************************************************************************** + * + * Encountered invalid opcode. + * + *****************************************************************************/ + + return VME_INVALID_FILE; + } + } + + return 0; +} + +/*************************************************************** +* +* ispVMLoop +* +* Perform the function call upon by the REPEAT opcode. +* Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP. +* After the loop is stored then execution begin. The REPEATLOOP flag is set +* on the g_usFlowControl register to indicate the repeat loop is in session +* and therefore fetch opcode from the memory instead of from the file. +* +***************************************************************/ + +signed char ispVMLoop(unsigned short a_usLoopCount) +{ + /* 09/11/07 NN added local variables initialization */ + signed char cRetCode = 0; + unsigned short iHeapIndex = 0; + unsigned short iLoopIndex = 0; + + g_usShiftValue = 0; + for (iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++) { + g_pucHeapMemory[iHeapIndex] = GetByte(); + } + + if (g_pucHeapMemory[iHeapIndex - 1] != ENDLOOP) { + return (VME_INVALID_FILE); + } + + g_usFlowControl |= REPEATLOOP; + g_usDataType |= HEAP_IN; + + for (iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++) { + g_iHeapCounter = 0; + cRetCode = ispVMCode(); + g_usRepeatLoops++; + if (cRetCode < 0) { + break; + } + } + + g_usDataType &= ~(HEAP_IN); + g_usFlowControl &= ~(REPEATLOOP); + return (cRetCode); +} + +/*************************************************************** +* +* ispVMBitShift +* +* Shift the TDI stream left or right by the number of bits. The data in +* *g_pucInData is of the VME format, so the actual shifting is the reverse of +* IEEE 1532 or SVF format. +* +***************************************************************/ + +signed char ispVMBitShift(signed char mode, unsigned short bits) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short i = 0; + unsigned short size = 0; + unsigned short tmpbits = 0; + + if (g_usiDataSize % 8 > 0) { + /* 09/11/07 NN Type cast mismatch variables */ + size = (unsigned short)(g_usiDataSize / 8 + 1); + } else { + /* 09/11/07 NN Type cast mismatch variables */ + size = (unsigned short)(g_usiDataSize / 8); + } + + switch (mode) { + case SHR: + for (i = 0; i < size; i++) { + if (g_pucInData[i] != 0) { + tmpbits = bits; + while (tmpbits > 0) { + g_pucInData[i] <<= 1; + if (g_pucInData[i] == 0) { + i--; + g_pucInData[i] = 1; + } + tmpbits--; + } + } + } + break; + case SHL: + for (i = 0; i < size; i++) { + if (g_pucInData[i] != 0) { + tmpbits = bits; + while (tmpbits > 0) { + g_pucInData[i] >>= 1; + if (g_pucInData[i] == 0) { + i--; + g_pucInData[i] = 8; + } + tmpbits--; + } + } + } + break; + default: + return (VME_INVALID_FILE); + } + + return (0); +} + +/*************************************************************** +* +* ispVMComment +* +* Displays the SVF comments. +* +***************************************************************/ + +void ispVMComment(unsigned short a_usCommentSize) +{ + char cCurByte = 0; + int count = 0; + for (; a_usCommentSize > 0; a_usCommentSize--) { + /**************************************************************************** + * + * Print character to the terminal. + * + *****************************************************************************/ + cCurByte = GetByte(); + vme_out_char(cCurByte); + count ++ ; + } + cCurByte = '\n'; + vme_out_char(cCurByte); +} + +/*************************************************************** +* +* ispVMHeader +* +* Iterate the length of the header and discard it. +* +***************************************************************/ + +void ispVMHeader(unsigned short a_usHeaderSize) +{ + for (; a_usHeaderSize > 0; a_usHeaderSize--) { + GetByte(); + } +} + +/*************************************************************** +* +* ispVMCalculateCRC32 +* +* Calculate the 32-bit CRC. +* +***************************************************************/ + +void ispVMCalculateCRC32(unsigned char a_ucData) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned char ucIndex = 0; + unsigned char ucFlipData = 0; + unsigned short usCRCTableEntry = 0; + unsigned int crc_table[16] = { + 0x0000, 0xCC01, 0xD801, + 0x1400, 0xF001, 0x3C00, + 0x2800, 0xE401, 0xA001, + 0x6C00, 0x7800, 0xB401, + 0x5000, 0x9C01, 0x8801, + 0x4400 + }; + + for (ucIndex = 0; ucIndex < 8; ucIndex++) { + ucFlipData <<= 1; + if (a_ucData & 0x01) { + ucFlipData |= 0x01; + } + a_ucData >>= 1; + } + + /* 09/11/07 NN Type cast mismatch variables */ + usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]); + g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF); + g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ usCRCTableEntry ^ crc_table[ucFlipData & 0xF]); + usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]); + g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF); + g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ usCRCTableEntry ^ crc_table[(ucFlipData >> 4) & 0xF]); +} + +/*************************************************************** +* +* ispVMLCOUNT +* +* Process the intelligent programming loops. +* +***************************************************************/ + +signed char ispVMLCOUNT(unsigned short a_usCountSize) +{ + unsigned short usContinue = 1; + unsigned short usIntelBufferIndex = 0; + unsigned short usCountIndex = 0; + signed char cRetCode = 0; + signed char cRepeatHeap = 0; + signed char cOpcode = 0; + unsigned char ucState = 0; + unsigned short usDelay = 0; + unsigned short usToggle = 0; + unsigned char usByte = 0; + + g_usIntelBufferSize = (unsigned short)ispVMDataSize(); + + /**************************************************************************** + * + * Allocate memory for intel buffer. + * + *****************************************************************************/ + + ispVMMemManager(LHEAP, g_usIntelBufferSize); + + /**************************************************************************** + * + * Store the maximum size of the intelligent buffer. Used to convert VME to HEX. + * + *****************************************************************************/ + + if (g_usIntelBufferSize > g_usLCOUNTSize) { + g_usLCOUNTSize = g_usIntelBufferSize; + } + + /**************************************************************************** + * + * Copy intel data to the buffer. + * + *****************************************************************************/ + + for (usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize; usIntelBufferIndex++) { + g_pucIntelBuffer[usIntelBufferIndex] = GetByte(); + } + + /**************************************************************************** + * + * Set the data type register to get data from the intelligent data buffer. + * + *****************************************************************************/ + + g_usDataType |= LHEAP_IN; + + /**************************************************************************** + * + * If the HEAP_IN flag is set, temporarily unset the flag so data will be + * retrieved from the status buffer. + * + *****************************************************************************/ + + if (g_usDataType & HEAP_IN) { + g_usDataType &= ~HEAP_IN; + cRepeatHeap = 1; + } + +#ifdef VME_DEBUG + printf("LCOUNT %d;\n", a_usCountSize); +#endif /* VME_DEBUG */ + + /**************************************************************************** + * + * Iterate through the intelligent programming command. + * + *****************************************************************************/ + + for (usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++) { + + /**************************************************************************** + * + * Initialize the intel data index to 0 before each iteration. + * + *****************************************************************************/ + + g_usIntelDataIndex = 0; + cOpcode = 0; + ucState = 0; + usDelay = 0; + usToggle = 0; + usByte = 0; + usContinue = 1; + + /*************************************************************** + * + * Begin looping through all the VME opcodes. + * + ***************************************************************/ + /*************************************************************** + * 4/1/09 Nguyen replaced the recursive function call codes on + * the ispVMLCOUNT function + * + ***************************************************************/ + while (usContinue) { + cOpcode = GetByte(); + switch (cOpcode) { + case HIR: + case TIR: + case HDR: + case TDR: + /*************************************************************** + * + * Set the header/trailer of the device in order to bypass + * successfully. + * + ***************************************************************/ + + ispVMAmble(cOpcode); + break; + case STATE: + + /*************************************************************** + * + * Step the JTAG state machine. + * + ***************************************************************/ + + ucState = GetByte(); + /*************************************************************** + * + * Step the JTAG state machine to DRCAPTURE to support Looping. + * + ***************************************************************/ + + if ((g_usDataType & LHEAP_IN) && + (ucState == DRPAUSE) && + (g_cCurrentJTAGState == ucState)) { + ispVMStateMachine(DRCAPTURE); + } + ispVMStateMachine(ucState); +#ifdef VME_DEBUG + printf("LDELAY %s ", GetState(ucState)); +#endif /* VME_DEBUG */ + break; + case SIR: +#ifdef VME_DEBUG + printf("SIR "); +#endif /* VME_DEBUG */ + /*************************************************************** + * + * Shift in data into the device. + * + ***************************************************************/ + + cRetCode = ispVMShift(cOpcode); + break; + case SDR: + +#ifdef VME_DEBUG + printf("LSDR "); +#endif /* VME_DEBUG */ + /*************************************************************** + * + * Shift in data into the device. + * + ***************************************************************/ + + cRetCode = ispVMShift(cOpcode); + break; + case WAIT: + + /*************************************************************** + * + * Observe delay. + * + ***************************************************************/ + + usDelay = (unsigned short)ispVMDataSize(); + ispVMDelay(usDelay); + +#ifdef VME_DEBUG + if (usDelay & 0x8000) { + + /*************************************************************** + * + * Since MSB is set, the delay time must be decoded to + * millisecond. The SVF2VME encodes the MSB to represent + * millisecond. + * + ***************************************************************/ + + usDelay &= ~0x8000; + printf("%.2E SEC;\n", (float)usDelay / 1000); + } else { + + /*************************************************************** + * + * Since MSB is not set, the delay time is given as microseconds. + * + ***************************************************************/ + + printf("%.2E SEC;\n", (float)usDelay / 1000000); + } +#endif /* VME_DEBUG */ + break; + case TCK: + + /*************************************************************** + * + * Issue clock toggles. + * + ***************************************************************/ + + usToggle = (unsigned short)ispVMDataSize(); + ispVMClocks(usToggle); + +#ifdef VME_DEBUG + printf("RUNTEST %d TCK;\n", usToggle); +#endif /* VME_DEBUG */ + break; + case ENDLOOP: + + /*************************************************************** + * + * Exit point from processing loops. + * + ***************************************************************/ + usContinue = 0; + break; + + case COMMENT: + + /*************************************************************** + * + * Display comment. + * + ***************************************************************/ + + ispVMComment((unsigned short)ispVMDataSize()); + break; + case ispEN: + ucState = GetByte(); + if ((ucState == ON) || (ucState == 0x01)) + writePort(JTAG_ENABLE, 0x01); + else + writePort(JTAG_ENABLE, 0x00); + ispVMDelay(1); + break; + case TRST: + if (GetByte() == 0x01) + writePort(JTAG_TRST, 0x01); + else + writePort(JTAG_TRST, 0x00); + ispVMDelay(1); + break; + default: + + /*************************************************************** + * + * Invalid opcode encountered. + * + ***************************************************************/ + +#ifdef VME_DEBUG + printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode); +#endif /* VME_DEBUG */ + + return VME_INVALID_FILE; + } + } + if (cRetCode >= 0) { + /**************************************************************************** + * + * Break if intelligent programming is successful. + * + *****************************************************************************/ + + break; + } + + } + /**************************************************************************** + * + * If HEAP_IN flag was temporarily disabled, re-enable it before exiting. + * + *****************************************************************************/ + + if (cRepeatHeap) { + g_usDataType |= HEAP_IN; + } + + /**************************************************************************** + * + * Set the data type register to not get data from the intelligent data buffer. + * + *****************************************************************************/ + + g_usDataType &= ~LHEAP_IN; + return cRetCode; +} + +/*************************************************************** +* +* ispVMClocks +* +* Applies the specified number of pulses to TCK. +* +***************************************************************/ + +void ispVMClocks(unsigned short Clocks) +{ + unsigned short iClockIndex = 0; + for (iClockIndex = 0; iClockIndex < Clocks; iClockIndex++) { + sclock(); + } +} + +/*************************************************************** +* +* ispVMBypass +* +* This procedure takes care of the HIR, HDR, TIR, TDR for the +* purpose of putting the other devices into Bypass mode. The +* current state is checked to find out if it is at DRPAUSE or +* IRPAUSE. If it is at DRPAUSE, perform bypass register scan. +* If it is at IRPAUSE, scan into instruction registers the bypass +* instruction. +* +***************************************************************/ + +void ispVMBypass(signed char ScanType, unsigned short Bits) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short iIndex = 0; + unsigned short iSourceIndex = 0; + unsigned char cBitState = 0; + unsigned char cCurByte = 0; + unsigned char *pcSource = NULL; + + if (Bits <= 0) { + return; + } + + switch (ScanType) { + case HIR: + pcSource = g_pucHIRData; + break; + case TIR: + pcSource = g_pucTIRData; + break; + case HDR: + pcSource = g_pucHDRData; + break; + case TDR: + pcSource = g_pucTDRData; + break; + default: + break; + } + if (pcSource) { + iSourceIndex = 0; + cBitState = 0; + for (iIndex = 0; iIndex < Bits - 1; iIndex++) { + /* Scan instruction or bypass register */ + if (iIndex % 8 == 0) { + cCurByte = pcSource[iSourceIndex++]; + } + cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80) ? 0x01 : 0x00); + writePort(JTAG_TDI, cBitState); + sclock(); + } + + if (iIndex % 8 == 0) { + cCurByte = pcSource[iSourceIndex++]; + } + + cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80) ? 0x01 : 0x00); + writePort(JTAG_TDI, cBitState); + } +} + +/*************************************************************** +* +* ispVMStateMachine +* +* This procedure steps all devices in the daisy chain from a given +* JTAG state to the next desirable state. If the next state is TLR, +* the JTAG state machine is brute forced into TLR by driving TMS +* high and pulse TCK 6 times. +* +***************************************************************/ + +void ispVMStateMachine(signed char cNextJTAGState) +{ + /* 09/11/07 NN added local variables initialization */ + signed char cPathIndex = 0; + signed char cStateIndex = 0; + short int found = 0; + + if ((g_cCurrentJTAGState == cNextJTAGState) && (cNextJTAGState != RESET)) { + return; + } + + for (cStateIndex = 0; cStateIndex < 25; cStateIndex++) { + if ((g_cCurrentJTAGState == g_JTAGTransistions[cStateIndex].CurState) && (cNextJTAGState == g_JTAGTransistions[cStateIndex].NextState)) { + found = 1; + break; + } + } + if (found) { + g_cCurrentJTAGState = cNextJTAGState; + for (cPathIndex = 0; cPathIndex < g_JTAGTransistions[cStateIndex].Pulses; cPathIndex++) { + if ((g_JTAGTransistions[cStateIndex].Pattern << cPathIndex) & 0x80) { + writePort(JTAG_TMS, (unsigned char)0x01); + } else { + writePort(JTAG_TMS, (unsigned char)0x00); + } + sclock(); + } + + writePort(JTAG_TDI, 0x00); + writePort(JTAG_TMS, 0x00); + } +} + +/*************************************************************** +* +* ispVMStart +* +* Enable the port to the device and set the state to RESET (TLR). +* +***************************************************************/ + +void ispVMStart() +{ +#ifdef VME_DEBUG + printf("// ISPVM EMBEDDED ADDED\n"); + printf("STATE RESET;\n"); +#endif + + ispVMStateMachine(RESET); /* step devices to RESET state */ + +} + +/*************************************************************** +* +* ispVMEnd +* +* Set the state of devices to RESET to enable the devices and disable +* the port. +* +***************************************************************/ + +void ispVMEnd() +{ +#ifdef VME_DEBUG + printf("// ISPVM EMBEDDED ADDED\n"); + printf("STATE RESET;\n"); + printf("RUNTEST 1.00E-001 SEC;\n"); +#endif + + ispVMStateMachine(RESET); /* step devices to RESET state */ + ispVMDelay(1000); /* wake up devices */ +} + +/*************************************************************** +* +* ispVMSend +* +* Send the TDI data stream to devices. The data stream can be +* instructions or data. +* +***************************************************************/ + +signed char ispVMSend(unsigned short a_usiDataSize) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short iIndex = 0; + unsigned short iInDataIndex = 0; + unsigned char cCurByte = 0; + unsigned char cBitState = 0; + + for (iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++) { + if (iIndex % 8 == 0) { + cCurByte = g_pucInData[iInDataIndex++]; + } + cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80) ? 0x01 : 0x00); + writePort(JTAG_TDI, cBitState); + sclock(); + } + + if (iIndex % 8 == 0) { + /* Take care of the last bit */ + cCurByte = g_pucInData[iInDataIndex]; + } + + cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80) ? 0x01 : 0x00); + + writePort(JTAG_TDI, cBitState); + if (g_usFlowControl & CASCADE) { + /* 1/15/04 Clock in last bit for the first n-1 cascaded frames */ + sclock(); + } + + return 0; +} + +/*************************************************************** +* +* ispVMRead +* +* Read the data stream from devices and verify. +* +***************************************************************/ + +signed char ispVMRead(unsigned short a_usiDataSize) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short usDataSizeIndex = 0; + unsigned short usErrorCount = 0; + unsigned short usLastBitIndex = 0; + unsigned char cDataByte = 0; + unsigned char cMaskByte = 0; + unsigned char cInDataByte = 0; + unsigned char cCurBit = 0; + unsigned char cByteIndex = 0; + unsigned short usBufferIndex = 0; + unsigned char ucDisplayByte = 0x00; + unsigned char ucDisplayFlag = 0x01; + char StrChecksum[256] = { 0 }; + unsigned char g_usCalculateChecksum = 0x00; + + /* 09/11/07 NN Type cast mismatch variables */ + usLastBitIndex = (unsigned short)(a_usiDataSize - 1); + + + /**************************************************************************** + * + * If mask is not all zeros, then set the display flag to 0x00, otherwise + * it shall be set to 0x01 to indicate that data read from the device shall + * be displayed. If VME_DEBUG is defined, always display data. + * + *****************************************************************************/ + + + for (usDataSizeIndex = 0; usDataSizeIndex < (a_usiDataSize + 7) / 8; usDataSizeIndex++) { + + if (g_usDataType & MASK_DATA) { + if (g_pucOutMaskData[usDataSizeIndex] != 0x00) { + ucDisplayFlag = 0x00; + break; + } + } else if (g_usDataType & CMASK_DATA) { + g_usCalculateChecksum = 0x01; + ucDisplayFlag = 0x00; + break; + } else { + ucDisplayFlag = 0x00; + break; + } + } + + /**************************************************************************** + * + * Begin shifting data in and out of the device. + * + *****************************************************************************/ + for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; usDataSizeIndex++) { + if (cByteIndex == 0) { + + /*************************************************************** + * + * Grab byte from TDO buffer. + * + ***************************************************************/ + + if (g_usDataType & TDO_DATA) { + cDataByte = g_pucOutData[usBufferIndex]; + } + + /*************************************************************** + * + * Grab byte from MASK buffer. + * + ***************************************************************/ + + if (g_usDataType & MASK_DATA) { + cMaskByte = g_pucOutMaskData[usBufferIndex]; + } else { + cMaskByte = 0xFF; + } + + /*************************************************************** + * + * Grab byte from CMASK buffer. + * + ***************************************************************/ + + if (g_usDataType & CMASK_DATA) { + cMaskByte = 0x00; + g_usCalculateChecksum = 0x01; + } + + /*************************************************************** + * + * Grab byte from TDI buffer. + * + ***************************************************************/ + + if (g_usDataType & TDI_DATA) { + cInDataByte = g_pucInData[usBufferIndex]; + } + + usBufferIndex++; + } + + cCurBit = readPort(); + + if (ucDisplayFlag) { + ucDisplayByte <<= 1; + ucDisplayByte |= cCurBit; + } + + /**************************************************************************** + * + * Check if data read from port matches with expected TDO. + * + *****************************************************************************/ + + + if (g_usDataType & TDO_DATA) { + /* 08/28/08 NN Added Calculate checksum support. */ + if (g_usCalculateChecksum) { + if (cCurBit == 0x01) + g_usChecksum += (1 << (g_uiChecksumIndex % 8)); + g_uiChecksumIndex++; + } else { + if ((((cMaskByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) { + if (cCurBit != (unsigned char)(((cDataByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) { + usErrorCount++; + } + } + } + } + + /**************************************************************************** + * + * Write TDI data to the port. + * + *****************************************************************************/ + + writePort(JTAG_TDI, (unsigned char)(((cInDataByte << cByteIndex) & 0x80) ? 0x01 : 0x00)); + + if (usDataSizeIndex < usLastBitIndex) { + + /**************************************************************************** + * + * Clock data out from the data shift register. + * + *****************************************************************************/ + + sclock(); + } else if (g_usFlowControl & CASCADE) { + + /**************************************************************************** + * + * Clock in last bit for the first N - 1 cascaded frames. + * + *****************************************************************************/ + + sclock(); + } + + /*************************************************************** + * + * Increment the byte index. If it exceeds 7, then reset it back + * to zero. + * + ***************************************************************/ + + cByteIndex++; + if (cByteIndex >= 8) { + if (ucDisplayFlag) { + + /*************************************************************** + * + * Store displayed data in the TDO buffer. By reusing the TDO + * buffer to store displayed data, there is no need to allocate + * a buffer simply to hold display data. This will not cause any + * false verification errors because the true TDO byte has already + * been consumed. + * + ***************************************************************/ + + g_pucOutData[usBufferIndex - 1] = ucDisplayByte; + ucDisplayByte = 0; + } + + cByteIndex = 0; + } + /* 09/12/07 Nguyen changed to display the 1 bit expected data */ + else if (a_usiDataSize == 1) { + if (ucDisplayFlag) { + + /*************************************************************** + * + * Store displayed data in the TDO buffer. By reusing the TDO + * buffer to store displayed data, there is no need to allocate + * a buffer simply to hold display data. This will not cause any + * false verification errors because the true TDO byte has already + * been consumed. + * + ***************************************************************/ + + /**************************************************************************** + * + * Flip ucDisplayByte and store it in cDataByte. + * + *****************************************************************************/ + cDataByte = 0x00; + for (usBufferIndex = 0; usBufferIndex < 8; usBufferIndex++) { + cDataByte <<= 1; + if (ucDisplayByte & 0x01) { + cDataByte |= 0x01; + } + ucDisplayByte >>= 1; + } + g_pucOutData[0] = cDataByte; + ucDisplayByte = 0; + } + + cByteIndex = 0; + } + } + if (ucDisplayFlag) { + + /**************************************************************************** + * + * Display data read from the device. + * + *****************************************************************************/ + +#ifdef VME_DEBUG + printf("RECIEVED TDO ("); +#else + vme_out_string("Display Data: 0x"); +#endif /* VME_DEBUG */ + + /* 09/11/07 NN Type cast mismatch variables */ + for (usDataSizeIndex = (unsigned short)((a_usiDataSize + 7) / 8); usDataSizeIndex > 0; usDataSizeIndex--) { + cMaskByte = g_pucOutData[usDataSizeIndex - 1]; + cDataByte = 0x00; + + /**************************************************************************** + * + * Flip cMaskByte and store it in cDataByte. + * + *****************************************************************************/ + + for (usBufferIndex = 0; usBufferIndex < 8; usBufferIndex++) { + cDataByte <<= 1; + if (cMaskByte & 0x01) { + cDataByte |= 0x01; + } + cMaskByte >>= 1; + } +#ifdef VME_DEBUG + printf("%.2X", cDataByte); + if ((((a_usiDataSize + 7) / 8) - usDataSizeIndex) % 40 == 39) { + printf("\n\t\t"); + } +#else + vme_out_hex(cDataByte); +#endif /* VME_DEBUG */ + } + +#ifdef VME_DEBUG + printf(")\n\n"); +#else + vme_out_string("\n\n"); +#endif /* VME_DEBUG */ + /* 09/02/08 Nguyen changed to display the data Checksum */ + vme_out_string("g_usChecksum:"); + sprintf(StrChecksum, "%.4X\n\n", (unsigned int)g_usChecksum); + vme_out_string(StrChecksum); + vme_out_string("\n\n"); + if (g_usChecksum != 0) { + g_usChecksum &= 0xFFFF; + sprintf(StrChecksum, "Data Checksum: %.4X\n\n", (unsigned int)g_usChecksum); + vme_out_string(StrChecksum); + g_usChecksum = 0; + } + } + + if (usErrorCount > 0) { + + if (g_usFlowControl & VERIFYUES) { + vme_out_string("USERCODE verification failed. Continue programming......\n\n"); + g_usFlowControl &= ~(VERIFYUES); + return 0; + } else { + +#ifdef VME_DEBUG + printf("TOTAL ERRORS: %d\n", usErrorCount); +#endif /* VME_DEBUG */ + + return VME_VERIFICATION_FAILURE; + } + } else { + if (g_usFlowControl & VERIFYUES) { + vme_out_string("USERCODE verification passed. Programming aborted. \n\n"); + g_usFlowControl &= ~(VERIFYUES); + return 1; + } else { + return 0; + } + } +} + +/*************************************************************** +* +* ispVMReadandSave +* +* Support dynamic I/O. +* +***************************************************************/ + +signed char ispVMReadandSave(unsigned short int a_usiDataSize) +{ + /* 09/11/07 NN added local variables initialization */ + unsigned short int usDataSizeIndex = 0; + unsigned short int usLastBitIndex = 0; + unsigned short int usBufferIndex = 0; + unsigned short int usOutBitIndex = 0; + unsigned short int usLVDSIndex = 0; + unsigned char cDataByte = 0; + unsigned char cDMASKByte = 0; + unsigned char cInDataByte = 0; + unsigned char cCurBit = 0; + unsigned char cByteIndex = 0; + signed char cLVDSByteIndex = 0; + + /* 09/11/07 NN Type cast mismatch variables */ + usLastBitIndex = (unsigned short)(a_usiDataSize - 1); + + /*************************************************************** + * + * Iterate through the data bits. + * + ***************************************************************/ + + for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; usDataSizeIndex++) { + if (cByteIndex == 0) { + + /*************************************************************** + * + * Grab byte from DMASK buffer. + * + ***************************************************************/ + + if (g_usDataType & DMASK_DATA) { + cDMASKByte = g_pucOutDMaskData[usBufferIndex]; + } else { + cDMASKByte = 0x00; + } + + /*************************************************************** + * + * Grab byte from TDI buffer. + * + ***************************************************************/ + + if (g_usDataType & TDI_DATA) { + cInDataByte = g_pucInData[usBufferIndex]; + } + + usBufferIndex++; + } + + cCurBit = readPort(); + cDataByte = (unsigned char)(((cInDataByte << cByteIndex) & 0x80) ? 0x01 : 0x00); + + /*************************************************************** + * + * Initialize the byte to be zero. + * + ***************************************************************/ + + if (usOutBitIndex % 8 == 0) { + g_pucOutData[usOutBitIndex / 8] = 0x00; + } + + /*************************************************************** + * + * Use TDI, DMASK, and device TDO to create new TDI (actually + * stored in g_pucOutData). + * + ***************************************************************/ + + if ((((cDMASKByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) { + + if (g_pLVDSList) { + for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) { + if (g_pLVDSList[usLVDSIndex].usNegativeIndex == usDataSizeIndex) { + g_pLVDSList[usLVDSIndex].ucUpdate = 0x01; + break; + } + } + } + + /*************************************************************** + * + * DMASK bit is 1, use TDI. + * + ***************************************************************/ + + g_pucOutData[usOutBitIndex / 8] |= (unsigned char)(((cDataByte & 0x1) ? 0x01 : 0x00) << (7 - usOutBitIndex % 8)); + } else { + + /*************************************************************** + * + * DMASK bit is 0, use device TDO. + * + ***************************************************************/ + + g_pucOutData[usOutBitIndex / 8] |= (unsigned char)(((cCurBit & 0x1) ? 0x01 : 0x00) << (7 - usOutBitIndex % 8)); + } + + /*************************************************************** + * + * Shift in TDI in order to get TDO out. + * + ***************************************************************/ + + usOutBitIndex++; + writePort(JTAG_TDI, cDataByte); + if (usDataSizeIndex < usLastBitIndex) { + sclock(); + } + + /*************************************************************** + * + * Increment the byte index. If it exceeds 7, then reset it back + * to zero. + * + ***************************************************************/ + + cByteIndex++; + if (cByteIndex >= 8) { + cByteIndex = 0; + } + } + + /*************************************************************** + * + * If g_pLVDSList exists and pairs need updating, then update + * the negative-pair to receive the flipped positive-pair value. + * + ***************************************************************/ + + if (g_pLVDSList) { + for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) { + if (g_pLVDSList[usLVDSIndex].ucUpdate) { + + /*************************************************************** + * + * Read the positive value and flip it. + * + ***************************************************************/ + + cDataByte = (unsigned char)(((g_pucOutData[g_pLVDSList[usLVDSIndex].usPositiveIndex / 8] << (g_pLVDSList[usLVDSIndex].usPositiveIndex % 8)) & 0x80) ? 0x01 : 0x00); + //09/11/07 NN Type cast mismatch variables + cDataByte = (unsigned char)(!cDataByte); + + /*************************************************************** + * + * Get the byte that needs modification. + * + ***************************************************************/ + + cInDataByte = g_pucOutData[g_pLVDSList[usLVDSIndex].usNegativeIndex / 8]; + + if (cDataByte) { + + /*************************************************************** + * + * Copy over the current byte and set the negative bit to 1. + * + ***************************************************************/ + + cDataByte = 0x00; + for (cLVDSByteIndex = 7; cLVDSByteIndex >= 0; cLVDSByteIndex--) { + cDataByte <<= 1; + if (7 - (g_pLVDSList[usLVDSIndex].usNegativeIndex % 8) == cLVDSByteIndex) { + + /*************************************************************** + * + * Set negative bit to 1. + * + ***************************************************************/ + + cDataByte |= 0x01; + } else if (cInDataByte & 0x80) { + cDataByte |= 0x01; + } + + cInDataByte <<= 1; + } + + /*************************************************************** + * + * Store the modified byte. + * + ***************************************************************/ + + g_pucOutData[g_pLVDSList[usLVDSIndex].usNegativeIndex / 8] = cDataByte; + } else { + + /*************************************************************** + * + * Copy over the current byte and set the negative bit to 0. + * + ***************************************************************/ + + cDataByte = 0x00; + for (cLVDSByteIndex = 7; cLVDSByteIndex >= 0; cLVDSByteIndex--) { + cDataByte <<= 1; + if (7 - (g_pLVDSList[usLVDSIndex].usNegativeIndex % 8) == cLVDSByteIndex) { + + /*************************************************************** + * + * Set negative bit to 0. + * + ***************************************************************/ + + cDataByte |= 0x00; + } else if (cInDataByte & 0x80) { + cDataByte |= 0x01; + } + + cInDataByte <<= 1; + } + + /*************************************************************** + * + * Store the modified byte. + * + ***************************************************************/ + + g_pucOutData[g_pLVDSList[usLVDSIndex].usNegativeIndex / 8] = cDataByte; + } + + break; + } + } + } + + return (0); +} + +signed char ispVMProcessLVDS(unsigned short a_usLVDSCount) +{ + unsigned short usLVDSIndex = 0; + + /*************************************************************** + * + * Allocate memory to hold LVDS pairs. + * + ***************************************************************/ + + ispVMMemManager(LVDS, a_usLVDSCount); + g_usLVDSPairCount = a_usLVDSCount; + +#ifdef VME_DEBUG + printf("LVDS %d (", a_usLVDSCount); +#endif /* VME_DEBUG */ + + /*************************************************************** + * + * Iterate through each given LVDS pair. + * + ***************************************************************/ + + for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) { + + /*************************************************************** + * + * Assign the positive and negative indices of the LVDS pair. + * + ***************************************************************/ + + /* 09/11/07 NN Type cast mismatch variables */ + g_pLVDSList[usLVDSIndex].usPositiveIndex = (unsigned short)ispVMDataSize(); + /* 09/11/07 NN Type cast mismatch variables */ + g_pLVDSList[usLVDSIndex].usNegativeIndex = (unsigned short)ispVMDataSize(); + +#ifdef VME_DEBUG + if (usLVDSIndex < g_usLVDSPairCount - 1) { + printf("%d:%d, ", g_pLVDSList[usLVDSIndex].usPositiveIndex, g_pLVDSList[usLVDSIndex].usNegativeIndex); + } else { + printf("%d:%d", g_pLVDSList[usLVDSIndex].usPositiveIndex, g_pLVDSList[usLVDSIndex].usNegativeIndex); + } +#endif /* VME_DEBUG */ + + } + +#ifdef VME_DEBUG + printf(") -- %d;\n", a_usLVDSCount); +#endif /* VME_DEBUG */ + + return (0); +} diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/vmopcode.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/vmopcode.h new file mode 100644 index 000000000000..ae9d713ff86c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/firmware_upgrade/firmware_upgrade_ispvme/vmopcode.h @@ -0,0 +1,192 @@ +/*************************************************************** +* +* This is the include file for Lattice Semiconductor's ispVM +* Embedded software application. +* +***************************************************************/ + +/*************************************************************** +* +* VME version. +* +* History: +* +***************************************************************/ + +#define VME_VERSION_NUMBER "12.2" + +/*************************************************************** +* +* Maximum declarations. +* +***************************************************************/ + +#define VMEHEXMAX 60000L /* The hex file is split 60K per file. */ +#define SCANMAX 64000L /* The maximum SDR/SIR burst. */ + +/*************************************************************** +* +* Supported JTAG state transitions. +* +***************************************************************/ + +#define RESET 0x00 +#define IDLE 0x01 +#define IRPAUSE 0x02 +#define DRPAUSE 0x03 +#define SHIFTIR 0x04 +#define SHIFTDR 0x05 +#define DRCAPTURE 0x06 + +/*************************************************************** +* +* Flow control register bit definitions. A set bit indicates +* that the register currently exhibits the corresponding mode. +* +***************************************************************/ + +#define INTEL_PRGM 0x0001 /* Intelligent programming is in effect. */ +#define CASCADE 0x0002 /* Currently splitting large SDR. */ +#define REPEATLOOP 0x0008 /* Currently executing a repeat loop. */ +#define SHIFTRIGHT 0x0080 /* The next data stream needs a right shift. */ +#define SHIFTLEFT 0x0100 /* The next data stream needs a left shift. */ +#define VERIFYUES 0x0200 /* Continue if fail is in effect. */ + +/*************************************************************** +* +* DataType register bit definitions. A set bit indicates +* that the register currently holds the corresponding type of data. +* +***************************************************************/ + +#define EXPRESS 0x0001 /* Simultaneous program and verify. */ +#define SIR_DATA 0x0002 /* SIR is the active SVF command. */ +#define SDR_DATA 0x0004 /* SDR is the active SVF command. */ +#define COMPRESS 0x0008 /* Data is compressed. */ +#define TDI_DATA 0x0010 /* TDI data is present. */ +#define TDO_DATA 0x0020 /* TDO data is present. */ +#define MASK_DATA 0x0040 /* MASK data is present. */ +#define HEAP_IN 0x0080 /* Data is from the heap. */ +#define LHEAP_IN 0x0200 /* Data is from intel data buffer. */ +#define VARIABLE 0x0400 /* Data is from a declared variable. */ +#define CRC_DATA 0x0800 /* CRC data is pressent. */ +#define CMASK_DATA 0x1000 /* CMASK data is pressent. */ +#define RMASK_DATA 0x2000 /* RMASK data is pressent. */ +#define READ_DATA 0x4000 /* READ data is pressent. */ +#define DMASK_DATA 0x8000 /* DMASK data is pressent. */ + +/*************************************************************** +* +* Pin opcodes. +* +***************************************************************/ + +#define signalENABLE 0x1C /* ispENABLE pin. */ +#define signalTMS 0x1D /* TMS pin. */ +#define signalTCK 0x1E /* TCK pin. */ +#define signalTDI 0x1F /* TDI pin. */ +#define signalTRST 0x20 /* TRST pin. */ + +/*************************************************************** +* +* Supported vendors. +* +***************************************************************/ + +#define VENDOR 0x56 +#define LATTICE 0x01 +#define ALTERA 0x02 +#define XILINX 0x03 + +/*************************************************************** +* +* Opcode definitions. +* +* Note: opcodes must be unique. +* +***************************************************************/ + +#define ENDDATA 0x00 /* The end of the current SDR data stream. */ +#define RUNTEST 0x01 /* The duration to stay at the stable state. */ +#define ENDDR 0x02 /* The stable state after SDR. */ +#define ENDIR 0x03 /* The stable state after SIR. */ +#define ENDSTATE 0x04 /* The stable state after RUNTEST. */ +#define TRST 0x05 /* Assert the TRST pin. */ +#define HIR 0x06 /* The sum of the IR bits of the leading devices. */ +#define TIR 0x07 /* The sum of the IR bits of the trailing devices. */ +#define HDR 0x08 /* The number of leading devices. */ +#define TDR 0x09 /* The number of trailing devices. */ +#define ispEN 0x0A /* Assert the ispEN pin. */ +#define FREQUENCY 0x0B /* The maximum clock rate to run the JTAG state machine. */ +#define STATE 0x10 /* Move to the next stable state. */ +#define SIR 0x11 /* The instruction stream follows. */ +#define SDR 0x12 /* The data stream follows. */ +#define TDI 0x13 /* The following data stream feeds into the device. */ +#define TDO 0x14 /* The following data stream is compared against the device. */ +#define MASK 0x15 /* The following data stream is used as mask. */ +#define XSDR 0x16 /* The following data stream is for simultaneous program and verify. */ +#define XTDI 0x17 /* The following data stream is for shift in only. It must be stored for the next XSDR. */ +#define XTDO 0x18 /* There is not data stream. The data stream was stored from the previous XTDI. */ +#define MEM 0x19 /* The maximum memory needed to allocate in order hold one row of data. */ +#define WAIT 0x1A /* The duration of delay to observe. */ +#define TCK 0x1B /* The number of TCK pulses. */ +#define SHR 0x23 /* Set the flow control register for right shift. */ +#define SHL 0x24 /* Set the flow control register for left shift. */ +#define HEAP 0x32 /* The memory size needed to hold one loop. */ +#define REPEAT 0x33 /* The beginning of the loop. */ +#define LEFTPAREN 0x35 /* The beginning of data following the loop. */ +#define VAR 0x55 /* Plac holder for loop data. */ +#define SEC 0x1C /* The delay time in seconds that must be observed. */ +#define SMASK 0x1D /* The mask for TDI data. */ +#define MAX 0x1E /* The absolute maximum wait time. */ +#define ON 0x1F /* Assert the targeted pin. */ +#define OFF 0x20 /* Dis-assert the targeted pin. */ +#define SETFLOW 0x30 /* Change the flow control register. */ +#define RESETFLOW 0x31 /* Clear the flow control register. */ +#define CRC 0x47 /* The following data stream is used for CRC calculation. */ +#define CMASK 0x48 /* The following data stream is used as mask for CRC calculation. */ +#define RMASK 0x49 /* The following data stream is used as mask for read and save. */ +#define READ 0x50 /* The following data stream is used for read and save. */ +#define ENDLOOP 0x59 /* The end of the repeat loop. */ +#define SECUREHEAP 0x60 /* Used to secure the HEAP opcode. */ +#define VUES 0x61 /* Support continue if fail. */ +#define DMASK 0x62 /* The following data stream is used for dynamic I/O. */ +#define COMMENT 0x63 /* Support SVF comments in the VME file. */ +#define HEADER 0x64 /* Support header in VME file. */ +#define FILE_CRC 0x65 /* Support crc-protected VME file. */ +#define LCOUNT 0x66 /* Support intelligent programming. */ +#define LDELAY 0x67 /* Support intelligent programming. */ +#define LSDR 0x68 /* Support intelligent programming. */ +#define LHEAP 0x69 /* Memory needed to hold intelligent data buffer */ +#define CONTINUE 0x70 /* Allow continuation. */ +#define LVDS 0x71 /* Support LVDS. */ +#define ENDVME 0x7F /* End of the VME file. */ +#define HIGH 0x80 /* Assert the targeted pin. */ +#define LOW 0x81 /* Dis-assert the targeted pin. */ +#define ENDFILE 0xFF /* End of file. */ + +/*************************************************************** +* +* ispVM Embedded Return Codes. +* +***************************************************************/ + +#define VME_VERIFICATION_FAILURE -1 +#define VME_FILE_READ_FAILURE -2 +#define VME_VERSION_FAILURE -3 +#define VME_INVALID_FILE -4 +#define VME_ARGUMENT_FAILURE -5 +#define VME_CRC_FAILURE -6 + +/*************************************************************** +* +* Type definitions. +* +***************************************************************/ + +/* Support LVDS */ +typedef struct { + unsigned short usPositiveIndex; + unsigned short usNegativeIndex; + unsigned char ucUpdate; +} LVDSPair; diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/Makefile new file mode 100644 index 000000000000..4f697d4058a1 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/Makefile @@ -0,0 +1,36 @@ +top_srcdir:=$(shell pwd) +#include $(top_srcdir)/Rules.mk +DIR=$(shell pwd) +BUILD_OUTPUT=$(DIR)/tmp +SRCS=$(wildcard *.c) +OBJS=$(patsubst %.c, $(BUILD_OUTPUT)/%.o, $(SRCS)) +DEPS=$(patsubst %.o, %.d, $(OBJS)) +CFLAGS+=-Wall -W -g -I$(DIR)/include +LDFLAGS= +ifdef ENABLE_GCOV +ifeq ($(ENABLE_GCOV), y) +LDFLAGS+= -lgcov +endif +endif # ENABLE_GCOV +PROGRAM=hw_test.bin + +.PHONY: all + +all:$(OBJS) + $(CC) $(OBJS) $(LDFLAGS) -o $(BUILD_OUTPUT)/$(PROGRAM) + cp -p $(BUILD_OUTPUT)/$(PROGRAM) $(common_out_put_dir) + + +$(OBJS):$(SRCS) + @if [ ! -d ${BUILD_OUTPUT} ]; then mkdir -p ${BUILD_OUTPUT} ;fi + $(CC) -c $(CFLAGS) $(INCLUDE) $(*F).c -o $@ + +.PHONY: install +install: + @mkdir -p $(install_sbin_dir) + cp -p $(BUILD_OUTPUT)/$(PROGRAM) $(common_out_put_dir) + + +rebuild: clean all +clean: + @rm -rf $(BUILD_OUTPUT)/* \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/ft_ddr_test.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/ft_ddr_test.c new file mode 100644 index 000000000000..120bb2e2288e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/ft_ddr_test.c @@ -0,0 +1,2111 @@ +/* + * $Id: ft_ddr_test.c,v 1.0.0.0 2009/08/05 17:37:52 xiezb Exp $ + * Copyright (C)2009-2009 Ragile Network. All rights reserved. + */ + +/* + * ft_ddr_test.c + * Original Author: support@ragilenetworks.com, 2009-8-5 + * Memory test algorithm implementation function + * + * History + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef USE_DMA /* disable DMA */ +typedef unsigned int uint32; +#define MEMORY_SIZE_1G (1024 * 1024 * 1024ul) + +volatile uint32 *pp = 0; +uint32 p1 = 0, p2 = 0, p0 = 0; +int fail = 0; +int segs = 0; +struct vars variables = { }; +struct vars *v = &variables; +/* dma_tx_data_t g_dma_tx_data[MAX_DMA_CHAN][NUM_LINK_DESC]; */ +static unsigned int SEED_X = 521288629; +static unsigned int SEED_Y = 362436069; + +/* memory block size during dma transfer */ +int blk_size_array[BLK_SIZE_NUM_MAX] = { + 0x2000000, /* 32MB */ + 0x1800000, /* 24MB */ + 0x1000000, /* 16MB */ + 0xA00000, /* 10MB */ + 0x800000, /* 8MB */ + 0x600000, /* 6MB */ + 0x500000, /* 5MB */ + 0x300000, /* 3MB */ + 0x200000, /* 2MB */ +}; + +#if 0 +extern int dma_mov_addr(int engine, int from_addr, int to_addr, int size); +#endif +static int ddr_half_mov_inv_random_pat(char *desc); +static int ddr_mov_inv_random_pat(char *desc); +static int ddr_mov_inv_0_1(char *desc); +static int ddr_mov_inv_8_pat(char *desc); +static int ddr_mov_inv_32_pat(char *desc); +static int ddr_mod20_random_pat(char *desc); +static int ddr_mod20_0_1_pat(char *desc); +static int ddr_mod20_8_pat(char *desc); +static int ddr_addr_walking(char *desc); +static int ddr_march_c(char *desc); +static int ddr_march_g(char *desc); +static int ddr_galloping(char *desc); +static int ddr_column_operate(char *desc); +static int ddr_swap_blocks(char *desc); + +ft_ddr_test_interface_t ft_ddr_test_fun[TETS_TOTAL_NUMBER] = { + {0, ddr_half_mov_inv_random_pat, "半移动反转-随机数测试"}, /* Half move reversions-Random number test */ + {1, ddr_mov_inv_random_pat, "移动反转-随机数测试"}, /* moving reversions-Random Number Test */ + {0, ddr_mov_inv_0_1, "移动反转-0&1测试"}, /* moving reversions-0 & 1 test */ + {1, ddr_mov_inv_8_pat, "移动反转-8bit测试"}, /* moving reversions-8 bit test */ + {0, ddr_mov_inv_32_pat, "移动反转-32bit测试"}, /* moving reversions-32 bit test */ + {0, ddr_mod20_random_pat, "模20-随机数测试"}, /* modulo 20-random number test */ + {1, ddr_mod20_0_1_pat, "模20-0&1测试"}, /* modulo 20-0&1 test */ + {1, ddr_mod20_8_pat, "模20-8bit测试"}, /* modulo 20-8 bit test */ + {1, ddr_addr_walking, "走1地址测试"}, /* Take 1 address test */ + {0, ddr_march_c, "March C测试"}, /* March C test */ + {1, ddr_march_g, "March G测试"}, /* March G test */ + {1, ddr_galloping, "Galloping测试 "}, /* Galloping test */ + {1, ddr_column_operate, "Column operate测试"}, /* Column operate test */ + {0, ddr_swap_blocks, " block move测试"}, /* block move test */ +}; + +static inline ulong roundup(ulong value, ulong mask) +{ + return (value + mask) & ~mask; +} + +#if 0 +static inline void set_vars(ulong start, ulong end) +{ + int i = 0; + + for (i = 0; i < v->msegs; i++) { + v->pmap[i].start = (uint)start; + v->pmap[i].end = (uint)end; + v->map[i].start = (ulong *)start; + v->map[i].end = (ulong *)end; + } +} +#endif + +#if 1 +void rand_seed(unsigned int seed1, unsigned int seed2) +{ + if (seed1) + SEED_X = seed1; /* use default seeds if parameter is 0 */ + if (seed2) + SEED_Y = seed2; +} + +static inline unsigned int ft_rand() +{ + static unsigned int a = 18000, b = 30903; + + SEED_X = a * (SEED_X & 65535) + (SEED_X >> 16); + SEED_Y = b * (SEED_Y & 65535) + (SEED_Y >> 16); + + return ((SEED_X << 16) + (SEED_Y & 65535)); +} +#else +static inline unsigned long ft_rand() +{ + if (sizeof(ulong) == 8) { + return ((ulong)rand() << 32) | rand(); + } + + return rand(); +} + +#endif +/** + * addrress_walking + * + * use "address test" algorithm + * The address conversion rules for data to be written are as follow: + * address = Initial address | (mask << 1) + * + * return void + */ +static int addrress_walking(char *desc) +{ + int i, j, k; + uint32 *pt, *end, mask, bank; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + /* Test the global address bits */ + for (p1 = 0, j = 0; j < 2; j++) { + /* set initial address 0x20000 alignment */ + pp = (uint32 *)roundup((ulong)v->map[0].start, 0x1ffff); + *pp = p1; + + /* Now write pattern compliment */ + p1 = ~p1; + end = v->map[segs - 1].end; + for (i = 0; i < 1000; i++) { + mask = 4; + do { + pt = (uint32 *) ((ulong) pp | mask); + if (pt == pp) { + mask = mask << 1; + continue; + } + if (pt >= end) { + break; + } + *pt = p1; + if (*pp != ~p1) { + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, ~p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + mask = mask << 1; + } while (mask); + } + FT_DDR_SHOW(); + } + + /* Now check the address bits in each bank + * If we have more than 8mb of memory then the bank size must be + * bigger than 256k. If so use 1mb for the bank size. + */ + if (v->pmap[v->msegs - 1].end > (0x800000 >> 12)) { + bank = 0x100000; + } else { + bank = 0x40000; + } + + for (p1 = 0, k = 0; k < 2; k++) { + for (j = 0; j < segs; j++) { + pp = v->map[j].start; + /* set initial address ַ256k alignment */ + pp = (uint32 *) roundup((ulong) pp, bank - 1); + end = v->map[j].end; + while (pp < end) { + *pp = p1; + p1 = ~p1; + for (i = 0; i < 200; i++) { + mask = 4; + do { + pt = (uint32 *)((ulong) pp | mask); + if (pt == pp) { + mask = mask << 1; + continue; + } + if (pt >= end) { + break; + } + *pt = p1; + if (*pp != ~p1) { + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, ~p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + mask = mask << 1; + } while (mask); + } + if (pp + bank > pp) { + pp += bank; + } else { + pp = end; + } + p1 = ~p1; + } + } + p1 = ~p1; + FT_DDR_SHOW(); + } + + return FT_DDR_SUCCESS; +} + +/** + * moving_inversions + * @iter: repeat times + * @p1: data written pattern1 + * @p2: data written pattern2 + * + * use the "movement reversla" algorithm to write memory address from low address to high address and + * from high address to low address + * write the p1 data format to the test memory area first,and check whether data is correct + * then write ~p1 data format to the test memory area,and check whether the written data is correct + * + * return 0 if success,else return 1 + */ +static int moving_inversions(char * desc, int iter, uint32 p1, uint32 p2) +{ + int i, j, done; + uint32 *pe; + uint32 *start, *end; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "Iter:%d P1:0x%x P2:0x%x.\n", iter, p1, p2); + /* from low address to high address,write p1 value to test memory area */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + + for (; pp < pe; pp++) { + *pp = p1; + } + } while (!done); + FT_DDR_SHOW(); + } + + for (i = 0; i < iter; i++) { + /* verify write data,from low address to high address,write p2 value to test memory area */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + + for (; pp < pe; pp++) { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p2; + } + } while (!done); + FT_DDR_SHOW(); + } + + /* verify write data,from high address to low address,write p1 value to test memory area */ + for (j = segs - 1; j >= 0; j--) { + start = v->map[j].start; + end = v->map[j].end; + pe = end - 1; + pp = end - 1; + done = 0; + do { + /* Check for underflow */ + if (pe - SPINSZ < pe) { + pe -= SPINSZ; + } else { + pe = start; + } + if (pe <= start) { + pe = start; + done++; + } + if (pp == pe) { + break; + } + + do { + if (*pp != p2) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p1; + } while (pp-- > pe); + } while (!done); + FT_DDR_SHOW(); + } + } + + return FT_DDR_SUCCESS; +} + +/** + * moving_inversions32 + * @iter: repeat times + * @p1: data pattern when writting memory for the first time + * @low_pattern: initial data pattern when from low address to high address + * @high_pattern: initial data pattern when from high address to low address + * @sval: + * @offset: bit offset when writting memory for the first time,low_pattern = p1 >> offset + * + * + * Using the "moving reversions-32bit" algorithm, the algorithm uses 32 write operations as a loop, + * and fter each write operation, for writing memory from low address to high address, the written data pattern + * needs to be shifted 1 bit to the left + * For writing memory from high address to low address, the written data pattern needs to be shifted 1 bit to the right + * + * return 0 if success ,else return 1 + */ +static int moving_inversions32(char *desc, int iter, uint32 p1, uint32 low_pattern, uint32 high_pattern, int sval, int offset) +{ + int i, j, k = 0, done; + uint32 *pe; + uint32 *start, *end; + uint32 pattern = 0; + uint32 p3 = sval << 31; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "Iter:%d P1:0x%x low_pattern:0x%x high_pattern:0x%x sval:%d offset:%d.\n", + iter, p1, low_pattern, high_pattern, sval, offset); + /* From low address to high address, write pattern value to test memory area */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + k = offset; + pattern = p1; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + while (pp < pe) { + *pp = pattern; + if (++k >= 32) { + pattern = low_pattern; + k = 0; + } else { + pattern = pattern << 1; + pattern |= sval; + } + pp++; + } + } while (!done); + FT_DDR_SHOW(); + } + + for (i = 0; i < iter; i++) { + /* Verify write data, from low address to high address, + write pattern value to test memory area */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + k = offset; + pattern = p1; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + + while (pp < pe) { + if (*pp != pattern) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, pattern, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, pattern, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = ~pattern; + if (++k >= 32) { + pattern = low_pattern; + k = 0; + } else { + pattern = pattern << 1; + pattern |= sval; + } + pp++; + } + } while (!done); + FT_DDR_SHOW(); + } + + /* Verify write data, from high address to low address, write pattern value to test memory area */ + pattern = low_pattern; + if (0 != (k = (k - 1) & 31)) { + pattern = (pattern << k); + if (sval) + pattern |= ((sval << k) - 1); + } + k++; + for (j = segs - 1; j >= 0; j--) { + start = v->map[j].start; + end = v->map[j].end; + pp = end - 1; + pe = end - 1; + done = 0; + do { + /* Check for underflow */ + if (pe - SPINSZ < pe) { + pe -= SPINSZ; + } else { + pe = start; + } + if (pe <= start) { + pe = start; + done++; + } + if (pp == pe) { + break; + } + + do { + if (*pp != ~pattern) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, ~pattern, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, ~pattern, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = pattern; + if (--k <= 0) { + pattern = high_pattern; + k = 32; + } else { + pattern = pattern >> 1; + pattern |= p3; + } + } while (pp-- > pe); + } while (!done); + FT_DDR_SHOW(); + } + } + + return FT_DDR_SUCCESS; +} + +/** + * modtst + * @offset: write the offset address of the P1 value + * @iter: number of repetitions of writing P2 value + * @p1: Data written 1 + * @p2: Data written 2 + * + * Write p1 data to the offset address of 20 * n + offset in the test memory area + * Write p2 data to other offset addresses, repeat iter times + * Check whether the data written in the offset address of 20 * n + offset is correct + * + * return 0 if success,else return 1 + */ +static int modtst(char *desc, int offset, int iter, uint32 p1, uint32 p2) +{ + int j, k, l, done; + uint32 *pe; + uint32 *start, *end; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "offset:%d Iter:%d P1:0x%x p2:0x%x.\n", offset, iter, p1, p2); + /* Write p1 data to the offset address of 20 * n + offset in the test memory area */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = (uint32 *) start; + pp = start + offset; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + + for (; pp < pe; pp += MOD_SZ) { + *pp = p1; + } + + } while (!done); + FT_DDR_SHOW(); + } + + /* Write p2 data to other offset addresses, repeat iter times */ + for (l = 0; l < iter; l++) { + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = (uint32 *) start; + pp = start; + done = 0; + k = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + + for (; pp < pe; pp++) { + if (k != offset) { + *pp = p2; + } + if (++k > MOD_SZ - 1) { + k = 0; + } + } + + } while (!done); + FT_DDR_SHOW(); + } + } + + /* Now check every nth location */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = (uint32 *) start; + pp = start + offset; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + + for (; pp < pe; pp += MOD_SZ) { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + } + + } while (!done); + FT_DDR_SHOW(); + } + + return FT_DDR_SUCCESS; +} + + +/** + * march_c + * @iter: repeat times + * @p1: Data written pattern1 + * @p2: Data written pattern2 + * + * From low address to high address, read p1, write p2, then read p2, write p1 + * From high address to low address, read p1, write p2, then read p2, write p1 + * + * return void + */ +static int march_c(char *desc, int iter, uint32 p1, uint32 p2) +{ + int i, j, done; + uint32 *pe; + uint32 *start, *end; + uint32 p_temp; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "Iter:%d P1:0x%x p2:0x%x.\n", iter, p1, p2); + /* form low address to high address, write p1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + *pp = p1; + } + } while (!done); + FT_DDR_SHOW(); + } + + /* From low address to high address, read p1, write p2, then read p2, write p1 */ + for (i = 0; i < 2; i++) { + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p2; + } + + } while (!done); + FT_DDR_SHOW(); + } + /* Exchange of p1 and p2 values */ + p_temp = p1; + p1 = p2; + p2 = p_temp; + } + + /* from high address to low address, read p1, write p2, then read p2, write p1 */ + for (i = 0; i < 2; i++) { + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = end - 1; + pp = end - 1; + done = 0; + do { + /* Check for underflow */ + if (pe - SPINSZ < pe) { + pe -= SPINSZ; + } else { + pe = start; + } + if (pe <= start) { + pe = start; + done++; + } + if (pp == pe) { + break; + } + + do { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p2; + } while (pp-- > pe); + + } while (!done); + FT_DDR_SHOW(); + } + + /* Exchange of p1 and p2 values */ + p_temp = p1; + p1 = p2; + p2 = p_temp; + } + + /* Verify the last written p1 value */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + } + + } while (!done); + FT_DDR_SHOW(); + } + + return FT_DDR_SUCCESS; +} + + +/** + * march_g + * @iter: repeat times + * @p1: data written pattern1 + * @p2: data written pattern2 + * + * from low address to high address, for the same address: read p1, write p2, then read p2, write p1 + * from low address to high address, for the same address: read p2, write p1 first, then write p2 + * from high address to low address, for the same address: read p2, write p1, write p2, and then write p1 + * from high address to low address, for the same address: read p1, write p2 first, and then write p1 + * + * return void + */ +static int march_g(char *desc, int iter, uint32 p1, uint32 p2) +{ + int j, done; + uint32 *pe; + uint32 *start, *end; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "Iter:%d P1:0x%x p2:0x%x.\n", iter, p1, p2); + /* from low address to high address, write p1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + *pp = p1; + } + } while (!done); + FT_DDR_SHOW(); + } + + /* from low address to high address, for the same address: read p1, write p2, read p2 again, write p1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p2; + if (*pp != p2) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p1; + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p2; + } + } while (!done); + FT_DDR_SHOW(); + } + + /* from low address to high address, for the same address: read p2, write p1 first and then write p2 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + if (*pp != p2) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p1; + *pp = p2; + } + } while (!done); + FT_DDR_SHOW(); + } + + /* from high address to low address, for the same address: read p2, write p1, write p2, and then write p1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = end - 1; + pp = end - 1; + done = 0; + do { + /* Check for underflow */ + if (pe - SPINSZ < pe) { + pe -= SPINSZ; + } else { + pe = start; + } + if (pe <= start) { + pe = start; + done++; + } + if (pp == pe) { + break; + } + + do { + if (*pp != p2) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p1; + *pp = p2; + *pp = p1; + } while (pp-- > pe); + + } while (!done); + FT_DDR_SHOW(); + } + + /* from high address to low address, for the same address: read p1, write p2 first, and then write p1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = end - 1; + pp = end - 1; + done = 0; + do { + /* Check for underflow */ + if (pe - SPINSZ < pe) { + pe -= SPINSZ; + } else { + pe = start; + } + if (pe <= start) { + pe = start; + done++; + } + if (pp == pe) { + break; + } + + do { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = p2; + *pp = p1; + } while (pp-- > pe); + + } while (!done); + FT_DDR_SHOW(); + } + + /* from high address to low address, to the same address: read p1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + } + + } while (!done); + FT_DDR_SHOW(); + } + + return FT_DDR_SUCCESS; +} + + +/** + * column_operate + * @iter: repeat times + * @p1: data written pattern1 + * @col_num: column address offset + * + * Using the "column operation" algorithm + * From low address to high address, write p1 to (n * step + col_addr) address + * + * return void + */ +static int column_operate(char *desc, int iter, uint32 p1, uint32 col_num) +{ + int j, k, done; + uint32 *pe; + uint32 *start, *end; + ulong n; + ulong step = 0x2000; + ulong addr; + ulong col_addr; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + /* from low address to high address, write p1 to (n * step + col_addr) address */ + for (k = 0; k < iter; k++) { + + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + + if (((ulong) start % step) <= (col_num & 0x3FF) << 3) { + n = (ulong) start / step; + } else { + n = (ulong) start / step + 1; + } + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp >= pe) { + break; + } + do { + col_addr = (col_num & 0x3FF) << 3; + addr = n * step + col_addr; + pp = (uint32 *) addr; + if (pp >= end) + break; + *pp = p1; + n++; + } while (pp < pe); + } while (!done); + } + /* FT_DDR_SHOW(); */ + + /* From low address to high address, verify (n * step + col_addr) address value */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + if (((ulong) start % step) < (col_num & 0x3FF) << 3) { + n = (ulong) start / step; + } else { + n = (ulong) start / step + 1; + } + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp >= pe) { + break; + } + do { + col_addr = (col_num & 0x3FF) << 3; + addr = n * step + col_addr; + pp = (uint32 *) addr; + if (pp >= end) + break; + if (*pp != p1) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p1, *pp); + fail = 1; + return FT_DDR_ERR; + } + n++; + } while (pp < pe); + } while (!done); + } + /* FT_DDR_SHOW(); */ + } + + return FT_DDR_SUCCESS; +} + + +/** + * galloping + * @p1: data written pattern1 + * @p2: data written pattern2 + * + * from low address to high address, write p2 to addr, read addr+1, read addr, write p1 to addr+1 + * from high address to low address, write p2 to addr, read addr-1, read addr, write p1 to addr-1 + * + * return void + */ +static int galloping(char *desc, uint32 p1, uint32 p2) +{ + int j, done; + uint32 *pe; + uint32 *start, *end; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + /* From low address to high address, write p1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + *pp = p1; + } + } while (!done); + FT_DDR_SHOW(); + } + + /* from low address to high address, write p2 to addr, read addr+1, read addr, write p1 to addr+1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + if (pp + 1 >= pe) + break; + *pp = p2; + *(pp + 1) = p1; + } + *pp = p2; + + } while (!done); + FT_DDR_SHOW(); + } + + /* from low address to high address, read p2 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + if (*pp != p2) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + fail = 1; + return FT_DDR_ERR; + } + } + } while (!done); + FT_DDR_SHOW(); + } + + /* from high address to low address, write p2 to addr, read addr-1, read addr, write p1 to addr-1 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = end - 1; + pp = end - 1; + done = 0; + do { + /* Check for underflow */ + if (pe - SPINSZ < pe) { + pe -= SPINSZ; + } else { + pe = start; + } + if (pe <= start) { + pe = start; + done++; + } + if (pp == pe) { + break; + } + + do { + if (pp - 1 <= pe) + break; + *pp = p2; + *(pp - 1) = p1; + } while (pp-- > pe); + *pp = p2; + } while (!done); + FT_DDR_SHOW(); + } + + /* rom high address to low address, read p2 */ + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = end - 1; + pp = end - 1; + done = 0; + do { + /* Check for underflow */ + if (pe - SPINSZ < pe) { + pe -= SPINSZ; + } else { + pe = start; + } + if (pe <= start) { + pe = start; + done++; + } + if (pp == pe) { + break; + } + + do { + if (*pp != p2) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, p2, *pp); + fail = 1; + return FT_DDR_ERR; + } + } while (pp-- > pe); + + } while (!done); + FT_DDR_SHOW(); + } + + return FT_DDR_SUCCESS; +} + +#if 0 +void dma_mov_addr(int chan_id, int from_addr, int to_addr, int size) +{ + dma_tx_data_init(); + get_dma_chan_cb(chan_id); + g_dma_tx_data[chan_id][0].src_addr = from_addr; + g_dma_tx_data[chan_id][0].dest_addr = to_addr; + g_dma_tx_data[chan_id][0].size = size; + dma_move(chan_id, 1); +} +#endif + +static void block_move_use_long_type(ulong *s, ulong *d, int blk_size) +{ + uint32 k; + + for (k = 0; k < blk_size / sizeof(ulong); k++) { + *(d++) = *(s++); + } +} + +/** + * swap_blocks + * @iter: repeat times + * @swap_times: number of block swaps repeated + * @blk_size: the size of each memory block + * + * Divide the memory area to be tested into n+1 blocks, and + * the n+1th block is used as a temporary swap block + * From the first block to the nth block, the data of two + * adjacent blocks are exchanged + * From the nth block to the first block, exchange the data of + * two adjacent blocks + * + * return void + */ +static int swap_blocks(char *desc, int iter, int swap_times, ulong blk_size) +{ + int i, j, done; + uint32 *pe; + uint32 *start, *end; + uint32 *ptemp; + uint32 *pprev; + uint32 *pnext; + ulong n; + int t; + int seed1, seed2; + int times; + uint32 num; + uint32 *pend; + ulong test_size; + + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + + iter = 1; + for (times = 0; times < iter; times++) { + start = v->map[0].start; + end = v->map[0].end; + pe = start; + pp = start; + done = 0; + seed1 = 521288629; + seed2 = 362436069; + + rand_seed(seed1, seed2); + + /* from low address to high address, write rand() */ + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + *pp = ft_rand(); + } + } while (!done); + FT_DDR_SHOW(); + + start = v->map[0].start; + end = v->map[0].end; + pe = start; + pp = start; + done = 0; + + for (t = 0; t < swap_times; t++) { + test_size = (ulong)end - (ulong)start; + n = test_size / blk_size; + FAC_LOG_DBG(GRTD_LOG_DEBUG,"start = %p, end = %p, test_size:0x%lx n = %lu\r\n", start, end, test_size, n); + + /* the last complete block is used as a swap block */ + while (1) { + ptemp = (uint32 *)((ulong)start + (n + 1) * blk_size); + pend = (uint32 *)((ulong)ptemp + blk_size); + if (pend >= end) { + n--; + } else { + break; + } + } + FT_DDR_SHOW(); + FAC_LOG_DBG(GRTD_LOG_DEBUG,"n = %lu\r\n", n); + + FAC_LOG_DBG(GRTD_LOG_DEBUG,"Test form 1 to %lu.\r\n", n); + /* from the first block to the nth block, the data of two adjacent blocks are exchanged */ + for (i = 0; (ulong)i < n; i++) { + pprev = (uint32 *) ((ulong) start + i * blk_size); + for (j = i + 1; (ulong)j <= n; j++) { + /* write all the data of the current i-th block to the exchange block */ + pprev = (uint32 *) ((ulong) start + i * blk_size); + ptemp = (uint32 *) ((ulong) start + (n + 1) * blk_size); + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"pprev:%p ptemp:%p.\r\n", pprev, ptemp); */ +#ifndef USE_DMA + block_move_use_long_type((ulong *)pprev, (ulong *)ptemp, blk_size); +#else + ret = dma_mov_addr(0, (ulong)pprev, (ulong)ptemp, blk_size); + if (ret) { + fail = 1; + return FT_DDR_ERR; + } + //return; +#endif + + /* write all the data of the current i+1th block to the current i-th block */ + pprev = (uint32 *)((ulong) start + i * blk_size); + pnext = (uint32 *)((ulong) start + j * blk_size); + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"pprev:%p pnext:%p.\r\n", pprev, pnext); */ +#ifndef USE_DMA + block_move_use_long_type((ulong *)pnext, (ulong *)pprev, blk_size); +#else + ret = dma_mov_addr(0, (ulong) pnext, (ulong) pprev, blk_size); + if (ret) { + fail = 1; + return FT_DDR_ERR; + } + +#endif + /* write all the data of the current exchange block to the current i+1 block */ + pnext = (uint32 *) ((ulong) start + j * blk_size); + ptemp = (uint32 *) ((ulong) start + (n + 1) * blk_size); + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"pnext:%p ptemp:%p.\r\n", pnext, ptemp); */ +#ifndef USE_DMA + block_move_use_long_type((ulong *)ptemp, (ulong *)pnext, blk_size); +#else + ret = dma_mov_addr(0, (ulong) ptemp, (ulong) pnext, blk_size); + if (ret) { + fail = 1; + return FT_DDR_ERR; + } + +#endif + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"test time %d-%d\r\n", i, j); */ + } + FT_DDR_SHOW(); + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG,"Test form %lu to 1.\r\n", n); + ptemp = (uint32 *) ((ulong) start + (n + 1) * blk_size); + /* from the nth block to the first block, exchange the data of two adjacent blocks */ + for (i = n; i > 0; i--) { + pprev = (uint32 *) ((ulong) start + i * blk_size); + for (j = i - 1; j >= 0; j--) { + /* write all the data of the current i-th block to the exchange block */ + pprev = (uint32 *) ((ulong) start + i * blk_size); + ptemp = (uint32 *) ((ulong) start + (n + 1) * blk_size); + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"pprev:%p ptemp:%p.\r\n", pprev, ptemp); */ +#ifndef USE_DMA + block_move_use_long_type((ulong *)pprev, (ulong *)ptemp, blk_size); +#else + ret = dma_mov_addr(0, (ulong) pprev, (ulong) ptemp, blk_size); + if (ret) { + fail = 1; + return FT_DDR_ERR; + } + +#endif + /* write all the data of the current i-1th block to the current i-th block */ + pnext = (uint32 *) ((ulong) start + j * blk_size); + pprev = (uint32 *) ((ulong) start + i * blk_size); + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"pnext:%p pprev:%p.\r\n", pnext, pprev); */ +#ifndef USE_DMA + block_move_use_long_type((ulong *)pnext, (ulong *)pprev, blk_size); +#else + ret = dma_mov_addr(0, (ulong) pnext, (ulong) pprev, blk_size); + if (ret) { + fail = 1; + return FT_DDR_ERR; + } + +#endif + /* write all the data of the current exchange block to the current i-1 block */ + pnext = (uint32 *) ((ulong) start + j * blk_size); + ptemp = (uint32 *) ((ulong) start + (n + 1) * blk_size); + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"pnext:%p ptemp:%p.\r\n", pnext, ptemp); */ +#ifndef USE_DMA + block_move_use_long_type((ulong *)ptemp, (ulong *)pnext, blk_size); +#else + ret = dma_mov_addr(0, (ulong) ptemp, (ulong) pnext, blk_size); + if (ret) { + fail = 1; + return FT_DDR_ERR; + } + +#endif + /* FAC_LOG_DBG(GRTD_LOG_DEBUG,"test time %d-%d\r\n", i, j); */ + } + FT_DDR_SHOW(); + } + + /* from low address to high address, read rand() */ + pe = start; + pp = start; + done = 0; + end = (uint32 *) ((ulong)pend - blk_size); + rand_seed(seed1, seed2); + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + num = ft_rand(); + if (*pp != num) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, num, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, num, *pp); + fail = 1; + return FT_DDR_ERR; + } + } + } while (!done); + FT_DDR_SHOW(); + } + } + + return FT_DDR_SUCCESS; +} + +/** + * ft_ddr_test_init + * + * initialize the memory area to be tested, + * the default is all the ranges allowed by the factory test + * + * return void + */ +void ft_ddr_test_init(void *start, size_t size) +{ + int i; + + v->rdtsc = 1; + v->msegs = 1; /* the number of memory areas currently set to be tested is 1 */ + fail = 0; + segs = 1; + + FAC_LOG_DBG(GRTD_LOG_ERR, "star:%p size:0x%lx(%lu MB).\n", start, size, size / 1024 / 1024); + for (i = 0; i < v->msegs; i++) { + v->pmap[i].start = (ulong)start; + v->pmap[i].end = ((ulong)start + size); + v->map[i].start = (uint32 *)start; + v->map[i].end = (uint32 *)((ulong)start + size); + } +} + +/** + * ddr_half_mov_inv_random_pat + * + * use the "half moving reversions" algorithm to write the memory + * address from low address to high address; + * write the p1 data format to the test memory area first, and + * check whether the written data is correct + * Then write ~p1 data format to the test memory area, and check + * whether the written data is correct + * + * return 0 if success ,else return 1 + */ +static int ddr_half_mov_inv_random_pat(char *desc) +{ + int i, j, done, seed1, seed2; + uint32 *pe; + uint32 *start, *end; + uint32 num; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_half_mov_inv_random_pat test.\n"); + if (fail) { + sprintf(desc, "No test."); + return FT_DDR_ERR; + } + /* Initialize memory with initial sequence of random numbers. */ + seed1 = 521288629 + v->pass; + seed2 = 362436069 - v->pass; + rand_seed(seed1, seed2); + + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + for (; pp < pe; pp++) { + *pp = ft_rand(); + } + } while (!done); + printf("."); + } + + /* Do moving inversions test. Check for initial pattern and then + * write the complement for each memory location. Test from bottom + * up and then from the top down. + */ + for (i = 0; i < 2; i++) { + rand_seed(seed1, seed2); + for (j = 0; j < segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + pp = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (pp == pe) { + break; + } + + if (i) { + num = 0xffffffff; + } else { + num = 0; + } + for (; pp < pe; pp++) { + num = ft_rand(); + if (i) { + num = ~num; + } + if (*pp != num) { + FAC_LOG_DBG(GRTD_LOG_ERR, "[%p] should be 0x%x,but is 0x%x.\n", pp, num, *pp); + sprintf(desc, "[%p] should be 0x%x,but is 0x%x.\n", pp, num, *pp); + fail = 1; + return FT_DDR_ERR; + } + *pp = ~num; + } + } while (!done); + } + } + + return FT_DDR_SUCCESS; +} + +/** + * ddr_mov_inv_random_pat + * + * use the "moving reversions" algorithm to write the memory address + * from low address to high address and from high address to address; + * Write the p1 data format to the test memory area first, and check + * whether the written data is correct; + * then write ~p1 data format to the test memory area, and check whether + the written data is correct; + * return 0 if success ,else return 1 + */ +static int ddr_mov_inv_random_pat(char *desc) +{ + /* Random Data */ + p1 = ft_rand(); + p2 = ~p1; + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_mov_inv_random_pat test.\n"); + return moving_inversions(desc, 2, p1, p2); +} + +/** + * ddr_mov_inv_0_1 + * @show: output control parameter information + * + * using "moving reversions" algorithm + * Data format:p1 = 0;p2 = ~0;p1 = ~0;p2 = 0; + * + * return 0 if success ,else return 1 + */ +static int ddr_mov_inv_0_1(char *desc) +{ + static unsigned int test_times = 0; + + test_times++; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_mov_inv_0_1 test.\n"); + /* Moving inversions, all ones and zeros */ + if (test_times % 2 == 1) { + p1 = 0; + p2 = ~p1; + } else { + /* Switch patterns */ + p2 = p1; + p1 = ~p2; + } + + return moving_inversions(desc, 3, p1, p2); +} + +/** + * ddr_mov_inv_8_pat + * @show: output control parameter information + * + * using "moving reversions" algorithm + * Data format: + * after each call of this function, p0 is shifted to the left by 1 bit + * p1 = p0;p2 = ~p0;p1 = ~p0;p2 = p0; + * + * return 0 if success,else return 1 + */ +static int ddr_mov_inv_8_pat(char *desc) +{ + static int times = 0; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_mov_inv_8_pat test.\n"); + /* Moving inversions, 8 bit wide walking ones and zeros. */ + if (times == 0) { + p0 = 0x80; + } else { + p0 = p0 >> 1; + } + p1 = p0 | (p0 << 8) | (p0 << 16) | (p0 << 24); + + if (times % 2 == 0) { + p2 = ~p1; + } else { + /* Switch patterns */ + p2 = p1; + p1 = ~p2; + } + times++; + + if (times >= 8) { + times = 0; + } + + return moving_inversions(desc, 3, p1, p2); +} + +/** + * ddr_mov_inv_32_pat + * @show: output control parameter information + * + * using "moving reversions 32" algorithm + * + * return 0 success,else return 1 + */ +static int ddr_mov_inv_32_pat(char *desc) +{ + static int times = 0; + static unsigned int test_times = 0; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_mov_inv_32_pat test.\n"); + test_times++; + if (times == 0) { + p1 = 1; + } else { + p1 = p1 << 1; + times ++; + if (times >= 32) + times = 0; + } + + if (moving_inversions32(desc, 2, p1, 1, 0x80000000, 0, times) || + moving_inversions32(desc, 2, ~p1, 0xfffffffe, 0x7fffffff, 1, times)) { + return FT_DDR_ERR; + } + + return FT_DDR_SUCCESS; +} + +/** + * ddr_mod20_random_pat + * @show: output control parameter information + * + * using the "modulo 20" algorithm + * Data format: + * p1 = ft_rand();p2 = ~ft_rand();or p1 = ~ft_rand();p2 = ft_rand(); + * + * return 0 if success,else return 1 + */ +static int ddr_mod20_random_pat(char *desc) +{ + static int mod20_rand_times = 0; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_mod20_random_pat test.\n"); + /* Modulo 20 check, Random pattern */ + if (mod20_rand_times % 40 == 0) { + p1 = ft_rand(); + mod20_rand_times = 0; + } else { + mod20_rand_times++; + } + + if (mod20_rand_times % 2 == 0) { + p2 = ~p1; + } else { + /* Switch patterns */ + p2 = p1; + p1 = ~p2; + } + + return modtst(desc, mod20_rand_times, 3, p1, p2); +} + +/** + * ddr_mod20_0_1_pat + * @show: output control parameter information + * + * using the "modulo 20" algorithm + * Data format:p1 = 0;p2 = ~0;p1 = ~0;p2 = 0; + * + * return 0 if success,esle return 1 + */ +static int ddr_mod20_0_1_pat(char *desc) +{ + static int ddr_mod20_0_1_times = 0; + int times; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_mod20_0_1_pat test.\n"); + /* Modulo 20 check, all ones and zeros */ + p1 = 0; + times = ddr_mod20_0_1_times % MOD_SZ; + ddr_mod20_0_1_times++; + + if (times % 2 == 0) { + p2 = ~p1; + /* modtst(times, 3, p1, p2); */ + } else { + /* Switch patterns */ + p2 = p1; + p1 = ~p2; + /* modtst(times, 3, p1, p2); */ + } + + return modtst(desc, times, 3, p1, p2); +} + +/** + * ddr_mod20_8_pat + * @show: output control parameter information + * + * using the "modulo 20" algorithm + * Data format: + * after each call of this function, p0 is shifted to the left by 1 bit + * p1 = p0;p2 = ~p0;p1 = ~p0;p2 = p0; + * + * return 0 if success,else return 1 + */ +static int ddr_mod20_8_pat(char *desc) +{ + static int pass = 0; + static int ddr_mod20_8_pat_times = 0; + int times; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_mod20_8_pat test.\n"); + /* Modulo 20 check, 8 bit pattern */ + pass = ddr_mod20_8_pat_times / MOD_SZ; + pass = pass % 8; + if (pass == 0) { + p0 = 0x80; + } else { + p0 = p0 >> 1; + } + + p1 = p0 | (p0 << 8) | (p0 << 16) | (p0 << 24); + + times = ddr_mod20_8_pat_times % MOD_SZ; + if (times % 2 == 0) { + p2 = ~p1; + } else { + /* Switch patterns */ + p2 = p1; + p1 = ~p2; + } + ddr_mod20_8_pat_times ++; + + return modtst(desc, times, 2, p1, p2); +} + +static int ddr_addr_walking(char *desc) +{ + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_addr_walking test.\n"); + return addrress_walking(desc); +} + +static int ddr_march_c(char *desc) +{ + static unsigned int test_times = 0; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_march_c test.\n"); + test_times++; + if (test_times == 1) { + p1 = 0; + } else { + p1 = ft_rand(); + } + p2 = ~p1; + + return march_c(desc, 1, p1, p2); +} + +static int ddr_march_g(char *desc) +{ + static unsigned int test_times = 0; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_march_g test.\n"); + test_times++; + if (test_times == 1) { + p1 = 0; + } else { + p1 = ft_rand(); + } + p2 = ~p1; + + return march_g(desc, 1, p1, p2); +} + +static int ddr_galloping(char *desc) +{ + static unsigned int test_times=0; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_galloping test.\n"); + test_times ++; + if (test_times == 1) { + p1 = 0; + } else { + p1 = ft_rand(); + } + p2 = ~p1; + + return galloping(desc, p1, p2); +} + +static int ddr_column_operate(char *desc) +{ + int i; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_column_operate test.\n"); + for (i = 0; i < 1023; i++) { + p1 = ~i; + /* column_operate(1, p1, i); */ + if (column_operate(desc, 1, p1, i)) { + return FT_DDR_ERR; + } + if (i % 100 == 0) { + FT_DDR_SHOW(); + } + } + + return FT_DDR_SUCCESS; +} + +static int ddr_swap_blocks(char *desc) +{ + static unsigned int test_times = 0; + ulong blk_size; + int ret; + int swap_times = 1; + struct vars v_tmp; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ddr_swap_blocks test.\n"); + test_times++; + blk_size = (ulong)blk_size_array[1]; /* 24MB */ + + strncpy((char *)(&v_tmp), (char *)(v), sizeof(struct vars)); + if (((ulong)v->map[0].end - (ulong)v->map[0].start) > MEMORY_SIZE_1G) { + FAC_LOG_DBG(GRTD_LOG_DEBUG, "set memory size to 0x%lx.\n", MEMORY_SIZE_1G); + v->map[0].end = (unsigned int *)((ulong)v->map[0].start + MEMORY_SIZE_1G); + } + ret = swap_blocks(desc, test_times, swap_times, blk_size); + strncpy((char *)(v), (char *)(&v_tmp), sizeof(struct vars)); + + return ret; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_dram.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_dram.c new file mode 100644 index 000000000000..e720490f52ba --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_dram.c @@ -0,0 +1,800 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_dram.c + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * Dram HardWare test + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int platform_fac_dbg = GRTD_LOG_NONE; +static int do_mlock = 1; +static ulong mem_test_data1 = sizeof(ulong) == 4 ? 0x55555555UL : 0x5555555555555555ULL; +static ulong mem_test_data2 = sizeof(ulong) == 4 ? 0xAAAAAAAAUL : 0xAAAAAAAAAAAAAAAAULL; + +int dram_wr_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + + +int dram_rd_main(int argc, char **argv) +{ + int fd, i, ret; + unsigned char buffer[1024]; + memset(buffer, 0, 1024); + argc = argc; + argv = argv; + if ((fd = open("/dev/mem",O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO)) < 0 ) { + printf("xxxx:%s\r\n", strerror(errno)); + return fd; + } + + if ((ret = lseek(fd, 0x1f400000, SEEK_SET)) < 0) { + printf("llseek:%s\r\n", strerror(errno)); + close(fd); + return ret; + } + if ((ret = read(fd, buffer, 1024)) < 0) { + printf("read:%s\r\n", strerror(errno)); + close(fd); + return ret; + } + + for (i = 0; i < 1024; i++) { + printf("%02x ", buffer[i]); + if ((i + 1) % 16 == 0) { + printf("\r\n"); + } + } + printf("\r\n"); + + close(fd); + return 0; +} + + +int dram_chk_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + +static int dram_test_arg_pars(int argc, char **argv, int *simple, int *all, int *debug) +{ + switch(argc) { + case 1: + *simple = 1; + *all = 0; + *debug = 0; + return 0; + case 2: + if (strcmp(argv[1], "simple") == 0) { + *simple = 1; + *all = 0; + *debug = 0; + } else if (strcmp(argv[1], "complex") == 0) { + *simple = 0; + *all = 0; + *debug = 0; + } else if (strcmp(argv[1], "debug") == 0) { + *simple = 1; + *all = 0; + *debug = 1; + } else { + break; + } + return 0; + case 3: + if (strcmp(argv[1], "simple") == 0 && strcmp(argv[2], "debug") == 0) { + *simple = 1; + *all = 0; + *debug = 1; + } else if (strcmp(argv[1], "complex") == 0) { + if (strcmp(argv[2], "some") == 0) { + *simple = 0; + *all = 0; + *debug = 0; + } else if (strcmp(argv[2], "all") == 0) { + *simple = 0; + *all = 1; + *debug = 0; + } else if (strcmp(argv[2], "debug") == 0) { + *simple = 0; + *all = 0; + *debug = 1; + } + } else { + break; + } + return 0; + case 4: + if (strcmp(argv[1], "complex") == 0) { + if (strcmp(argv[2], "some") == 0 && strcmp(argv[3], "debug") == 0) { + *simple = 0; + *all = 0; + *debug = 1; + } else if (strcmp(argv[2], "all") == 0 && strcmp(argv[3], "debug") == 0) { + *simple = 0; + *all = 1; + *debug = 1; + } else { + break; + } + } else { + break; + } + return 0; + default: + break; + } + + return -1; +} + +int platform_devfile_read(const char *filename, char *buf, int size, int offset) +{ + int fd; + int nread; + int ret; + + if (filename == NULL || buf == NULL) { + FAC_LOG_DBG(GRTD_LOG_ERR, "param is error!\n"); + return FAC_TEST_FAIL; + } + ret = FAC_TEST_OK; + if ((fd = open(filename, O_RDONLY | O_SYNC)) < 0) { + FAC_LOG_DBG(GRTD_LOG_ERR, "ERROR: Open file[%s] failed(%s)!\n", filename, strerror(errno)); + return FAC_TEST_FAIL; + } + + lseek(fd, offset, SEEK_SET); + + nread = read(fd, buf, size); + if (nread < 0) { + FAC_LOG_DBG(GRTD_LOG_ERR, "ERROR: Read file[%s] error(%s)!\n", filename, strerror(errno)); + ret = FAC_TEST_FAIL; + goto error; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "%s read data(off:0x%x):0x%x\n", filename, offset, buf[0]); +error: + close(fd); + return ret; +} + +int platform_devfile_write(const char *filename, char *buf, int size, int offset) +{ + int fd; + int nwrite; + int ret; + + if (filename == NULL || buf == NULL) { + FAC_LOG_DBG(GRTD_LOG_ERR, "param is error!\n"); + return FAC_TEST_FAIL; + } + ret = FAC_TEST_OK; + if ((fd = open(filename, O_CREAT | O_RDWR | O_TRUNC | O_SYNC, 0)) < 0) { + FAC_LOG_DBG(GRTD_LOG_ERR, "ERROR: Open file[%s] failed(%s)!\n", filename, strerror(errno)); + return FAC_TEST_FAIL; + } + + lseek(fd, offset, SEEK_SET); + + nwrite = write(fd, buf, size); + if (nwrite != size) { + FAC_LOG_DBG(GRTD_LOG_ERR, "ERROR: Write file[%s] error(%s)!\n", filename, strerror(errno)); + ret = FAC_TEST_FAIL; + goto error; + } + +error: + close(fd); + sync(); + return ret; +} + +int platform_get_sys_memory_size_form_cmdline(unsigned int *sys_memory_size) +{ + int ret; + char *start; + char *mem_start_string; + char mem_size_buf[FAC_MEM_SIZE_BUF_LEN]; + + /* MEMORY information area start character string */ + mem_start_string = "RAMSZ="; + /* get the memory size from the /proc/octeon_info file */ + memset(mem_size_buf, 0, FAC_MEM_SIZE_BUF_LEN); + ret = platform_devfile_read("/proc/cmdline", mem_size_buf, FAC_MEM_SIZE_BUF_LEN - 1, 0); + if (ret) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Read mem info fail!\n"); + return FAC_TEST_FAIL; + } + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:mem info[%s]\n", mem_size_buf); + + /* Extract memory size information from the read information */ + start = strstr(mem_size_buf, mem_start_string); + if (start != NULL) { + start = start + strlen(mem_start_string); + *sys_memory_size = strtoul(start, NULL, 10); + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:Mem size[%d MB]\n", *sys_memory_size); + return FAC_TEST_OK; + } else { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Get mem size fail!\n"); + return FAC_TEST_FAIL; + } +} + +/* + * platform_simple_get_mem_space - get space for memory test + * @buf: start address pointer + * @size: space size + * + * return: FAC_TEST_FAIL | FAC_TEST_OK + */ +static int platform_simple_get_mem_space(void **buf, size_t *size) +{ + size_t pagesize, wantsize, alignedsize; + void *start, *aligned; + int done_mem; + ptrdiff_t pagesizemask; + + start = NULL; + done_mem = 0; + wantsize = FAC_MEM_TEST_SIZE; + pagesize = 4096; + pagesizemask = (ptrdiff_t) ~(pagesize - 1); + + while (!done_mem) { + while (!start && wantsize) { + start = (void *) malloc(wantsize); + if (!start) wantsize -= pagesize; + } + *size = wantsize; + alignedsize = wantsize; + + fflush(stdout); + if (do_mlock && wantsize) { + fflush(stdout); + + if ((size_t) start % pagesize) { + aligned = (void *) ((size_t) start & pagesizemask) + pagesize; + alignedsize -= ((size_t) aligned - (size_t) start); + } else { + aligned = start; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "trying mlock ...start[0x%lx], size[0x%x]", (ulong)start, + (int)alignedsize); + /* Try mlock */ + if (mlock(aligned, alignedsize) < 0) { + switch(errno) { + case EAGAIN: + FAC_LOG_DBG(GRTD_LOG_ERR, "over system/pre-process limit, reducing...\n"); + free(start); + start = NULL; + wantsize -= pagesize; + break; + case ENOMEM: + FAC_LOG_DBG(GRTD_LOG_ERR, "too many pages, reducing...\n"); + free(start); + start = NULL; + wantsize -= pagesize; + break; + case EPERM: + FAC_LOG_DBG(GRTD_LOG_ERR, "insufficient permission.\n"); + FAC_LOG_DBG(GRTD_LOG_ERR, "Trying again, unlocked:\n"); + do_mlock = 0; + free(start); + start = NULL; + wantsize = FAC_MEM_TEST_SIZE; + break; + default: + FAC_LOG_DBG(GRTD_LOG_ERR, "failed for unknown reason.\n"); + do_mlock = 0; + done_mem = 1; + } + } else { + FAC_LOG_DBG(GRTD_LOG_DEBUG, "locked.\n"); + done_mem = 1; + } + } else { + done_mem = 1; + } + } + + if (!wantsize) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Malloc space failed\n"); + return FAC_TEST_FAIL; + } + if (!do_mlock) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Mlock mmap'ed space failed\n"); + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM WARNING:Continuing with unlocked memory;" + " testing will be slower and less reliable.\n"); + } + *buf = start; + return FAC_TEST_OK; +} + +static int platform_simple_check_addrline(ulong *start, size_t size, char *desc) +{ + ulong *p1; + ulong j; + size_t i; + size_t physaddr; + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:addr line check START[0x%lx] SIZE[0x%lx]!\n", + (ulong)start, (ulong)size); + fflush(stdout); + for (j = 0; j < 2; j++) { + p1 = start; + + fflush(stdout); + for (i = 0; i < size; i += sizeof(ulong), p1++) { + *((volatile ulong *)p1) = ((((j + i) % 2) == 0) ? (ulong)p1 : ~((ulong)p1)); + } + + fflush(stdout); + + p1 = start; + for (i = 0; i < size; i += sizeof(ulong), p1++) { + if (*((volatile ulong *)p1) != (((j + i) % 2) == 0 ? (ulong)p1 : ~((ulong)p1))) { + physaddr = (size_t)start + (i * sizeof(ulong)); + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Possible bad address line at physical " + "address 0x%08lx.\n", physaddr); + sprintf(desc, "MEM ERROR:Possible bad address line at physical " + "address 0x%08lx.\n", physaddr); + fflush(stdout); + return FAC_TEST_FAIL; + } + } + } + fflush(stdout); + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:addr line check OK!\n"); + return FAC_TEST_OK; +} +static int platform_simple_check_data(ulong *start, size_t size, char *desc) +{ + int i; + size_t j; + ulong data = 0; + ulong *p1; + ulong check_error = 0; + + /* Walking 1's Test */ + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:Walking 1's Test START[0x%lx] SIZE[0x%lx]!\n", + (ulong)start, (ulong)size); + for (i = 0; i < 8; i++) { + data = (data << 1) + 1; + p1 = start; + fflush(stdout); + for (j = 0; j < size; j += sizeof(ulong), p1++) { + *((volatile ulong *)p1) = data; + } + fflush(stdout); + p1 = start; + for (j = 0; j < size; j += sizeof(ulong), p1++) { + if (*((volatile ulong *)p1) != data) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:[0x%lx] should be 0x%lx,but is 0x%lx.\n", + (ulong)p1, data, *((volatile ulong *)p1)); + check_error++; + sprintf(desc, "MEM ERROR:[0x%lx] should be 0x%lx,but is 0x%lx.\n", + (ulong)p1, data, *((volatile ulong *)p1)); + return FAC_TEST_FAIL; + } + } + } + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:Walking 1's Test END!\n"); + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:Bus Noise Test START[0x%lx] SIZE[0x%lx]!\n", + (ulong)start, (ulong)size); + + /* Bus Noise Test */ + fflush(stdout); + p1 = start; + for (j = 0; j < size; j += sizeof(ulong), p1++) { + *((volatile ulong *)p1) = (j % 2) ? mem_test_data1 : mem_test_data2; + } + fflush(stdout); + p1 = start; + for (j = 0; j < size; j += sizeof(ulong), p1++) { + if (*((volatile ulong *)p1) != ((j % 2) ? mem_test_data1 : mem_test_data2)) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:[0x%lx] should be 0x%lx,but is 0x%lx.\n", + (ulong)p1, ((j % 2) ? mem_test_data1 : mem_test_data2), *((volatile ulong *)p1)); + check_error++; + sprintf(desc, "MEM ERROR:[0x%lx] should be 0x%lx,but is 0x%lx.\n", + (ulong)p1, ((j % 2) ? mem_test_data1 : mem_test_data2), *((volatile ulong *)p1)); + return FAC_TEST_FAIL; + } + } + fflush(stdout); + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:Bus Noise Test END!\n"); + return check_error; +} + +static void platform_simple_free_mem_space(void *buf, size_t size) +{ + if (do_mlock) { + munlock(buf, size); + } + free(buf); +} + +static int platform_simple_sdram_ecc_detect() +{ + char c; + char *loc, *next; + FILE *fp; + char file_line[FAC_FILE_LINE_LEN]; + int i, core_num, temp, ecc_error; + + i = 0; + core_num = 0; + ecc_error = 0; + + /* Open MTD device file */ + if ((fp = fopen("/proc/interrupts", "r")) == NULL) { + FAC_LOG_DBG(GRTD_LOG_ERR, "Fopen /proc/interrupts fail!\t err_no[%d]\n", errno); + return FAC_TEST_FAIL; + } + + memset(file_line, 0, FAC_FILE_LINE_LEN); + /* Find the name of the MTD device that can be used for production testing in each line of the MTD file */ + while (fgets(file_line, FAC_FILE_LINE_LEN, fp) != NULL) { + if (i == 0) { + loc = strrchr(file_line, 'U'); + core_num = strtoul(loc + 1, NULL, 10); + } + i++; + if (strstr(file_line, "LMC") != NULL) { + goto find; + } + } + FAC_LOG_DBG(GRTD_LOG_ERR, "ECC: Not find lmc info in file\n"); + fclose(fp); + return ecc_error; +find: + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ECC: Get ecc info[%s]\n", file_line); + /* Get the number of the MTD device name that can be tested in production, + the device name and device partition size separator is a colon */ + c = ':'; + if ((loc = strchr(file_line, c))!= NULL) { + i = 0; + loc++; + while (i <= core_num) { + temp = strtoul(loc, &next, 10); + loc = next; + ecc_error += temp; + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ECC: cpu %d ecc error num: %d\n", i, temp); + i++; + } + + } + + fclose(fp); + FAC_LOG_DBG(GRTD_LOG_DEBUG, "ECC: ecc error num: %d\n", ecc_error); + return ecc_error; + +} + +int platform_simple_sys_memory_test(char *desc) +{ + void *buf, *aligned; + size_t size, alignedsize, pagesize; + ptrdiff_t pagesizemask; + int ret = FAC_TEST_OK; + + /* get memory space available for testing */ + if (platform_simple_get_mem_space(&buf, &size) != FAC_TEST_OK) { + ret = GRTD_SDRAM_WR_ERR; + goto ecctest; + } + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:Get test space success, start at [0x%lx] size[0x%lx]\n", + (ulong)buf, (ulong)size); + + /* alignment 4K */ + pagesize = 4096; + pagesizemask = (ptrdiff_t) ~(pagesize - 1); + alignedsize = size; + if ((size_t) buf % pagesize) { + aligned = (void *) ((size_t) buf & pagesizemask) + pagesize; + alignedsize -= ((size_t) aligned - (size_t) buf); + } else { + aligned = buf; + } + + /* check the address line */ + if (platform_simple_check_addrline((ulong *)aligned, alignedsize, desc) != FAC_TEST_OK) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Check address line failed!\n"); + ret = GRTD_SDRAM_WR_ERR; + goto _error; + } + + /* memory read and write check */ + if (platform_simple_check_data((ulong *)aligned, alignedsize, desc)) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Check data failed!\n"); + ret = GRTD_SDRAM_WR_ERR; + goto _error; + } + +_error: + platform_simple_free_mem_space(buf, size); +ecctest: + /* memory ECC error detection */ + if (platform_simple_sdram_ecc_detect()) { + FAC_LOG_DBG(GRTD_LOG_ERR, "ERROR: ECC error occured!\n"); + ret = GRTD_SDRAM_ECC_ERR; + } + return ret; +} + +static int platform_get_system_free_mem(size_t *free_size) +{ + int len; + FILE *fp; + char *loc; + char mem_file_line[FAC_FILE_LINE_LEN]; + char mem_size[FAC_FILE_LINE_LEN]; + size_t all_free_size; + + if ((fp = fopen("/proc/meminfo", "r")) == NULL) { + FAC_LOG_DBG(GRTD_LOG_ERR, "Open meminfo fail(%s)!\n", strerror(errno)); + return FAC_TEST_FAIL; + } + + /* get the path of mount */ + memset(mem_file_line, 0, sizeof(mem_file_line)); + while (fgets(mem_file_line, FAC_FILE_LINE_LEN, fp) != NULL) { + FAC_LOG_DBG(GRTD_LOG_DEBUG, "meminfo file content:%s \n", mem_file_line); + loc = strstr(mem_file_line, "MemFree:"); + if (loc == NULL) { + continue; + } + + loc = loc + strlen("MemFree:"); + while (*loc == ' ') { + loc++; + } + len = 0; + while (*(loc + len) != ' ') { + len++; + } + FAC_LOG_DBG(GRTD_LOG_DEBUG, "free mem info:%s, len:%d \n", loc, len); + strncpy(mem_size, loc, len); + mem_size[len] = 0; + all_free_size = strtoul(mem_size, NULL, 10); + /* Use 90% to test */ + *free_size = all_free_size / 4 / 10 * 9 * 4096; + goto getok; + } + + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM free info get failed!\n"); + fclose(fp); + return FAC_TEST_FAIL; + +getok: + FAC_LOG_DBG(GRTD_LOG_DEBUG, "free mem: total--0x%lx use--0x%lx\n", all_free_size * 1024, *free_size); + fclose(fp); + return FAC_TEST_OK; +} + +/* + * platform_get_mem_space - get space for memory test + * @buf: start address pointer obtained + * @size: space size + * + * Return int: FAC_TEST_FAIL | FAC_TEST_OK + */ +static int platform_get_mem_space(void **buf, size_t *size) +{ + void *start; + size_t pagesize, wantsize; + + start = NULL; + if (platform_get_system_free_mem(&wantsize)) { + FAC_LOG_DBG(GRTD_LOG_DEBUG, "Get free mem info fail,use defaul size(0x%x)\n", FAC_MEM_TEST_SIZE); + wantsize = FAC_MEM_TEST_SIZE; + } + pagesize = 4096; /* page size is 4K */ + +retry: + while (!start && wantsize) { + start = (void *) malloc(wantsize); + if (!start) wantsize -= pagesize; + } + if (!wantsize) { + FAC_LOG_DBG(GRTD_LOG_ERR, "MEM ERROR:Malloc space failed\n"); + return FAC_TEST_FAIL; + } + *size = wantsize; + FAC_LOG_DBG(GRTD_LOG_DEBUG, "trying mlock ...start[%p], size[0x%lx]\n", start, wantsize); + /* mlock memory sapce */ + if (mlock(start, wantsize) < 0) { + FAC_LOG_DBG(GRTD_LOG_ERR, "failed for mlock(%s), retry.\n", strerror(errno)); + free(start); + start = NULL; + wantsize -= pagesize; + goto retry; + } + + *buf = start; + return FAC_TEST_OK; +} + +/* + * platform_free_mem_space - free the memory requested by the memory test + * + * Return void: + */ +static void platform_free_mem_space(void *buf, size_t size) +{ + munlock(buf, size); + free(buf); +} + +/** + * platform_complex_sys_memory_test - memory test + * @sdram_test: output, memory test result details + * @kaoji: input, whether to copy the machine currently * + * Return int: FAC_TEST_FAIL | FAC_TEST_OK + */ +int platform_complex_sys_memory_test(char *desc, int kaoji) +{ + int ret; + void *buf; + size_t size, autotest_size; + int i; + char desc_tmp[128]; + + if (desc == NULL) { + FAC_LOG_DBG(GRTD_LOG_ERR, "param is error!\n"); + return FAC_TEST_FAIL; + } + + ret = FAC_TEST_OK; + /* get memory space available for testing */ + if (platform_get_mem_space(&buf, &size) != FAC_TEST_OK) { + return FAC_TEST_FAIL; + } + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "MEM:Get test space success, start at [0x%lx] size[0x%lx]\n", + (ulong)buf, (ulong)size); + + autotest_size = size; +#if 0 + /* Init ddr test. */ + if (kaoji && autotest_size > FAC_MEM_AUTOTEST_SIZE) { + autotest_size = FAC_MEM_AUTOTEST_SIZE; + } else if (autotest_size > FAC_MEM_MAX_SIZE) { + autotest_size = FAC_MEM_MAX_SIZE; + } +#endif + ft_ddr_test_init(buf, autotest_size); + /* init memory */ + memset((char *)buf, 0, autotest_size); + + /* Test memory */ + memset((char *)desc_tmp, 0, 128); + for (i = 0 ; i < TETS_TOTAL_NUMBER; i++) { + if (ft_ddr_test_fun[i].always == 0 && kaoji) { + /* some test items are not tested in the copy machine state */ + continue; + } + + if (ft_ddr_test_fun[i].ddr_test != NULL) { + if (ft_ddr_test_fun[i].ddr_test(desc_tmp) != FT_DDR_SUCCESS) { + sprintf(desc, "%s:%s", ft_ddr_test_fun[i].name, desc_tmp); + ret = GRTD_SDRAM_WR_ERR; + break; + } + } + } + FT_DDR_SHOW_END(); + + FAC_LOG_DBG(GRTD_LOG_DEBUG, "TEST ok(ret:%d).\n", ret); + /* Free memory */ + platform_free_mem_space(buf, size); + return ret; +} + +static int memory_test(int simple, int all) +{ + unsigned int memory_size; + char desc[128]; + int ret; + + if (platform_get_sys_memory_size_form_cmdline(&memory_size)) { + printf("Get memory size fail\n"); + return FAC_TEST_FAIL; + } + + if (simple) { + ret = platform_simple_sys_memory_test(desc); + } else { + if (all) { + ret = platform_complex_sys_memory_test(desc, 0); + } else { + ret = platform_complex_sys_memory_test(desc, 1); + } + } + + if (simple) { + printf("\n[Simple Algorithm]\n"); + } else { + if (all) { + printf("\n[Complex All Algorithm]\n"); + } else { + printf("\n[Complex Some Algorithm]\n"); + } + } + printf(" SDRAM Space: %d(MB)\n", memory_size); + if (ret != FAC_TEST_OK) { + switch (ret) { + case GRTD_SDRAM_ECC_ERR: + printf(" ECC CHECK ERROR\r\n"); + break; + case GRTD_SDRAM_WR_ERR: + printf(" ERROR TYPE:SDRAM WR ERROR\r\n"); + break; + case GRTD_SDRAM_GET_MEM_SIZE_ERR: + printf(" ERROR TYPE:GET SDRAM MEM SIZE ERROR\r\n"); + break; + default: + printf(" UNKNOWN(%d)\r\n", ret); + break; + } + printf(" %s", desc); + printf(" Test Result: Fail\n\n"); + } else { + printf(" Test Result: Pass\n\n"); + } + return ret; +} + +int dram_test_main(int argc, char **argv) +{ + int simple,all,debug; + int ret; + + printf("\r\n" + "********************** dram test **********************\r\n"); + ret = dram_test_arg_pars(argc, argv, &simple, &all, &debug); + if (ret < 0) { + fprintf(stderr, + "Usage: dram_test [simple|complex some|complex all] \r\n" + " simple Use the simple Algorithm \r\n" + " complex some Use some the complex Algorithm \r\n" + " complex all Use all the complex Algorithm \r\n"); + exit(1); + return -1; + } + if (debug) { + platform_fac_dbg = GRTD_LOG_DEBUG; + } + + return memory_test(simple, all); +} + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_emmc.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_emmc.c new file mode 100644 index 000000000000..6361979fff0d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_emmc.c @@ -0,0 +1,130 @@ +/* + * $Id:$ + * Copyright(C) 2015 Ragile Network. All rights reserved. + */ +/* + * hw_emmc.c + * Original Author: support@ragilenetworks.com, 2015-06-05 + * + * eMMC test + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* XXX: Temporarily write to death */ +#define EMMC_SYS_BLOCK_PATH "/sys/block/emmcblk0/size" +#define EMMC_DEV_FACTEST_PATH "/dev/emmcblk0p7" +#define EMMC_BLK_SIZE 512 +#if 0 +/* The test value is the same as nandflash, the emmc factory_test partition has nearly 16MB */ +static char emmc_test_ch[] = { + 0x00, 0xFF, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, + 0xBF, 0x7F +}; +#endif +int emmc_test_main(int argc, char **argv) +{ +#if 1 + argc = argc; + argv = argv; + return -1; +#else + char *buf; + int fd, i, j, ret; + + if (argc != 1) { + fprintf(stderr, "Error: Wrong input!\n"); + return -1; + } + argv = argv; + + ret = posix_memalign((void **) &buf, EMMC_BLK_SIZE, EMMC_BLK_SIZE); + if (ret != 0) { + fprintf(stderr, "Error: Alloc memory failed(%d,%s)!\n", + ret, strerror(ret)); + return -1; + } + + fd = open(EMMC_DEV_FACTEST_PATH, O_RDWR | O_DIRECT, S_IRWXU); + if (fd < 0) { + fprintf(stderr, "ERROR: Open file[rw,%s] failed(%s)!\n", + EMMC_DEV_FACTEST_PATH, strerror(errno)); + goto out_free; + } + + for (i = 0; i < (int) sizeof(emmc_test_ch); i++) { + memset(buf, emmc_test_ch[i], EMMC_BLK_SIZE); + ret = write(fd, buf, EMMC_BLK_SIZE); + if (ret != EMMC_BLK_SIZE) { + fprintf(stderr, "ERROR: Write file error(%d,%d,%s)!\n", + ret, i, strerror(errno)); + goto out_close; + } + } + + ret = fsync(fd); + if (ret != 0) { + fprintf(stderr, "ERROR: Fsync file error(%d,%s)!\n", + ret, strerror(errno)); + goto out_close; + } + + close(fd); + + fd = open(EMMC_DEV_FACTEST_PATH, O_RDONLY | O_DIRECT, S_IRWXU); + if (fd < 0) { + fprintf(stderr, "ERROR: Open file[rd,%s] failed(%s)!\n", + EMMC_DEV_FACTEST_PATH, strerror(errno)); + goto out_free; + } + + for (i = 0; i < (int) sizeof(emmc_test_ch); i++) { + memset(buf, 0x11, EMMC_BLK_SIZE); /* 0x11 does not belong to any test value? */ + ret = read(fd, buf, EMMC_BLK_SIZE); + if (ret != EMMC_BLK_SIZE) { + fprintf(stderr, "ERROR: Read file error(%d,%d,%s)!\n", + ret, i, strerror(errno)); + goto out_close; + } + + for (j = 0; j < EMMC_BLK_SIZE; j++) { + if (buf[j] != emmc_test_ch[i]) { + fprintf(stderr, "ERROR: Check error(%d,%d,%d,%d)!\n", + i, j, buf[j], emmc_test_ch[i]); + goto out_close; + } + } + } + + close(fd); + + free(buf); + + printf("SUCCESS: eMMC test pass!\n"); + + return 0; + +out_close: + close(fd); + +out_free: + free(buf); + + return -1; +#endif +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_i2c.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_i2c.c new file mode 100644 index 000000000000..03a5499fab4d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_i2c.c @@ -0,0 +1,726 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * i2c.c + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * i2c HardWare test + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void rtc_help(char *name) +{ + fprintf(stderr, + "Usage: %s rtc year month day hour minute second \r\n" + " rtc rtc number(default 0) \r\n" + " year \r\n" + " month \r\n" + " day \r\n" + " hour \r\n" + " minute \r\n" + " second \r\n", + name); + exit(1); +} + + +static void i2c_help(char *name) +{ + fprintf(stderr, + "Usage: %s i2c_bus slave_addr offset data [data_len] [times] [offset_len] \r\n" + " i2c_bus controller integer or an I2C bus name \r\n" + " slave_addr i2c device address \r\n" + " offset The relative offset within the device \r\n" + " data Test data(8bit) \r\n" + " [data_len] The length of test data(default 1) \r\n" + " [times} \r\n", + name); + exit(1); +} + + +static int lookup_i2c_bus(const char *i2cbus_arg) +{ + unsigned long i2cbus; + char *end; + + i2cbus = strtoul(i2cbus_arg, &end, 0); + if (*end || !*i2cbus_arg) { + /* Not a number, maybe a name? */ + /* return lookup_i2c_bus_by_name(i2cbus_arg); */ + return -EINVAL; + } + if (i2cbus > 0xFFFFF) { + fprintf(stderr, "Error: I2C bus out of range!\n"); + return -EINVAL; + } + + return i2cbus; +} + + +static int parse_i2c_address(const char *address_arg) +{ + long address; + char *end; + + address = strtol(address_arg, &end, 0); + if (*end || !*address_arg) { + fprintf(stderr, "Error: slave address is not a number!\n"); + return -EINVAL; + } + if (address < 0x03 || address > 0x255) { + fprintf(stderr, "Error: save address out of range " + "(0x03-0x77)!\n"); + return -EINVAL; + } + + return address; +} + + +static int i2c_arg_check(int argc, char **argv, struct i2c_dev_priv *i2c_priv, int min_arg) +{ + int i2cbus, address, offset = 0, data = 0, data_len = 1, times = 1; + int offset_len = 1; + char *end; + int flags = 0; + + if (argc < min_arg) { + return -EINVAL; + } + + i2cbus = lookup_i2c_bus(argv[flags + 1]); + if (i2cbus < 0) { + return -EINVAL; + } + + address = parse_i2c_address(argv[flags + 2]); + if (address < 0) { + return -EINVAL; + } + + offset = strtol(argv[flags + 3], &end, 0); + if (*end || offset < 0 || offset > 0xffff) { + fprintf(stderr, "Error: Data offset invalid!\n"); + return -EINVAL; + } + + if (argc > 4) { + data = strtol(argv[flags + 4], &end, 0); + if (*end || offset < 0) { + fprintf(stderr, "Error: Data invalid!\n"); + return -EINVAL; + } + } + + if (argc > 5) { + data_len = strtol(argv[flags + 5], &end, 0); + if (*end || data_len < 0) { + fprintf(stderr, "Error: Data length invalid!\n"); + return -EINVAL; + } + } + + if (argc > 6) { + times = strtol(argv[flags + 6], &end, 0); + if (*end || times < 0) { + fprintf(stderr, "Error: times invalid!\n"); + return -EINVAL; + } + } + + if (argc > 7) { + offset_len = strtol(argv[flags + 7], &end, 0); + if (*end || times < 0) { + fprintf(stderr, "Error: times invalid!\n"); + return -EINVAL; + } + } + + i2c_priv->i2cbus = i2cbus; + i2c_priv->save_addr = address; + i2c_priv->offset = offset; + i2c_priv->offset_len = offset_len; + i2c_priv->data = data; + i2c_priv->data_len = data_len; + i2c_priv->times = times; + return 0; +} + + +static int open_i2c_dev(int i2cbus) +{ + int file, ret; + char filename[I2C_MAX_NAME_SIZE]; + + ret = snprintf(filename, I2C_MAX_NAME_SIZE, "/dev/i2c-%d", i2cbus); + filename[ret] = '\0'; + if ((file = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "`%s': %s\n", filename, strerror(errno)); + } + + return file; +} + + +#if 0 +static int set_slave_addr(int file, int address, int force) +{ + /* With force, let the user read from/write to the registers + even when a driver is also running */ + if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0) { + fprintf(stderr, + "Error: Could not set address to 0x%02x: %s\n", + address, strerror(errno)); + return -errno; + } + + return 0; +} +#endif + + +/** + * + * i2c_transfer + * + * + * @param file + * @param i2c_priv + * @param read_write 0:write 1:read + * @param num_msgs + * + * @return int + */ +static int i2c_transfer(int file, struct i2c_dev_priv *i2c_priv, int read_write, int num_msgs) +{ + int i; + unsigned char offset[2]; + struct i2c_msg msgs[2]; + struct i2c_rdwr_ioctl_data ioctl_data; + int len; + + if (i2c_priv->buffer == NULL) { + i2c_priv->buffer = malloc(i2c_priv->data_len); + if (i2c_priv->buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + return -ENOMEM; + } + } + + for (i = 0; i < i2c_priv->data_len && !read_write; i++) { + i2c_priv->buffer[i] = i2c_priv->data; + } + + if (i2c_priv->offset_len == 1) { + offset[0] = (i2c_priv->offset & 0xFF); + len = 1; + } else { + offset[0] = ((i2c_priv->offset & 0xFF00) >> 8); + offset[1] = (i2c_priv->offset & 0xFF); + len = 2; + } + + switch (num_msgs) { + case 1: + msgs[0].addr = i2c_priv->save_addr; + msgs[0].flags = read_write; + msgs[0].buf = i2c_priv->buffer; + msgs[0].len = i2c_priv->data_len; + + ioctl_data.msgs = msgs; + ioctl_data.nmsgs = 1; + break; + case 2: + msgs[0].addr = i2c_priv->save_addr; + msgs[0].flags = 0; + msgs[0].buf = offset; + msgs[0].len = len; + + msgs[1].addr = i2c_priv->save_addr; + msgs[1].flags = read_write; + msgs[1].buf = i2c_priv->buffer; + msgs[1].len = i2c_priv->data_len; + + ioctl_data.msgs = msgs; + ioctl_data.nmsgs = 2; + break; + default: + break; + } + + if (ioctl(file, I2C_RDWR, &ioctl_data) < 0) { + fprintf(stderr, + "Error: i2c_transfer error %s\n", + strerror(errno)); + return -1; + } + + return 0; +} + + +static void print_arg(struct i2c_dev_priv *i2c_priv) +{ + printf("I2C Controller %d, Slave addr: 0x%02X, Offset: 0x%02X", + i2c_priv->i2cbus, i2c_priv->save_addr, i2c_priv->offset); + + if (i2c_priv->data) { + printf(", Data = 0x%02X", i2c_priv->data); + } + + if (i2c_priv->data_len) { + printf(", Data_len = %d", i2c_priv->data_len); + } + + if (i2c_priv->times) { + printf(", Times = %u", i2c_priv->times); + } + + if (i2c_priv->offset_len) { + printf(", Offset_len = %u", i2c_priv->offset_len); + } + + printf("\r\n"); +} + + +static int i2c_check_data(unsigned char *buffer, struct i2c_dev_priv *i2c_priv) +{ + int i; + for (i = 0; i < i2c_priv->data_len; i++) { + if (buffer[i] != i2c_priv->buffer[i]) { + return (-1); + } + } + + return (0); +} + + +int i2c_wr_main(int argc, char **argv) +{ + int ret, fd; + struct i2c_dev_priv i2c_priv; + + memset(&i2c_priv, 0, sizeof(struct i2c_dev_priv)); + + ret = i2c_arg_check(argc, argv, &i2c_priv, 5); + if (ret < 0) { + i2c_help("i2c_wr"); + return -1; + } + + printf("\r\n" + "********************** I2C write test **********************\r\n"); + print_arg(&i2c_priv); + + if ((fd = open_i2c_dev(i2c_priv.i2cbus)) < 0) { + return -1; + } + +#if 0 + if ((ret = set_slave_addr(fd, i2c_priv.save_addr, 0)) < 0) { + close(fd); + return -1; + } +#endif + + while (i2c_priv.times--) { + if ((ret = i2c_transfer(fd, &i2c_priv, 0, 2)) < 0) { + goto error_out; + } + } + +error_out: + printf("\r\n******************** I2C read test End ********************\r\n\r\n"); + if (i2c_priv.buffer) { + free(i2c_priv.buffer); + } + close(fd); + return ret; +} + + +int i2c_rd_main(int argc, char **argv) +{ + int i, ret, fd; + struct i2c_dev_priv i2c_priv; + + memset(&i2c_priv, 0, sizeof(struct i2c_dev_priv)); + ret = i2c_arg_check(argc, argv, &i2c_priv, 4); + if (ret < 0) { + i2c_help("i2c_rd"); + return -1; + } + + if ((fd = open_i2c_dev(i2c_priv.i2cbus)) < 0) { + return -1; + } + + printf("\r\n" + "********************** I2C read test **********************\r\n"); + print_arg(&i2c_priv); + + +#if 0 + if ((ret = set_slave_addr(fd, i2c_priv.save_addr, 0)) < 0) { + close(fd); + return -1; + } +#endif + + while (i2c_priv.times--) { + if ((ret = i2c_transfer(fd, &i2c_priv, I2C_M_RD, 2)) < 0) { + goto error_out; + } + } + printf("Last Read: \r\n"); + /* dump data */ + for (i = 0; i < i2c_priv.data_len; i++) { + printf("%02X ", i2c_priv.buffer[i]); + if ((i + 1) % 16 == 0) { + printf("\r\n"); + } + } + +error_out: + printf("\r\n******************** I2C read test End ********************\r\n\r\n"); + if (i2c_priv.buffer) { + free(i2c_priv.buffer); + } + close(fd); + return ret; +} + + +int i2c_chk_main(int argc, char **argv) +{ + int ret, fd; + struct i2c_dev_priv i2c_priv; + unsigned char *buffer; + + memset(&i2c_priv, 0, sizeof(struct i2c_dev_priv)); + + ret = i2c_arg_check(argc, argv, &i2c_priv, 5); + if (ret < 0) { + i2c_help("i2c_chk"); + return -1; + } + + printf("\r\n" + "********************** I2C write test **********************\r\n"); + print_arg(&i2c_priv); + + if ((fd = open_i2c_dev(i2c_priv.i2cbus)) < 0) { + return -1; + } + +#if 0 + if ((ret = set_slave_addr(fd, i2c_priv.save_addr, 0)) < 0) { + close(fd); + return -1; + } +#endif + + buffer = malloc(i2c_priv.data_len); + if (buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + ret = -ENOMEM; + goto error_out; + } + while (i2c_priv.times--) { + if ((ret = i2c_transfer(fd, &i2c_priv, 0, 2)) < 0) { + goto error_out; + } + memcpy(buffer, i2c_priv.buffer, i2c_priv.data_len); + if ((ret = i2c_transfer(fd, &i2c_priv, I2C_M_RD, 2)) < 0) { + goto error_out; + } + if ((ret = i2c_check_data(buffer, &i2c_priv)) < 0) { + i2c_priv.check_test_errors++; + } + } + printf("Check test errors = %u\r\n", i2c_priv.check_test_errors); + +error_out: + printf("\r\n******************** I2C read test End ********************\r\n\r\n"); + if (i2c_priv.buffer) { + free(i2c_priv.buffer); + } + if (buffer) { + free(buffer); + } + close(fd); + return ret; +} + + +int i2c_reset_main(int argc, char **argv) +{ + printf("not support %s argc:%d, \r\n", argv[0], argc); + return 0; +} + + +int pca9548_rd_main(int argc, char **argv) +{ + int i, ret, fd; + struct i2c_dev_priv i2c_priv; + + memset(&i2c_priv, 0, sizeof(struct i2c_dev_priv)); + ret = i2c_arg_check(argc, argv, &i2c_priv, 4); + if (ret < 0) { + i2c_help("pca9548_rd"); + return -1; + } + + printf("\r\n" + "********************** I2C multiplexer read test **********************\r\n"); + print_arg(&i2c_priv); + + if ((fd = open_i2c_dev(i2c_priv.i2cbus)) < 0) { + return -1; + } + +#if 0 + if ((ret = set_slave_addr(fd, i2c_priv.save_addr, 0)) < 0) { + close(fd); + return -1; + } +#endif + + while (i2c_priv.times--) { + if ((ret = i2c_transfer(fd, &i2c_priv, I2C_M_RD, 1)) < 0) { + goto error_out; + } + } + printf("Last Read: \r\n"); + /* dump data */ + for (i = 0; i < i2c_priv.data_len; i++) { + printf("%02X ", i2c_priv.buffer[i]); + if ((i + 1) % 16 == 0) { + printf("\r\n"); + } + } + +error_out: + printf("\r\n******************** I2C multiplexer read test End ********************\r\n\r\n"); + if (i2c_priv.buffer) { + free(i2c_priv.buffer); + } + close(fd); + return ret; +} + + +int pca9548_wr_main(int argc, char **argv) +{ + int ret, fd; + struct i2c_dev_priv i2c_priv; + + memset(&i2c_priv, 0, sizeof(struct i2c_dev_priv)); + + ret = i2c_arg_check(argc, argv, &i2c_priv, 5); + if (ret < 0) { + i2c_help("pca9548_wr"); + return -1; + } + + printf("\r\n" + "********************** I2C multiplexer write test **********************\r\n"); + print_arg(&i2c_priv); + + if ((fd = open_i2c_dev(i2c_priv.i2cbus)) < 0) { + return -1; + } + +#if 0 + if ((ret = set_slave_addr(fd, i2c_priv.save_addr, 0)) < 0) { + close(fd); + return -1; + } +#endif + + while (i2c_priv.times--) { + if ((ret = i2c_transfer(fd, &i2c_priv, 0, 1)) < 0) { + goto error_out; + } + } + +error_out: + printf("\r\n******************** I2C multiplexer read test End ********************\r\n\r\n"); + if (i2c_priv.buffer) { + free(i2c_priv.buffer); + } + close(fd); + return ret; +} + + + +int rtc_rd_main(int argc, char **argv) +{ + int ret, fd; + struct rtc_time rtc; + int rtc_num; + char *end, filename[I2C_MAX_NAME_SIZE]; + + if (argc < 2) { + rtc_help("rtc_rd"); + } + + rtc_num = strtol(argv[1], &end, 0); + if (*end || rtc_num < 0 || rtc_num > 0xff) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_rd"); + return -EINVAL; + } + + ret = snprintf(filename, I2C_MAX_NAME_SIZE, "/dev/rtc%d", rtc_num); + filename[ret] = '\0'; + if ((fd = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "`%s': %s\n", filename, strerror(errno)); + return -1; + } + + if (ioctl(fd, RTC_RD_TIME, &rtc) < 0) { + fprintf(stderr, + "Error: get rtc error %s\n", + strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("\r\n******************** RTC read test ********************\r\n"); + + + printf("Read RTC: %d-%d-%d, %d:%d:%d\n", + rtc.tm_year + 1900, rtc.tm_mon + 1, rtc.tm_mday, + rtc.tm_hour, rtc.tm_min, rtc.tm_sec); + printf("\r\n******************** RTC read test End ********************\r\n\r\n"); + + return 0; +} + + +int rtc_wr_main(int argc, char **argv) +{ + int ret, fd, year; + struct rtc_time rtc; + int rtc_num; + char *end, filename[I2C_MAX_NAME_SIZE]; + + if (argc < 8) { + rtc_help("rtc_wr"); + } + + rtc_num = strtol(argv[1], &end, 0); + if (*end || rtc_num < 0 || rtc_num > 0xff) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_wr"); + return -EINVAL; + } + + year = strtol(argv[2], &end, 0); + if (*end || year < 0) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_wr"); + return -EINVAL; + } + + rtc.tm_year = year - 1900; + + rtc.tm_mon = strtol(argv[3], &end, 0); + if (*end || rtc.tm_mon <= 0 || rtc.tm_mon > 12) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_wr"); + return -EINVAL; + } + + rtc.tm_mon = rtc.tm_mon - 1; + + rtc.tm_mday = strtol(argv[4], &end, 0); + if (*end || rtc.tm_mday < 0 || rtc.tm_mday > 31) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_wr"); + return -EINVAL; + } + + rtc.tm_hour = strtol(argv[5], &end, 0); + if (*end || rtc.tm_hour < 0 || rtc.tm_hour > 23) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_wr"); + return -EINVAL; + } + + rtc.tm_min = strtol(argv[6], &end, 0); + if (*end || rtc.tm_min < 0 || rtc.tm_min > 59) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_wr"); + return -EINVAL; + } + + rtc.tm_sec = strtol(argv[7], &end, 0); + if (*end || rtc.tm_sec < 0 || rtc.tm_sec > 59) { + fprintf(stderr, "Error: Invalid argument!\n"); + rtc_help("rtc_wr"); + return -EINVAL; + } + + ret = snprintf(filename, I2C_MAX_NAME_SIZE, "/dev/rtc%d", rtc_num); + filename[ret] = '\0'; + if ((fd = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "`%s': %s\n", filename, strerror(errno)); + return -1; + } + + if (ioctl(fd, RTC_SET_TIME, &rtc) < 0) { + fprintf(stderr, + "Error: get rtc error %s\n", + strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("\r\n******************** RTC write test ********************\r\n"); + + printf("Set RTC: %d-%d-%d, %d:%d:%d\n", + year, rtc.tm_mon + 1, rtc.tm_mday, + rtc.tm_hour, rtc.tm_min, rtc.tm_sec); + printf("\r\n******************** RTC write test End ********************\r\n\r\n"); + + return 0; +} \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_misc.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_misc.c new file mode 100644 index 000000000000..84ac093c32e6 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_misc.c @@ -0,0 +1,720 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_misc.c + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * MISC HardWare test + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void dram_help(char *name) +{ + fprintf(stderr, + "Usage: %s reg_addr [reg_data] \r\n" + " reg_addr \r\n" + " reg_data \r\n", + name); + exit(1); +} + + +static void mdio_help(char *name) +{ + fprintf(stderr, + "Usage: %s is_c45 bus_id phy_id device reg_addr [reg_data] \r\n" + " is_c45 use c45 mode \r\n" + " bus_id mdio bus number \r\n" + " phy_id phy address \r\n" + " device device \r\n" + " reg_addr phy register offset \r\n" + " reg_data phy value \r\n", + name); + exit(1); +} + + +static int dram_arg_parse(int argc, char **argv, + u64 *reg_addr, u64 *reg_data, + int min_arg) +{ + u64 reg_addr_tmp, reg_data_tmp = 0; + char *end; + int flags = 0; + + if (argc < min_arg) { + return -EINVAL; + } + + reg_addr_tmp = strtoul(argv[flags + 1], &end, 0); + if (*end) { + fprintf(stderr, "Error: reg addr invalid!\n"); + return -EINVAL; + } + + if (argc > 2) { + reg_data_tmp = strtoul(argv[flags + 2], &end, 0); + if (*end) { + fprintf(stderr, "Error: reg data invalid!\n"); + return -EINVAL; + } + } + + *reg_addr = reg_addr_tmp; + *reg_data = reg_data_tmp; + + return 0; +} + + +static int mdio_arg_parse(int argc, char **argv, + u32 *isc45, u32 *busid, u32 *phyid, + u32 *deviceid, u32 *regoffset, u32 *regvalue, + int min_arg) +{ + int is_c45, bus_id, phy_id, device_id, reg_offset, value; + char *end; + int flags = 0; + + if (argc < min_arg) { + return -EINVAL; + } + + is_c45 = strtoul(argv[flags + 1], &end, 0); + if (*end || is_c45 < 0 || is_c45 > 0xff) { + fprintf(stderr, "Error: is_c45 id invalid!\n"); + return -EINVAL; + } + + bus_id = strtoul(argv[flags + 2], &end, 0); + if (*end || bus_id < 0 || bus_id > 0xff) { + fprintf(stderr, "Error: bus id invalid!\n"); + return -EINVAL; + } + + phy_id = strtoul(argv[flags + 3], &end, 0); + if (*end || phy_id < 0 || phy_id > 0xffff) { + fprintf(stderr, "Error: phy id invalid!\n"); + return -EINVAL; + } + + device_id = strtoul(argv[flags + 4], &end, 0); + if (*end || device_id < 0 || device_id > 0xffff) { + fprintf(stderr, "Error: device id invalid!\n"); + return -EINVAL; + } + + reg_offset = strtoul(argv[flags + 5], &end, 0); + if (*end || reg_offset < 0 || reg_offset > 0xffff) { + fprintf(stderr, "Error: reg location invalid!\n"); + return -EINVAL; + } + + if (argc > 6) { + value = strtoul(argv[flags + 6], &end, 0); + if (*end) { + fprintf(stderr, "Error: reg data invalid!\n"); + return -EINVAL; + } + *regvalue = value; + } + + *isc45 = is_c45; + *busid = bus_id; + *phyid = phy_id; + *deviceid = device_id; + *regoffset = reg_offset; + + return 0; +} + +int reload_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + + +int sys_info_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + + +int mem_dump_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + + +int cache_flush_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + + +int reg_wr64_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + unsigned int reg_data1, reg_data2; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 3); + if (ret < 0) { + dram_help("reg_wr64"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek :%s\n", strerror(errno)); + close(fd); + return -1; + } + reg_data2 = (unsigned int)(((u64)reg_data) >> 32) & 0xFFFFFFFF; + reg_data1 = (unsigned int)reg_data & 0xFFFFFFFF; + buf[0] = (reg_data1 >> 0) & 0xFF; + buf[1] = (reg_data1 >> 8) & 0xFF; + buf[2] = (reg_data1 >> 16) & 0xFF; + buf[3] = (reg_data1 >> 24) & 0xFF; + + buf[4] = (reg_data2 >> 0) & 0xFF; + buf[5] = (reg_data2 >> 8) & 0xFF; + buf[6] = (reg_data2 >> 16) & 0xFF; + buf[7] = (reg_data2 >> 24) & 0xFF; + + if ((ret = write(fd, buf, 8)) < 0) { + fprintf(stderr, "Error: Could not write file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Write quad-word 0x%16llX to address 0x%16llX.\n\n", reg_data, reg_addr); + return 0; +} + + +int reg_rd64_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + unsigned int reg_data1, reg_data2; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 2); + if (ret < 0) { + dram_help("reg_rd64"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if ((ret = read(fd, buf, 8)) < 0) { + fprintf(stderr, "Error: Could not read file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + reg_data1 = (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24)); + reg_data2 = (buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24)); + + printf("Read quad-word from address 0x%16llX: 0x%08X%08X\n\n", reg_addr, reg_data2, reg_data1); + return 0; +} + + +int reg_wr32_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + unsigned int reg_data1, reg_data2; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 3); + if (ret < 0) { + dram_help("reg_wr32"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek :%s\n", strerror(errno)); + close(fd); + return -1; + } + reg_data2 = (unsigned int)(((u64)reg_data) >> 32) & 0xFFFFFFFF; + reg_data1 = (unsigned int)reg_data & 0xFFFFFFFF; + buf[0] = (reg_data1 >> 0) & 0xFF; + buf[1] = (reg_data1 >> 8) & 0xFF; + buf[2] = (reg_data1 >> 16) & 0xFF; + buf[3] = (reg_data1 >> 24) & 0xFF; + + buf[4] = (reg_data2 >> 0) & 0xFF; + buf[5] = (reg_data2 >> 8) & 0xFF; + buf[6] = (reg_data2 >> 16) & 0xFF; + buf[7] = (reg_data2 >> 24) & 0xFF; + + if ((ret = write(fd, buf, 4)) < 0) { + fprintf(stderr, "Error: Could not write file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Write word 0x%08X to address 0x%16llX.\n\n", reg_data1, reg_addr); + return 0; +} + + +int reg_rd32_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + unsigned int reg_data1; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 2); + if (ret < 0) { + dram_help("reg_rd32"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if ((ret = read(fd, buf, 4)) < 0) { + fprintf(stderr, "Error: Could not read file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + reg_data1 = (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24)); + + printf("Read word from address 0x%16llX: 0x%08X\n\n", reg_addr, reg_data1); + return 0; +} + + +int reg_wr16_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + unsigned int reg_data1, reg_data2; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 3); + if (ret < 0) { + dram_help("reg_wr16"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek :%s\n", strerror(errno)); + close(fd); + return -1; + } + reg_data2 = (unsigned int)(((u64)reg_data) >> 32) & 0xFFFFFFFF; + reg_data1 = (unsigned int)reg_data & 0xFFFFFFFF; + buf[0] = (reg_data1 >> 0) & 0xFF; + buf[1] = (reg_data1 >> 8) & 0xFF; + buf[2] = (reg_data1 >> 16) & 0xFF; + buf[3] = (reg_data1 >> 24) & 0xFF; + + buf[4] = (reg_data2 >> 0) & 0xFF; + buf[5] = (reg_data2 >> 8) & 0xFF; + buf[6] = (reg_data2 >> 16) & 0xFF; + buf[7] = (reg_data2 >> 24) & 0xFF; + + if ((ret = write(fd, buf, 2)) < 0) { + fprintf(stderr, "Error: Could not write file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Write half-word 0x%02X%02X to address 0x%16llX.\n\n", buf[1], buf[0], reg_addr); + return 0; +} + +int reg_rd16_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 2); + if (ret < 0) { + dram_help("reg_rd16"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if ((ret = read(fd, buf, 2)) < 0) { + fprintf(stderr, "Error: Could not read file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Read half-word from address 0x%16llX: 0x%02X%02X\n\n", reg_addr, buf[1], buf[0]); + return 0; +} + + +int reg_wr8_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + unsigned int reg_data1, reg_data2; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 3); + if (ret < 0) { + dram_help("reg_wr8"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek :%s\n", strerror(errno)); + close(fd); + return -1; + } + reg_data2 = (unsigned int)(((u64)reg_data) >> 32) & 0xFFFFFFFF; + reg_data1 = (unsigned int)reg_data & 0xFFFFFFFF; + buf[0] = (reg_data1 >> 0) & 0xFF; + buf[1] = (reg_data1 >> 8) & 0xFF; + buf[2] = (reg_data1 >> 16) & 0xFF; + buf[3] = (reg_data1 >> 24) & 0xFF; + + buf[4] = (reg_data2 >> 0) & 0xFF; + buf[5] = (reg_data2 >> 8) & 0xFF; + buf[6] = (reg_data2 >> 16) & 0xFF; + buf[7] = (reg_data2 >> 24) & 0xFF; + + if ((ret = write(fd, buf, 1)) < 0) { + fprintf(stderr, "Error: Could not write file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Write byte 0x%02X to address 0x%16llX.\n\n", buf[0], reg_addr); + return 0; +} + + +int reg_rd8_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 2); + if (ret < 0) { + dram_help("reg_rd8"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if ((ret = read(fd, buf, 1)) < 0) { + fprintf(stderr, "Error: Could not read file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Read byte from address 0x%16llX: 0x%02X\n\n", reg_addr, buf[0]); + return 0; +} + + +int mdio_rd_main(int argc, char **argv) +{ + struct mdio_user_info mdio_info; + int fd; + long int ret; + + ret = mdio_arg_parse(argc, argv, + &mdio_info.c45, + &mdio_info.bus_id, + &mdio_info.phy_addr, + &mdio_info.device, + &mdio_info.location, + &mdio_info.value, + 6); + if (ret < 0) { + mdio_help("mdio_rd"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + + + if ((ret = ioctl(fd, MDIO_READ, &mdio_info)) < 0) { + fprintf(stderr, "Error: mdio read error : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Read mdio from [bus:%d, phy:0x%x, device:0x%x, reg:0x%x]: 0x%08x\r\n", + mdio_info.bus_id, mdio_info.phy_addr, mdio_info.device, mdio_info.location, mdio_info.value); + + return 0; +} + + +int mdio_wr_main(int argc, char **argv) +{ + struct mdio_user_info mdio_info; + int fd; + long int ret; + + ret = mdio_arg_parse(argc, argv, + &mdio_info.c45, + &mdio_info.bus_id, + &mdio_info.phy_addr, + &mdio_info.device, + &mdio_info.location, + &mdio_info.value, + 6); + + if (ret < 0) { + mdio_help("mdio_wr"); + return -1; + } + + if ((fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + + + if ((ret = ioctl(fd, MDIO_WRITE, &mdio_info)) < 0) { + fprintf(stderr, "Error: mdio read error : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + printf("Write 0x%08X to address [bus:%d, phy:0x%x, device:0x%x, reg:0x%x].\n\n", + mdio_info.value, mdio_info.bus_id, mdio_info.phy_addr, mdio_info.device, mdio_info.location); + + return 0; +} + +#define LPC_CPLD_DEV_NAME "/dev/lpc_cpld" + +int lpc_cpld_wr8_main(int argc, char **argv) +{ + u64 reg_addr, reg_data; + unsigned int reg_data1, reg_data2; + int fd; + long int ret; + unsigned char buf[MAX_DATA_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 3); + if (ret < 0) { + dram_help("reg_wr8"); + return -1; + } + + if ((fd = open(LPC_CPLD_DEV_NAME, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek :%s\n", strerror(errno)); + close(fd); + return -1; + } + reg_data2 = (unsigned int)(((u64)reg_data) >> 32) & 0xFFFFFFFF; + reg_data1 = (unsigned int)reg_data & 0xFFFFFFFF; + buf[0] = (reg_data1 >> 0) & 0xFF; + buf[1] = (reg_data1 >> 8) & 0xFF; + buf[2] = (reg_data1 >> 16) & 0xFF; + buf[3] = (reg_data1 >> 24) & 0xFF; + + buf[4] = (reg_data2 >> 0) & 0xFF; + buf[5] = (reg_data2 >> 8) & 0xFF; + buf[6] = (reg_data2 >> 16) & 0xFF; + buf[7] = (reg_data2 >> 24) & 0xFF; + + if ((ret = write(fd, buf, 1)) < 0) { + fprintf(stderr, "Error: Could not write file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + /*printf("Write byte 0x%02X to address 0x%16llX.\n\n", buf[0], reg_addr);*/ + return 0; +} + +#define MAX_LPC_SIZE 256 +int lpc_cpld_rd8_main(int argc, char **argv) +{ + u64 reg_addr, reg_data, size, i; + int fd; + long int ret; + unsigned char buf[MAX_LPC_SIZE]; + + ret = dram_arg_parse(argc, argv, ®_addr, ®_data, 2); + if (ret < 0) { + dram_help("reg_rd8"); + return -1; + } + + if ((fd = open(LPC_CPLD_DEV_NAME, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "/dev/dram: %s\n", strerror(errno)); + return -1; + } + + if ((ret = lseek(fd, reg_addr, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek : %s\n", strerror(errno)); + close(fd); + return -1; + } + + size = (reg_data ? (reg_data) : (1)); + if (size > MAX_LPC_SIZE) { + printf("size %llu exceed max %d.\n", size, MAX_LPC_SIZE); + close(fd); + return -1; + } + + if ((ret = read(fd, buf, size)) < 0) { + fprintf(stderr, "Error: Could not read file : %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + /* dump data */ + for (i = 0; i < size; i++) { + printf("%02X ", buf[i]); + if ((i + 1) % 16 == 0) { + printf("\r\n"); + } + } + + printf("\r\n"); + + return 0; +} diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_mtdflash.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_mtdflash.c new file mode 100644 index 000000000000..8f9f34963f39 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_mtdflash.c @@ -0,0 +1,731 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_norflash.c + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * NandFlash HardWare test + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void mtdflash_help(char *name) +{ + fprintf(stderr, + "Usage: %s start_addr end_addr data1 data2 [times] \r\n" + " start_addr Flash start address \r\n" + " end_addr Flash end address \r\n" + " data1 Test data1(8bit) \r\n" + " data2 Test data2(8bit) \r\n" + " [times} \r\n", + name); + exit(1); +} + + +static int mtd_arg_get(int argc, char **argv, struct mtd_dev_priv *mtd_priv, int min_arg) +{ + unsigned int start_addr, end_addr, data1 = 0, data2 = 0, times = 1; + char *end; + int flags = 0; + + if (argc < min_arg) { + return -EINVAL; + } + + + start_addr = strtol(argv[flags + 1], &end, 0); + if (*end) { + fprintf(stderr, "Error: start addr invalid!\n"); + return -EINVAL; + } + + end_addr = strtol(argv[flags + 2], &end, 0); + if (*end) { + fprintf(stderr, "Error: end addr invalid!\n"); + return -EINVAL; + } + + if (argc > 3) { + data1 = strtol(argv[flags + 3], &end, 0); + if (*end) { + fprintf(stderr, "Error: data1 invalid!\n"); + return -EINVAL; + } + } + + if (argc > 4) { + data2 = strtol(argv[flags + 4], &end, 0); + if (*end) { + fprintf(stderr, "Error: data2 invalid!\n"); + return -EINVAL; + } + } + + if (argc > 5) { + times = strtol(argv[flags + 5], &end, 0); + if (*end) { + fprintf(stderr, "Error: times invalid!\n"); + return -EINVAL; + } + } + + + mtd_priv->start_addr = start_addr; + mtd_priv->end_addr = end_addr; + mtd_priv->data1 = data1; + mtd_priv->data2 = data2; + mtd_priv->times = times; + return 0; +} + + +static void print_arg(struct mtd_dev_priv *mtd_priv) +{ + printf("Start: 0x%08X, End: 0x%08X\n", + mtd_priv->start_addr, mtd_priv->end_addr); + printf("Data1 = 0x%02X, Data2 = 0x%02X", + mtd_priv->data1, mtd_priv->data2); + + printf(", Times = %u", mtd_priv->times); + + printf("\r\n"); +} + + +static int open_mtd_dev(char *test_name) +{ + FILE *fd; + int file, ret; + char buffer[MAX_BUFFER_SIZE], filename[MAX_BUFFER_SIZE], *ptr; + + if ((fd = fopen("/proc/mtd", "r")) == NULL) { + fprintf(stderr, "Error: Could not open file " + "/proc/mtd: %s\n", strerror(errno)); + return -1; + } + + while (fgets(buffer, MAX_BUFFER_SIZE, fd)) { + if ((ptr = strstr(buffer, test_name)) != NULL) { + break; + } + } + fclose(fd); + + if ((ptr = strstr(buffer, ":")) == NULL) { + return -1; + } + *ptr = '\0'; + + ret = snprintf(filename, MAX_BUFFER_SIZE, "/dev/%s", buffer); + filename[ret] = '\0'; + + printf("....................%s\r\n", filename); + + if ((file = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "`%s': %s\n", filename, strerror(errno)); + } + + return file; +} + + +static int mtd_arg_check(int fd, + struct mtd_dev_priv *mtd_priv, + unsigned int *nand_erasesize) +{ + int ret; + struct mtd_info_user mtd; + + if ((ret = ioctl(fd, MEMGETINFO, &mtd)) < 0) { + perror("MEMGETINFO"); + return -1; + } + + if ((mtd.type != MTD_NANDFLASH && mtd.type != MTD_NORFLASH) || + (mtd.flags != MTD_CAP_NANDFLASH && mtd.flags != MTD_CAP_NORFLASH)) { + printf("Error, Not NandFlash or NorFlash!\r\n"); + return -1; + } + + if ((mtd_priv->start_addr & (mtd.writesize - 1)) || + (mtd_priv->end_addr & (mtd.writesize -1))) { + printf("Error, Address must be %d bytes aligned!\r\n", mtd.writesize); + return -1; + } + + if (mtd_priv->end_addr > mtd.size) { + printf("Error, Address out of test range!\r\n"); + return -1; + } + + if (mtd_priv->start_addr >= mtd_priv->end_addr) { + printf("Error, start address is higher than end address!\r\n"); + return -1; + } + + *nand_erasesize = mtd.erasesize; + + return 0; +} + + +static int mtd_check_data(unsigned char *buffer, + struct mtd_dev_priv *mtd_priv, + unsigned long len) +{ + unsigned int i; + len = mtd_priv->end_addr - mtd_priv->start_addr; + for (i = 0; i < len; i++) { + if (buffer[i] != mtd_priv->buffer[i]) { + return (-1); + } + } + + return (0); +} + + +int nand_wr_main(int argc, char **argv) +{ + int ret, fd; + unsigned long i, len; + unsigned int nand_erasesize; + struct mtd_dev_priv nand_priv; + struct erase_info_user erase; + + memset(&nand_priv, 0, sizeof(struct mtd_dev_priv)); + + ret = mtd_arg_get(argc, argv, &nand_priv, 5); + if (ret < 0) { + mtdflash_help("nand_wr"); + return -1; + } + + if ((fd = open_mtd_dev(NAND_TEST_PARTITION)) < 0) { + return -1; + } + + if ((ret = mtd_arg_check(fd, &nand_priv, &nand_erasesize)) < 0) { + close(fd); + return -1; + } + + len = nand_priv.end_addr - nand_priv.start_addr; + if (nand_priv.buffer == NULL) { + nand_priv.buffer = malloc(len); + if (nand_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + return -ENOMEM; + } + } + + printf("\r\n********************** NANDFLASH write test **********************\r\n"); + print_arg(&nand_priv); + + while (nand_priv.times--) { + erase.start = (nand_priv.start_addr / nand_erasesize) * nand_erasesize; + erase.length = ((len + nand_erasesize) / nand_erasesize) * nand_erasesize; + if ((ret = ioctl(fd, MEMERASE, &erase)) < 0) { + perror("MEMERASE"); + goto error_out; + } + if (nand_priv.times % 2) { + for (i = 0; i < len;) { + nand_priv.buffer[i++] = nand_priv.data1; + nand_priv.buffer[i++] = nand_priv.data2; + } + } else { + for (i = 0; i < len;) { + nand_priv.buffer[i++] = nand_priv.data2; + nand_priv.buffer[i++] = nand_priv.data1; + } + } + + if ((ret = lseek(fd, nand_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + + if ((ret = write(fd, nand_priv.buffer, len)) < 0) { + fprintf(stderr, "%s: write, size %ld, %d\n", __func__, len, ret); + perror("write"); + goto error_out; + } + } + +error_out: + printf("\r\n******************** NANDFLASH write test End ********************\r\n\r\n"); + close(fd); + if (nand_priv.buffer) { + free(nand_priv.buffer); + } + return ret; +} + + +int nand_rd_main(int argc, char **argv) +{ + int ret, fd; + unsigned long len; + unsigned int nand_erasesize; + struct mtd_dev_priv nand_priv; + + memset(&nand_priv, 0, sizeof(struct mtd_dev_priv)); + + ret = mtd_arg_get(argc, argv, &nand_priv, 3); + if (ret < 0) { + mtdflash_help("nand_rd"); + return -1; + } + + if ((fd = open_mtd_dev(NAND_TEST_PARTITION)) < 0) { + return -1; + } + + if ((ret = mtd_arg_check(fd, &nand_priv, &nand_erasesize)) < 0) { + close(fd); + return -1; + } + + len = nand_priv.end_addr - nand_priv.start_addr; + if (nand_priv.buffer == NULL) { + nand_priv.buffer = malloc(len); + if (nand_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + return -ENOMEM; + } + } + + printf("\r\n********************** NANDFLASH read test **********************\r\n"); + print_arg(&nand_priv); + + while (nand_priv.times--) { + if ((ret = lseek(fd, nand_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + if ((ret = read(fd, nand_priv.buffer, len)) < 0) { + fprintf(stderr, "%s: read, size %ld, %d\n", __func__, len, ret); + perror("read"); + goto error_out; + } + } +#if 0 + printf("Last Read: \r\n"); + /* dump data */ + for (i = 0; i < len; i++) { + printf("%02X ", nand_priv.buffer[i]); + if ((i + 1) % 16 == 0) { + printf("\r\n"); + } + } +#endif + +error_out: + printf("\r\n******************** NANDFLASH read test End ********************\r\n\r\n"); + close(fd); + if (nand_priv.buffer) { + free(nand_priv.buffer); + } + return ret; +} + + +int nand_chk_main(int argc, char **argv) +{ + int ret, fd; + unsigned long i, len; + unsigned int nand_erasesize; + struct mtd_dev_priv nand_priv; + struct erase_info_user erase; + unsigned char *buffer; + + memset(&nand_priv, 0, sizeof(struct mtd_dev_priv)); + + ret = mtd_arg_get(argc, argv, &nand_priv, 5); + if (ret < 0) { + mtdflash_help("nand_chk"); + return -1; + } + + if ((fd = open_mtd_dev(NAND_TEST_PARTITION)) < 0) { + return -1; + } + + if ((ret = mtd_arg_check(fd, &nand_priv, &nand_erasesize)) < 0) { + close(fd); + return -1; + } + + len = nand_priv.end_addr - nand_priv.start_addr; + if (nand_priv.buffer == NULL) { + nand_priv.buffer = malloc(len); + if (nand_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + return -ENOMEM; + } + } + buffer = malloc(len); + if (nand_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + if (nand_priv.buffer) { + free(nand_priv.buffer); + } + return -ENOMEM; + } + + printf("\r\n********************** NANDFLASH write test **********************\r\n"); + print_arg(&nand_priv); + + while (nand_priv.times--) { + erase.start = (nand_priv.start_addr / nand_erasesize) * nand_erasesize; + erase.length = ((len + nand_erasesize) / nand_erasesize) * nand_erasesize; + if ((ret = ioctl(fd, MEMERASE, &erase)) < 0) { + perror("MEMERASE"); + goto error_out; + } + if (nand_priv.times % 2) { + for (i = 0; i < len;) { + nand_priv.buffer[i++] = nand_priv.data1; + nand_priv.buffer[i++] = nand_priv.data2; + } + } else { + for (i = 0; i < len;) { + nand_priv.buffer[i++] = nand_priv.data2; + nand_priv.buffer[i++] = nand_priv.data1; + } + } + + if ((ret = lseek(fd, nand_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + + if ((ret = write(fd, nand_priv.buffer, len)) < 0) { + fprintf(stderr, "%s: write, size %ld, %d\n", __func__, len, ret); + perror("write"); + goto error_out; + } + + if ((ret = lseek(fd, nand_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + + if ((ret = read(fd, buffer, len)) < 0) { + fprintf(stderr, "%s: write, size %ld, %d\n", __func__, len, ret); + perror("write"); + goto error_out; + } + if ((ret = mtd_check_data(buffer, &nand_priv, len)) < 0) { + nand_priv.check_test_errors++; + } + } + +error_out: + printf("Check test errors = %u\r\n", nand_priv.check_test_errors); + printf("\r\n******************** NANDFLASH write test End ********************\r\n\r\n"); + close(fd); + if (nand_priv.buffer) { + free(nand_priv.buffer); + } + if (buffer) { + free(buffer); + } + return ret; +} + + +int nor_wr_main(int argc, char **argv) +{ + int ret, fd; + unsigned long i, len; + unsigned int nor_erasesize; + struct mtd_dev_priv nor_priv; + struct erase_info_user erase; + + memset(&nor_priv, 0, sizeof(struct mtd_dev_priv)); + + ret = mtd_arg_get(argc, argv, &nor_priv, 5); + if (ret < 0) { + mtdflash_help("nor_wr"); + return -1; + } + + if ((fd = open_mtd_dev(NOR_TEST_PARTITION)) < 0) { + return -1; + } + + if ((ret = mtd_arg_check(fd, &nor_priv, &nor_erasesize)) < 0) { + close(fd); + return -1; + } + + len = nor_priv.end_addr - nor_priv.start_addr; + if (nor_priv.buffer == NULL) { + nor_priv.buffer = malloc(len); + if (nor_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + return -ENOMEM; + } + } + + printf("\r\n********************** NORFLASH write test **********************\r\n"); + print_arg(&nor_priv); + + while (nor_priv.times--) { + erase.start = (nor_priv.start_addr / nor_erasesize) * nor_erasesize; + erase.length = ((len + nor_erasesize) / nor_erasesize) * nor_erasesize; + if ((ret = ioctl(fd, MEMERASE, &erase)) < 0) { + perror("MEMERASE"); + goto error_out; + } + if (nor_priv.times % 2) { + for (i = 0; i < len;) { + nor_priv.buffer[i++] = nor_priv.data1; + nor_priv.buffer[i++] = nor_priv.data2; + } + } else { + for (i = 0; i < len;) { + nor_priv.buffer[i++] = nor_priv.data2; + nor_priv.buffer[i++] = nor_priv.data1; + } + } + + if ((ret = lseek(fd, nor_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + + if ((ret = write(fd, nor_priv.buffer, len)) < 0) { + fprintf(stderr, "%s: write, size %ld, %d\n", __func__, len, ret); + perror("write"); + goto error_out; + } + } + +error_out: + printf("\r\n******************** NORFLASH write test End ********************\r\n\r\n"); + close(fd); + if (nor_priv.buffer) { + free(nor_priv.buffer); + } + return ret; +} + + +int nor_rd_main(int argc, char **argv) +{ + int ret, fd; + unsigned long i, len; + unsigned int nor_erasesize; + struct mtd_dev_priv nor_priv; + + memset(&nor_priv, 0, sizeof(struct mtd_dev_priv)); + + ret = mtd_arg_get(argc, argv, &nor_priv, 3); + if (ret < 0) { + mtdflash_help("nor_rd"); + return -1; + } + + if ((fd = open_mtd_dev(NOR_TEST_PARTITION)) < 0) { + return -1; + } + + if ((ret = mtd_arg_check(fd, &nor_priv, &nor_erasesize)) < 0) { + close(fd); + return -1; + } + + len = nor_priv.end_addr - nor_priv.start_addr; + if (nor_priv.buffer == NULL) { + nor_priv.buffer = malloc(len); + if (nor_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + return -ENOMEM; + } + } + + printf("\r\n********************** NORFLASH read test **********************\r\n"); + print_arg(&nor_priv); + + while (nor_priv.times--) { + if ((ret = lseek(fd, nor_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + if ((ret = read(fd, nor_priv.buffer, len)) < 0) { + fprintf(stderr, "%s: read, size %ld, %d\n", __func__, len, ret); + perror("read"); + goto error_out; + } + } +#if 1 + printf("Last Read: \r\n"); + /* dump data */ + for (i = 0; i < len; i++) { + printf("%02X ", nor_priv.buffer[i]); + if ((i + 1) % 16 == 0) { + printf("\r\n"); + } + } +#endif + +error_out: + printf("\r\n******************** NORFLASH read test End ********************\r\n\r\n"); + close(fd); + if (nor_priv.buffer) { + free(nor_priv.buffer); + } + return ret; +} + + +int nor_chk_main(int argc, char **argv) +{ + int ret, fd; + unsigned long i, len; + unsigned int nor_erasesize; + struct mtd_dev_priv nor_priv; + struct erase_info_user erase; + unsigned char *buffer; + + memset(&nor_priv, 0, sizeof(struct mtd_dev_priv)); + + ret = mtd_arg_get(argc, argv, &nor_priv, 5); + if (ret < 0) { + mtdflash_help("nand_chk"); + return -1; + } + + if ((fd = open_mtd_dev(NOR_TEST_PARTITION)) < 0) { + return -1; + } + + if ((ret = mtd_arg_check(fd, &nor_priv, &nor_erasesize)) < 0) { + close(fd); + return -1; + } + + len = nor_priv.end_addr - nor_priv.start_addr; + if (nor_priv.buffer == NULL) { + nor_priv.buffer = malloc(len); + if (nor_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + return -ENOMEM; + } + } + buffer = malloc(len); + if (nor_priv.buffer == NULL) { + fprintf(stderr, + "Error: Could not malloc memory %s\n", + strerror(errno)); + close(fd); + if (nor_priv.buffer) { + free(nor_priv.buffer); + } + return -ENOMEM; + } + + printf("\r\n********************** NORFLASH write test **********************\r\n"); + print_arg(&nor_priv); + + while (nor_priv.times--) { + erase.start = (nor_priv.start_addr / nor_erasesize) * nor_erasesize; + erase.length = ((len + nor_erasesize) / nor_erasesize) * nor_erasesize; + if ((ret = ioctl(fd, MEMERASE, &erase)) < 0) { + perror("MEMERASE"); + goto error_out; + } + if (nor_priv.times % 2) { + for (i = 0; i < len;) { + nor_priv.buffer[i++] = nor_priv.data1; + nor_priv.buffer[i++] = nor_priv.data2; + } + } else { + for (i = 0; i < len;) { + nor_priv.buffer[i++] = nor_priv.data2; + nor_priv.buffer[i++] = nor_priv.data1; + } + } + + if ((ret = lseek(fd, nor_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + + if ((ret = write(fd, nor_priv.buffer, len)) < 0) { + fprintf(stderr, "%s: write, size %ld, %d\n", __func__, len, ret); + perror("write"); + goto error_out; + } + + if ((ret = lseek(fd, nor_priv.start_addr, SEEK_SET)) < 0) { + perror("lseek"); + goto error_out; + } + + if ((ret = read(fd, buffer, len)) < 0) { + fprintf(stderr, "%s: write, size %ld, %d\n", __func__, len, ret); + perror("write"); + goto error_out; + } + if ((ret = mtd_check_data(buffer, &nor_priv, len)) < 0) { + nor_priv.check_test_errors++; + } + } + +error_out: + printf("Check test errors = %u\r\n", nor_priv.check_test_errors); + printf("\r\n******************** NORFLASH write test End ********************\r\n\r\n"); + close(fd); + if (nor_priv.buffer) { + free(nor_priv.buffer); + } + if (buffer) { + free(buffer); + } + return ret; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_pci.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_pci.c new file mode 100644 index 000000000000..5d72232cc0d2 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_pci.c @@ -0,0 +1,496 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_pci.c + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * PCI HardWare test + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void pci_help(char *name) +{ + fprintf(stderr, + "Usage: %s bus slot fn bar offset data [times] \r\n" + " bus pci bus number \r\n" + " slot pci slot number \r\n" + " fn pci device function number \r\n" + " bar pci resource bar number \r\n" + " offset pci register offset \r\n" + " data pci test data[32bit] \r\n" + " [times] \r\n", + name); + exit(1); +} + + +static void pci_cfg_help(char *name) +{ + fprintf(stderr, + "Usage: %s bus slot fn offset data [times] \r\n" + " bus pci bus number \r\n" + " slot pci slot number \r\n" + " fn pci device function number \r\n" + " offset pci register offset \r\n" + " data pci test data[8bit] \r\n" + " [times] \r\n", + name); + exit(1); +} + + +static int pci_arg_parse(int argc, char **argv, + struct pci_dev_priv *pci_priv, int min_arg, int is_cfg) +{ + int pcibus, slot, fn, bar = 0, offset = 0, times = 1; + unsigned long int data = 0; + char *end; + int flags = 0; + + if (argc < min_arg) { + return -EINVAL; + } + + pcibus = strtol(argv[flags + 1], &end, 0); + if (*end || pcibus < 0 || pcibus > 255) { + fprintf(stderr, "Error: pci bus number invalid!\n"); + return -EINVAL; + } + + slot = strtol(argv[flags + 2], &end, 0); + if (*end || slot < 0 || slot > 255) { + fprintf(stderr, "Error: pci slot number invalid!\n"); + return -EINVAL; + } + + fn = strtol(argv[flags + 3], &end, 0); + if (*end || fn < 0 || fn > 32) { + fprintf(stderr, "Error: pci device function number invalid!\n"); + return -EINVAL; + } + + if (!is_cfg) { + bar = strtol(argv[flags + 4], &end, 0); + if (*end || bar < 0 || bar > 12) { + fprintf(stderr, "Error: pci resource bar number invalid!\n"); + return -EINVAL; + } + flags++; + } + + offset = strtol(argv[flags + 4], &end, 0); + if (*end || offset < 0 || (offset & 0x3)) { + fprintf(stderr, "Error: pci register offset invalid!\n"); + return -EINVAL; + } + + if ((argc - flags) > 5) { + data = strtoul(argv[flags + 5], &end, 0); + if (*end) { + fprintf(stderr, "Error: data invalid!\n"); + return -EINVAL; + } + } + + if ((argc - flags) > 6) { + times = strtol(argv[flags + 6], &end, 0); + if (*end || times < 0) { + fprintf(stderr, "Error: times invalid!\n"); + return -EINVAL; + } + } + + pci_priv->pcibus = pcibus; + pci_priv->slot = slot; + pci_priv->fn = fn; + pci_priv->bar = bar; + pci_priv->offset = offset; + pci_priv->data = (unsigned int)data; + pci_priv->times = times; + return 0; +} + + +static void print_arg(struct pci_dev_priv *pci_priv, int is_cfg) +{ + printf("Bus: %d, Slot: %d/%d", + pci_priv->pcibus, pci_priv->slot, pci_priv->fn); + + if (!is_cfg) { + printf(", Bar: %d", pci_priv->bar); + } + printf(", offset: 0x%X", pci_priv->offset); + + if (pci_priv->data) { + printf(", Data = 0x%08X", pci_priv->data); + } + + if (pci_priv->times) { + printf(", Times = %u", pci_priv->times); + } + + printf("\r\n"); +} + + +static int open_pci_dev(struct pci_dev_priv *pci_priv, int is_cfg) +{ + int file, ret; + char filename[PCI_MAX_NAME_SIZE]; + + if (is_cfg) { + ret = snprintf(filename, PCI_MAX_NAME_SIZE, + "/sys/class/pci_bus/%04x:%02x/device/%04x:%02x:%02x.%d/config", + 0, pci_priv->pcibus, 0, pci_priv->pcibus, pci_priv->slot, pci_priv->fn); + } else { + ret = snprintf(filename, PCI_MAX_NAME_SIZE, + "/sys/class/pci_bus/%04x:%02x/device/%04x:%02x:%02x.%d/resource%d", + 0, pci_priv->pcibus, 0, pci_priv->pcibus, pci_priv->slot, pci_priv->fn, + pci_priv->bar); + } + + filename[ret] = '\0'; + if ((file = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + fprintf(stderr, "Error: Could not open file " + "`%s': %s\n", filename, strerror(errno)); + } + + printf("file;%s\r\n", filename); + return file; +} + + +int pci_wr_main(int argc, char **argv) +{ + int ret, fd; + struct pci_dev_priv pci_priv; + unsigned int *ptr; + struct stat sb; + + memset(&pci_priv, 0, sizeof(struct pci_dev_priv)); + ret = pci_arg_parse(argc, argv, &pci_priv, 6, 0); + if (ret < 0) { + pci_help("pci_wr"); + return -1; + } + + if ((fd = open_pci_dev(&pci_priv, 0)) < 0) { + return -1; + } + + if ((ret = fstat(fd, &sb)) == -1) { + fprintf(stderr, "Error: Could not fstat : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if (pci_priv.offset >= sb.st_size) { + fprintf(stderr, "Error: offset is out of range\n"); + close(fd); + return -1; + } + + if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + fprintf(stderr, "Error: Could not mmap : %s or resource is IO\n", strerror(errno)); + close(fd); + return -1; + } + + + printf("\r\n" + "********************** PCI write test **********************\r\n"); + print_arg(&pci_priv, 1); + + while (pci_priv.times--) { + *((volatile unsigned int *)(ptr + pci_priv.offset / sizeof(unsigned int))) = pci_priv.data; + } + printf("Write 0x%08X to offset 0x%08X.\n\n", pci_priv.data, pci_priv.offset); + + printf("\r\n******************** PCI write test End ********************\r\n\r\n"); + munmap(ptr, sb.st_size); + close(fd); + return ret; +} + + +int pci_rd_main(int argc, char **argv) +{ + int ret, fd; + struct pci_dev_priv pci_priv; + unsigned int data; + unsigned int *ptr; + struct stat sb; + + memset(&pci_priv, 0, sizeof(struct pci_dev_priv)); + ret = pci_arg_parse(argc, argv, &pci_priv, 6, 0); + if (ret < 0) { + pci_help("pci_rd"); + return -1; + } + + if ((fd = open_pci_dev(&pci_priv, 0)) < 0) { + return -1; + } + + if ((ret = fstat(fd, &sb)) == -1) { + fprintf(stderr, "Error: Could not fstat : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if (pci_priv.offset >= sb.st_size) { + fprintf(stderr, "Error: offset is out of range\n"); + close(fd); + return -1; + } + + if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + fprintf(stderr, "Error: Could not mmap : %s or resource is IO\n", strerror(errno)); + close(fd); + return -1; + } + + + printf("\r\n" + "********************** PCI read test **********************\r\n"); + print_arg(&pci_priv, 1); + + while (pci_priv.times--) { + data = *((volatile unsigned int *)(ptr + pci_priv.offset / sizeof(unsigned int))); + } + printf("Last Read: Data = 0x%08X\n", data); + + printf("\r\n******************** PCI read test End ********************\r\n\r\n"); + munmap(ptr, sb.st_size); + close(fd); + return ret; +} + + +int pci_cfg_wr_main(int argc, char **argv) +{ + int ret, fd; + struct pci_dev_priv pci_priv; + char buf[16]; + + memset(&pci_priv, 0, sizeof(struct pci_dev_priv)); + ret = pci_arg_parse(argc, argv, &pci_priv, 6, 1); + if (ret < 0) { + pci_cfg_help("pci_cfg_wr"); + return -1; + } + + if ((fd = open_pci_dev(&pci_priv, 1)) < 0) { + return -1; + } + + printf("\r\n" + "********************** PCI config write test **********************\r\n"); + print_arg(&pci_priv, 1); + + while (pci_priv.times--) { + if ((ret = lseek(fd, pci_priv.offset, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek : %s\n", strerror(errno)); + goto error_out; + } + + buf[0] = (pci_priv.data >> 0) & 0xFF; + buf[1] = (pci_priv.data >> 8) & 0xFF; + buf[2] = (pci_priv.data >> 16) & 0xFF; + buf[3] = (pci_priv.data >> 24) & 0xFF; + if ((ret = write(fd, buf, sizeof(unsigned int))) < 0) { + fprintf(stderr, "Error: Could not read file : %s\n", strerror(errno)); + goto error_out; + } + } + printf("Write 0x%08X to offset 0x%08X.\n\n", pci_priv.data, pci_priv.offset); + +error_out: + printf("\r\n******************** PCI config write test End ********************\r\n\r\n"); + close(fd); + return ret; +} + + +int pci_cfg_rd_main(int argc, char **argv) +{ + int ret, fd; + struct pci_dev_priv pci_priv; + unsigned int data; + + memset(&pci_priv, 0, sizeof(struct pci_dev_priv)); + ret = pci_arg_parse(argc, argv, &pci_priv, 5, 1); + if (ret < 0) { + pci_cfg_help("pci_cfg_rd"); + return -1; + } + + if ((fd = open_pci_dev(&pci_priv, 1)) < 0) { + return -1; + } + + printf("\r\n" + "********************** PCI config read test **********************\r\n"); + print_arg(&pci_priv, 1); + + while (pci_priv.times--) { + if ((ret = lseek(fd, pci_priv.offset, SEEK_SET)) < 0) { + fprintf(stderr, "Error: Could not llseek : %s\n", strerror(errno)); + goto error_out; + } + + if ((ret = read(fd, &data, sizeof(unsigned int))) < 0) { + fprintf(stderr, "Error: Could not read file : %s\n", strerror(errno)); + goto error_out; + } + } + printf("Last Read: Data = 0x%08X\n", data); + +error_out: + printf("\r\n******************** PCI config read test End ********************\r\n\r\n"); + close(fd); + return ret; +} + + +int pci_chk_main(int argc, char **argv) +{ + int ret, fd; + struct pci_dev_priv pci_priv; + unsigned int data; + unsigned int *ptr; + struct stat sb; + + memset(&pci_priv, 0, sizeof(struct pci_dev_priv)); + ret = pci_arg_parse(argc, argv, &pci_priv, 6, 0); + if (ret < 0) { + pci_help("pci_wr"); + return -1; + } + + if ((fd = open_pci_dev(&pci_priv, 0)) < 0) { + return -1; + } + + if ((ret = fstat(fd, &sb)) == -1) { + fprintf(stderr, "Error: Could not fstat : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if (pci_priv.offset >= sb.st_size) { + fprintf(stderr, "Error: offset is out of range\n"); + close(fd); + return -1; + } + + if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + fprintf(stderr, "Error: Could not mmap : %s or resource is IO\n", strerror(errno)); + close(fd); + return -1; + } + + + printf("\r\n" + "********************** PCI Check test **********************\r\n"); + print_arg(&pci_priv, 1); + + while (pci_priv.times--) { + *((volatile unsigned int *)(ptr + pci_priv.offset / sizeof(unsigned int))) = pci_priv.data; + data = *((volatile unsigned int *)(ptr + pci_priv.offset / sizeof(unsigned int))); + if (pci_priv.data != data) { + pci_priv.check_test_errors++; + } + } + printf("Check test errors = %u\r\n", pci_priv.check_test_errors); + + printf("\r\n******************** PCI Check test End ********************\r\n\r\n"); + munmap(ptr, sb.st_size); + close(fd); + return ret; +} + + +int pci_dump_main(int argc, char **argv) +{ + int ret, fd, i; + struct pci_dev_priv pci_priv; + unsigned int *ptr; + unsigned char *p; + struct stat sb; + + memset(&pci_priv, 0, sizeof(struct pci_dev_priv)); + ret = pci_arg_parse(argc, argv, &pci_priv, 6, 0); + if (ret < 0) { + pci_help("pci_dump"); + return -1; + } + + if ((fd = open_pci_dev(&pci_priv, 0)) < 0) { + return -1; + } + + if ((ret = fstat(fd, &sb)) == -1) { + fprintf(stderr, "Error: Could not fstat : %s\n", strerror(errno)); + close(fd); + return -1; + } + + if (pci_priv.offset >= sb.st_size) { + fprintf(stderr, "Error: offset is out of range\n"); + close(fd); + return -1; + } + + if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + fprintf(stderr, "Error: Could not mmap : %s or resource is IO\n", strerror(errno)); + close(fd); + return -1; + } + + + printf("\r\n" + "********************** PCI dump test **********************\r\n"); + print_arg(&pci_priv, 1); + + printf(" Address | 0 1 2 3 4 5 6 7 8 9 A B C D E F\r\n"); + while (pci_priv.times--) { + p = (unsigned char *)ptr; + for (i = 0; i < pci_priv.offset; i++, p++) { + if (i % 16 == 0) { + printf("%08X | ", (unsigned int)((unsigned long)p - (unsigned long)ptr)); + } + printf("%02X ", *p); + if ((i + 1) % 16 == 0) { + printf("\r\n"); + } + } + } + + printf("\r\n******************** PCI dump test End ********************\r\n\r\n"); + munmap(ptr, sb.st_size); + close(fd); + return ret; +} diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_test.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_test.c new file mode 100644 index 000000000000..561dfdaaac81 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_test.c @@ -0,0 +1,179 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_test.c + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * HardWare test + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct hw_applet hw_applets[] = { + /* I2C */ + HWTEST_APPLET(i2c_wr, "i2c_wr slave_addr offset data [data_len] [times] [offset_len]"), + HWTEST_APPLET(i2c_rd, "i2c_rd slave_addr offset [data_len] [times] [offset_len]"), + HWTEST_APPLET(i2c_chk, "i2c_chk slave_addr offset data [data_len] [times]"), + HWTEST_APPLET(i2c_reset, "not support"), + HWTEST_APPLET(pca9548_rd, "pca9548 i2c_bus slave_addr offset data [data_len] [times]"), + HWTEST_APPLET(pca9548_wr, "pca9548 i2c_bus slave_addr offset data [data_len] [times]"), + HWTEST_APPLET(rtc_rd, "rtc_rd rtc year month day hour minute second"), + HWTEST_APPLET(rtc_wr, "rtc_wr rtc year month day hour minute second"), + /* NorFlash */ + HWTEST_APPLET(nor_wr, "nor_wr start_addr end_addr data1 data2 [times]"), + HWTEST_APPLET(nor_rd, "nor_rd start_addr end_addr data1 data2 [times]"), + HWTEST_APPLET(nor_chk, "nor_chk start_addr end_addr data1 data2 [times]"), + /* NandFlash */ + HWTEST_APPLET(nand_wr, "nand_wr start_addr end_addr data1 data2 [times]"), + HWTEST_APPLET(nand_rd, "nand_rd start_addr end_addr data1 data2 [times]"), + HWTEST_APPLET(nand_chk, "nand_chk start_addr end_addr data1 data2 [times]"), + /* Dram */ + HWTEST_APPLET(dram_wr, "not support"), + HWTEST_APPLET(dram_rd, "not support"), + HWTEST_APPLET(dram_chk, "not support"), + HWTEST_APPLET(dram_test, "dram_test [simple|complex some|complex all]"), + /* PCI */ + HWTEST_APPLET(pci_wr, "pci_wr bus slot fn bar offset data [times]"), + HWTEST_APPLET(pci_rd, "pci_rd bus slot fn bar offset data [times]"), + HWTEST_APPLET(pci_dump, "pci_dump bus slot fn bar offset data [times]"), + HWTEST_APPLET(pci_cfg_wr, "pci_cfg_wr bus slot fn offset data [times]"), + HWTEST_APPLET(pci_cfg_rd, "pci_cfg_rd bus slot fn offset data [times]"), + HWTEST_APPLET(pci_chk, "pci_chk bus slot fn bar offset data [times]"), + /* USB */ + HWTEST_APPLET(usb_write, "not support"), + HWTEST_APPLET(usb_read, "not support"), + HWTEST_APPLET(usb_check, "not support"), + /* eMMC */ + HWTEST_APPLET(emmc_test, "emmc_test"), + /* MISC */ + HWTEST_APPLET(reload, "not support"), + HWTEST_APPLET(sys_info, "not support"), + HWTEST_APPLET(mem_dump, "not support"), + HWTEST_APPLET(cache_flush, "not support"), + HWTEST_APPLET(reg_wr64, "reg_wr64 reg_addr [reg_data]"), + HWTEST_APPLET(reg_rd64, "reg_rd64 reg_addr [reg_data]"), + HWTEST_APPLET(reg_wr32, "reg_wr32 reg_addr [reg_data]"), + HWTEST_APPLET(reg_rd32, "reg_rd32 reg_addr [reg_data]"), + HWTEST_APPLET(reg_wr16, "reg_wr16 reg_addr [reg_data]"), + HWTEST_APPLET(reg_rd16, "reg_rd16 reg_addr [reg_data]"), + HWTEST_APPLET(reg_wr8, "reg_wr8 reg_addr [reg_data]"), + HWTEST_APPLET(reg_rd8, "reg_rd8 reg_addr [reg_data]"), + HWTEST_APPLET(mdio_rd, "mdio_rd bus_id phy_id reg_addr [reg_data]"), + HWTEST_APPLET(mdio_wr, "mdio_wr bus_id phy_id reg_addr [reg_data]"), + HWTEST_APPLET(lpc_cpld_wr8, "lpc_cpld_wr8 reg_addr [reg_data]"), + HWTEST_APPLET(lpc_cpld_rd8, "lpc_cpld_rd8 reg_addr [reg_data]"), + /* hw help */ + HWTEST_APPLET(hw_help, "help") +}; + +static size_t hw_num_applets = (sizeof(hw_applets) / sizeof(struct hw_applet)); + + +static void error_msg_and_die(const char *s, ...) +{ + va_list p; + + va_start(p, s); + fflush(stdout); + vfprintf(stderr, s, p); + va_end(p); + fputs("\r\n", stderr); + exit(1); +} + + +static int applet_name_compare (const void *x, const void *y) +{ + const char *name = x; + const struct hw_applet *applet = y; + + return strcmp (name, applet->name); +} + + +struct hw_applet *find_applet_by_name (const char *name) +{ + return lfind(name, hw_applets, &hw_num_applets, sizeof(struct hw_applet), + applet_name_compare); +} + + +static void show_usage () +{ + size_t i; + for (i = 0; i < hw_num_applets; i++) { + printf("%-20s\t\t\t%s\r\n", hw_applets[i].name, hw_applets[i].help); + } + exit (0); +} + + +int hw_help_main(int argc, char **argv) +{ + argc = argc; + argv = argv; + show_usage(); + return 0; +} + + +static void run_applet_by_name (const char *name, int argc, char **argv) +{ + struct hw_applet *applet_using; + + if (argc == 0) { + show_usage (); + } + + if(!strncmp(name, "hw_test", 7)) { + run_applet_by_name(argv[1], argc - 1, argv + 1); + } + + applet_using = find_applet_by_name(name); + if(applet_using) { + if(argc == 2 && !strcmp(argv[1], "--help")) { + show_usage (); + } + exit ((*(applet_using->main)) (argc, argv)); + } +} + + +int main(int argc, char **argv) +{ + char *applet_name, *s; + applet_name = argv[0]; + + for (s = applet_name; *s; ) { + if (*(s++) == '/') { + applet_name = s; + } + } + + run_applet_by_name(applet_name, argc, argv); + error_msg_and_die("%s: applet not found", applet_name); + return 0; +} \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_usb.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_usb.c new file mode 100644 index 000000000000..a55d017df2c4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/hw_usb.c @@ -0,0 +1,44 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_usb.c + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * USB HardWare test + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int usb_write_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + + +int usb_read_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} + + +int usb_check_main(int argc, char **argv) +{ + printf("%s, %d, %d, %s\r\n", __FUNCTION__, __LINE__, argc, argv[0]); + return 0; +} diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/fac_common.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/fac_common.h new file mode 100644 index 000000000000..0a5cf83548eb --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/fac_common.h @@ -0,0 +1,44 @@ +/* + * Copyright(C) 2013 Ragile Network. All rights reserved. + */ +/* + * common.h + * Original Author: support@ragilenetworks.com, 2013-9-25 + * + * factroy generial handle of factory test. + */ + +#ifndef _FAC_AC_COMMON_H_ +#define _FAC_AC_COMMON_H_ + +#define FAC_TEST_OK 0 +#define FAC_TEST_FAIL 1 +#define GRTD_LOG_DEBUG 2 +#define GRTD_LOG_ERR 1 +#define GRTD_LOG_NONE 0 +#define FAC_MEM_SIZE_BUF_LEN 1024 /* save the length of the memory size */ +#define FAC_MEM_TEST_SIZE (1024*1024*32) /* memory test size */ +#define FAC_MEM_AUTOTEST_SIZE (1024*1024*2048ULL) /* memory test size */ +#define FAC_MEM_MAX_SIZE (1024*1024*4096ULL) /* memory test size */ +#define FAC_MEM_TEST_PAGESIZE 8192 /* memory test pagesize */ +#define FAC_FILENAME_LEN 128 /* the length of devive name */ +#define FAC_FILE_LINE_LEN 128 /* the length of each line of the file */ +#define FAC_FILE_SIZE_LEN 16 /* the length of the file indicating the size */ +#define GRTD_SDRAM_ECC_ERR 1 /* ECC check error */ +#define GRTD_SDRAM_WR_ERR 2 /* Read and write operation error */ +#define GRTD_SDRAM_GET_MEM_SIZE_ERR 3 /* get memory capacity error */ +#define GRTD_SDRAM_UNKNOW_ERR 4 /* other unknown errors */ + + +extern int platform_fac_dbg; + +#define FAC_LOG_DBG(dbg, fmt, arg...) \ + do { \ + if (dbg <= platform_fac_dbg) { \ + printf("[FACTORY <%s>:<%d>] " fmt, \ + __FUNCTION__, __LINE__, ##arg); \ + } \ + } while (0) + +#endif /* _FAC_AC_COMMON_H_ */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/ft_ddr_test.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/ft_ddr_test.h new file mode 100644 index 000000000000..b83b5e154c71 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/ft_ddr_test.h @@ -0,0 +1,119 @@ +/* + * $Id: ft_ddr_test.h,v 1.0.0.0 2009/08/05 17:37:52 xiezb Exp $ + * Copyright (C)2009-2009 �������. All rights reserved. + */ + +/* + * ft_ddr_test.h + * Original Author: support@ragilenetworks.com, 2009-8-5 + * �ڴ�����㷨���ͷ�ļ� + * + * History + * + */ + +#ifndef __FT_DDR_TEST_H__ +#define __FT_DDR_TEST_H__ + +#include + +#define FT_DDR_SUCCESS 0 +#define FT_DDR_ERR 1 +#define SPINSZ 0x800000 +#define MOD_SZ 20 +#define MAX_MEM_SEGMENTS 32 +#define BLK_SIZE_NUM_MAX 9 +#define BADRAM_MAXPATNS 10 +#define LOW_TEST_ADR 0x00002000 /* Final adrs for test code */ +#define HIGH_TEST_ADR 0x00180000 /* Relocation base address */ +#define USE_DMA +#define TETS_TOTAL_NUMBER 14 + +#define FT_SHOW_PROCESS +#ifdef FT_SHOW_PROCESS +#define FT_DDR_SHOW() do {printf("."); fflush(stdout);}while (0) +#define FT_DDR_SHOW_END() do {printf("\n"); fflush(stdout);}while (0) +#else +#define FT_DDR_SHOW() do {}while (0) +#define FT_DDR_SHOW_END() do {}while (0) +#endif + +typedef struct data_seg_s { + int seq; + ulong start_addr; + ulong end_addr; + ulong size; + int use_dma; +} data_seg_t; + +struct pair { + ulong adr; + ulong mask; +}; + +struct mmap { + ulong pbase_addr; + unsigned int *start; + unsigned int *end; +}; + +struct pmap { + ulong start; + ulong end; +}; + +/* Define common variables accross relocations of memtest86 */ +struct vars { + int test; + int pass; + unsigned long *eadr; + unsigned long exor; + int msg_line; + int ecount; + int ecc_ecount; + int msegs; /* Ҫ���Ե��ڴ������� */ + int testsel; + int scroll_start; + int rdtsc; + int pae; + int pass_ticks; + int total_ticks; + int pptr; + int tptr; + struct pmap pmap[MAX_MEM_SEGMENTS]; + struct mmap map[MAX_MEM_SEGMENTS]; + ulong plim_lower; + ulong plim_upper; + ulong clks_msec; + ulong starth; + ulong startl; + ulong snaph; + ulong snapl; + int printmode; + int numpatn; + struct pair patn [BADRAM_MAXPATNS]; + ulong test_pages; + ulong selected_pages; + ulong reserved_pages; +}; + +struct tseq { + short cache; + short pat; + short iter; + short ticks; + short errors; + char *msg; +}; + +typedef struct ft_ddr_test_interface_s { + int always; /* �����Ƿ���� 0:������ 1:���� */ + int (*ddr_test)(char *desc); + char name[64]; +} ft_ddr_test_interface_t; + +extern void ft_ddr_test_init(void *start, size_t size); +extern ft_ddr_test_interface_t ft_ddr_test_fun[TETS_TOTAL_NUMBER]; + +#endif /* __FT_DDR_TEST_H__ */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/hw_dram.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/hw_dram.h new file mode 100644 index 000000000000..54453c92eede --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_dram/hw_dram.h @@ -0,0 +1,22 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_dram.h + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * Dram HardWare test definitions + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ +#ifndef _HW_DRAM_H +#define _HW_DRAM_H + +extern int dram_wr_main(int argc, char **argv); +extern int dram_rd_main(int argc, char **argv); +extern int dram_chk_main(int argc, char **argv); +extern int dram_test_main(int argc, char **argv); + +#endif /* _HW_DRAM_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_emmc/hw_emmc.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_emmc/hw_emmc.h new file mode 100644 index 000000000000..04c96a0cdd1b --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_emmc/hw_emmc.h @@ -0,0 +1,18 @@ +/* + * $Id:$ + * Copyright(C) 2015 Ragile Network. All rights reserved. + */ +/* + * hw_emmc.c + * Original Author: support@ragilenetworks.com, 2015-06-05 + * + * eMMC test definitions + */ + +#ifndef _HW_EMMC_H +#define _HW_EMMC_H + +extern int emmc_test_main(int argc, char **argv); + +#endif /* _HW_EMMC_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/hw_i2c.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/hw_i2c.h new file mode 100644 index 000000000000..cdf5d3c18c70 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/hw_i2c.h @@ -0,0 +1,40 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_i2c.h + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * i2c HardWare test definitions + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ +#ifndef _HW_I2C_H +#define _HW_I2C_H + +struct i2c_dev_priv { + int i2cbus; + int save_addr; + int offset; + int offset_len; + unsigned char data; + int data_len; + int times; + unsigned int check_test_errors; + unsigned char *buffer; +}; + +#define I2C_MAX_NAME_SIZE 128 + +extern int i2c_wr_main(int argc, char **argv); +extern int i2c_rd_main(int argc, char **argv); +extern int i2c_chk_main(int argc, char **argv); +extern int i2c_reset_main(int argc, char **argv); +extern int pca9548_rd_main(int argc, char **argv); +extern int pca9548_wr_main(int argc, char **argv); +extern int rtc_rd_main(int argc, char **argv); +extern int rtc_wr_main(int argc, char **argv); + +#endif /* _HW_I2C_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c-dev.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c-dev.h new file mode 100644 index 000000000000..3f9285bd960d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c-dev.h @@ -0,0 +1,71 @@ +/* + i2c-dev.h - i2c-bus driver, char device interface + + Copyright (C) 1995-97 Simon G. Vogl + Copyright (C) 1998-99 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef _LINUX_I2C_DEV_H +#define _LINUX_I2C_DEV_H + +#include + +/* /dev/i2c-X ioctl commands. The ioctl's parameter is always an + * unsigned long, except for: + * - I2C_FUNCS, takes pointer to an unsigned long + * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data + * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data + */ +#define I2C_RETRIES 0x0701 /* number of times a device address should + be polled when not acknowledging */ +#define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */ + +/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses + * are NOT supported! (due to code brokenness) + */ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it + is already in use by a driver! */ +#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ + +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ + +#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */ + +#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ +#define I2C_SMBUS 0x0720 /* SMBus transfer */ + + +/* This is the structure as used in the I2C_SMBUS ioctl call */ +struct i2c_smbus_ioctl_data { + __u8 read_write; + __u8 command; + __u32 size; + union i2c_smbus_data *data; +}; + +/* This is the structure as used in the I2C_RDWR ioctl call */ +struct i2c_rdwr_ioctl_data { + struct i2c_msg *msgs; /* pointers to i2c_msgs */ + __u32 nmsgs; /* number of i2c_msgs */ +}; + +#define I2C_RDRW_IOCTL_MAX_MSGS 42 + + +#endif /* _LINUX_I2C_DEV_H */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c.h new file mode 100644 index 000000000000..913f701ed60d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/i2c.h @@ -0,0 +1,742 @@ +/* ------------------------------------------------------------------------- */ +/* */ +/* i2c.h - definitions for the i2c-bus interface */ +/* */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 1995-2000 Simon G. Vogl + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and + Frodo Looijaard */ + +#ifndef _LINUX_I2C_H +#define _LINUX_I2C_H + +#include +#ifdef __KERNEL__ +#include +#include +#include +#include /* for struct device */ +#include /* for completion */ +#include + +extern struct bus_type i2c_bus_type; +extern struct device_type i2c_adapter_type; + +/* --- General options ------------------------------------------------ */ + +struct i2c_msg; +struct i2c_algorithm; +struct i2c_adapter; +struct i2c_client; +struct i2c_driver; +union i2c_smbus_data; +struct i2c_board_info; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +/* + * The master routines are the ones normally used to transmit data to devices + * on a bus (or read from them). Apart from two basic transfer functions to + * transmit one message at a time, a more complex version can be used to + * transmit an arbitrary number of messages without interruption. + */ +extern int i2c_master_send(struct i2c_client *client, const char *buf, + int count); +extern int i2c_master_recv(struct i2c_client *client, char *buf, int count); + +/* Transfer num messages. + */ +extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); + +/* This is the very generalized SMBus access routine. You probably do not + want to use this, though; one of the functions below may be much easier, + and probably just as fast. + Note that we use i2c_adapter here, because you do not need a specific + smbus adapter to call this function. */ +extern s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data); + +/* Now follow the 'nice' access routines. These also document the calling + conventions of i2c_smbus_xfer. */ + +extern s32 i2c_smbus_read_byte(struct i2c_client *client); +extern s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value); +extern s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command); +extern s32 i2c_smbus_write_byte_data(struct i2c_client *client, + u8 command, u8 value); +extern s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command); +extern s32 i2c_smbus_write_word_data(struct i2c_client *client, + u8 command, u16 value); +/* Returns the number of read bytes */ +extern s32 i2c_smbus_read_block_data(struct i2c_client *client, + u8 command, u8 *values); +extern s32 i2c_smbus_write_block_data(struct i2c_client *client, + u8 command, u8 length, const u8 *values); +/* Returns the number of read bytes */ +extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, + u8 command, u8 length, u8 *values); +extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, + u8 command, u8 length, + const u8 *values); +#endif /* I2C */ + +/** + * struct i2c_driver - represent an I2C device driver + * @class: What kind of i2c device we instantiate (for detect) + * @attach_adapter: Callback for bus addition (for legacy drivers) + * @detach_adapter: Callback for bus removal (for legacy drivers) + * @probe: Callback for device binding + * @remove: Callback for device unbinding + * @shutdown: Callback for device shutdown + * @suspend: Callback for device suspend + * @resume: Callback for device resume + * @command: Callback for bus-wide signaling (optional) + * @driver: Device driver model driver + * @id_table: List of I2C devices supported by this driver + * @detect: Callback for device detection + * @address_data: The I2C addresses to probe, ignore or force (for detect) + * @clients: List of detected clients we created (for i2c-core use only) + * + * The driver.owner field should be set to the module owner of this driver. + * The driver.name field should be set to the name of this driver. + * + * For automatic device detection, both @detect and @address_data must + * be defined. @class should also be set, otherwise only devices forced + * with module parameters will be created. The detect function must + * fill at least the name field of the i2c_board_info structure it is + * handed upon successful detection, and possibly also the flags field. + * + * If @detect is missing, the driver will still work fine for enumerated + * devices. Detected devices simply won't be supported. This is expected + * for the many I2C/SMBus devices which can't be detected reliably, and + * the ones which can always be enumerated in practice. + * + * The i2c_client structure which is handed to the @detect callback is + * not a real i2c_client. It is initialized just enough so that you can + * call i2c_smbus_read_byte_data and friends on it. Don't do anything + * else with it. In particular, calling dev_dbg and friends on it is + * not allowed. + */ +struct i2c_driver { + unsigned int class; + + /* Notifies the driver that a new bus has appeared or is about to be + * removed. You should avoid using this if you can, it will probably + * be removed in a near future. + */ + int (*attach_adapter)(struct i2c_adapter *); + int (*detach_adapter)(struct i2c_adapter *); + + /* Standard driver model interfaces */ + int (*probe)(struct i2c_client *, const struct i2c_device_id *); + int (*remove)(struct i2c_client *); + + /* driver model interfaces that don't relate to enumeration */ + void (*shutdown)(struct i2c_client *); + int (*suspend)(struct i2c_client *, pm_message_t mesg); + int (*resume)(struct i2c_client *); + + /* a ioctl like command that can be used to perform specific functions + * with the device. + */ + int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); + + struct device_driver driver; + const struct i2c_device_id *id_table; + + /* Device detection callback for automatic device creation */ + int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *); + const struct i2c_client_address_data *address_data; + struct list_head clients; +}; +#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) + +/** + * struct i2c_client - represent an I2C slave device + * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address; + * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking + * @addr: Address used on the I2C bus connected to the parent adapter. + * @name: Indicates the type of the device, usually a chip name that's + * generic enough to hide second-sourcing and compatible revisions. + * @adapter: manages the bus segment hosting this I2C device + * @driver: device's driver, hence pointer to access routines + * @dev: Driver model device node for the slave. + * @irq: indicates the IRQ generated by this device (if any) + * @detected: member of an i2c_driver.clients list or i2c-core's + * userspace_devices list + * + * An i2c_client identifies a single device (i.e. chip) connected to an + * i2c bus. The behaviour exposed to Linux is defined by the driver + * managing the device. + */ +struct i2c_client { + unsigned short flags; /* div., see below */ + unsigned short addr; /* chip address - NOTE: 7bit */ + /* addresses are stored in the */ + /* _LOWER_ 7 bits */ + char name[I2C_NAME_SIZE]; + struct i2c_adapter *adapter; /* the adapter we sit on */ + struct i2c_driver *driver; /* and our access routines */ + struct device dev; /* the device structure */ + int irq; /* irq issued by device */ + struct list_head detected; +}; +#define to_i2c_client(d) container_of(d, struct i2c_client, dev) + +extern struct i2c_client *i2c_verify_client(struct device *dev); + +static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj) +{ + struct device * const dev = container_of(kobj, struct device, kobj); + return to_i2c_client(dev); +} + +static inline void *i2c_get_clientdata(const struct i2c_client *dev) +{ + return dev_get_drvdata(&dev->dev); +} + +static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) +{ + dev_set_drvdata(&dev->dev, data); +} + +/** + * struct i2c_board_info - template for device creation + * @type: chip type, to initialize i2c_client.name + * @flags: to initialize i2c_client.flags + * @addr: stored in i2c_client.addr + * @platform_data: stored in i2c_client.dev.platform_data + * @archdata: copied into i2c_client.dev.archdata + * @irq: stored in i2c_client.irq + * + * I2C doesn't actually support hardware probing, although controllers and + * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's + * a device at a given address. Drivers commonly need more information than + * that, such as chip type, configuration, associated IRQ, and so on. + * + * i2c_board_info is used to build tables of information listing I2C devices + * that are present. This information is used to grow the driver model tree. + * For mainboards this is done statically using i2c_register_board_info(); + * bus numbers identify adapters that aren't yet available. For add-on boards, + * i2c_new_device() does this dynamically with the adapter already known. + */ +struct i2c_board_info { + char type[I2C_NAME_SIZE]; + unsigned short flags; + unsigned short addr; + void *platform_data; + struct dev_archdata *archdata; + struct device_node *of_node; + int irq; +}; + +/** + * I2C_BOARD_INFO - macro used to list an i2c device and its address + * @dev_type: identifies the device type + * @dev_addr: the device's address on the bus. + * + * This macro initializes essential fields of a struct i2c_board_info, + * declaring what has been provided on a particular board. Optional + * fields (such as associated irq, or device-specific platform_data) + * are provided using conventional syntax. + */ +#define I2C_BOARD_INFO(dev_type, dev_addr) \ + .type = dev_type, .addr = (dev_addr) + + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +/* Add-on boards should register/unregister their devices; e.g. a board + * with integrated I2C, a config eeprom, sensors, and a codec that's + * used in conjunction with the primary hardware. + */ +extern struct i2c_client * +i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); + +/* If you don't know the exact address of an I2C device, use this variant + * instead, which can probe for device presence in a list of possible + * addresses. + */ +extern struct i2c_client * +i2c_new_probed_device(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list); + +/* For devices that use several addresses, use i2c_new_dummy() to make + * client handles for the extra addresses. + */ +extern struct i2c_client * +i2c_new_dummy(struct i2c_adapter *adap, u16 address); + +extern void i2c_unregister_device(struct i2c_client *); +#endif /* I2C */ + +/* Mainboard arch_initcall() code should register all its I2C devices. + * This is done at arch_initcall time, before declaring any i2c adapters. + * Modules for add-on boards must use other calls. + */ +#ifdef CONFIG_I2C_BOARDINFO +extern int +i2c_register_board_info(int busnum, struct i2c_board_info const *info, + unsigned n); +#else +static inline int +i2c_register_board_info(int busnum, struct i2c_board_info const *info, + unsigned n) +{ + return 0; +} +#endif /* I2C_BOARDINFO */ + +/* + * The following structs are for those who like to implement new bus drivers: + * i2c_algorithm is the interface to a class of hardware solutions which can + * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584 + * to name two of the most common. + */ +struct i2c_algorithm { + /* If an adapter algorithm can't do I2C-level access, set master_xfer + to NULL. If an adapter algorithm can do SMBus access, set + smbus_xfer. If set to NULL, the SMBus protocol is simulated + using common I2C messages */ + /* master_xfer should return the number of messages successfully + processed, or a negative value on error */ + int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); + int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data); + + /* To determine what the adapter supports */ + u32 (*functionality) (struct i2c_adapter *); +}; + +/* + * i2c_adapter is the structure used to identify a physical i2c bus along + * with the access algorithms necessary to access it. + */ +struct i2c_adapter { + struct module *owner; + unsigned int id; + unsigned int class; /* classes to allow probing for */ + const struct i2c_algorithm *algo; /* the algorithm to access the bus */ + void *algo_data; + + /* data fields that are valid for all devices */ + u8 level; /* nesting level for lockdep */ + struct mutex bus_lock; + + int timeout; /* in jiffies */ + int retries; + struct device dev; /* the adapter device */ + + int nr; + char name[48]; + struct completion dev_released; +}; +#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) + +static inline void *i2c_get_adapdata(const struct i2c_adapter *dev) +{ + return dev_get_drvdata(&dev->dev); +} + +static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) +{ + dev_set_drvdata(&dev->dev, data); +} + +static inline int i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) +{ + return adapter->dev.parent != NULL + && adapter->dev.parent->bus == &i2c_bus_type + && adapter->dev.parent->type == &i2c_adapter_type; +} + +/* Adapter locking functions, exported for shared pin cases */ +void i2c_lock_adapter(struct i2c_adapter *); +void i2c_unlock_adapter(struct i2c_adapter *); + +/*flags for the client struct: */ +#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ +#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */ + /* Must equal I2C_M_TEN below */ +#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */ + +/* i2c adapter classes (bitmask) */ +#define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ +#define I2C_CLASS_TV_ANALOG (1<<1) /* bttv + friends */ +#define I2C_CLASS_TV_DIGITAL (1<<2) /* dvb cards */ +#define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */ +#define I2C_CLASS_SPD (1<<7) /* SPD EEPROMs and similar */ + +/* i2c_client_address_data is the struct for holding default client + * addresses for a driver and for the parameters supplied on the + * command line + */ +struct i2c_client_address_data { + const unsigned short *normal_i2c; + const unsigned short *probe; + const unsigned short *ignore; + const unsigned short * const *forces; +}; + +/* Internal numbers to terminate lists */ +#define I2C_CLIENT_END 0xfffeU + +/* The numbers to use to set I2C bus address */ +#define ANY_I2C_BUS 0xffff + +/* Construct an I2C_CLIENT_END-terminated array of i2c addresses */ +#define I2C_ADDRS(addr, addrs...) \ + ((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END }) + + +/* ----- functions exported by i2c.o */ + +/* administration... + */ +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +extern int i2c_add_adapter(struct i2c_adapter *); +extern int i2c_del_adapter(struct i2c_adapter *); +extern int i2c_add_numbered_adapter(struct i2c_adapter *); + +extern int i2c_register_driver(struct module *, struct i2c_driver *); +extern void i2c_del_driver(struct i2c_driver *); + +static inline int i2c_add_driver(struct i2c_driver *driver) +{ + return i2c_register_driver(THIS_MODULE, driver); +} + +extern struct i2c_client *i2c_use_client(struct i2c_client *client); +extern void i2c_release_client(struct i2c_client *client); + +/* call the i2c_client->command() of all attached clients with + * the given arguments */ +extern void i2c_clients_command(struct i2c_adapter *adap, + unsigned int cmd, void *arg); + +extern struct i2c_adapter *i2c_get_adapter(int id); +extern void i2c_put_adapter(struct i2c_adapter *adap); + + +/* Return the functionality mask */ +static inline u32 i2c_get_functionality(struct i2c_adapter *adap) +{ + return adap->algo->functionality(adap); +} + +/* Return 1 if adapter supports everything we need, 0 if not. */ +static inline int i2c_check_functionality(struct i2c_adapter *adap, u32 func) +{ + return (func & i2c_get_functionality(adap)) == func; +} + +/* Return the adapter number for a specific adapter */ +static inline int i2c_adapter_id(struct i2c_adapter *adap) +{ + return adap->nr; +} +#endif /* I2C */ +#endif /* __KERNEL__ */ + +/** + * struct i2c_msg - an I2C transaction segment beginning with START + * @addr: Slave address, either seven or ten bits. When this is a ten + * bit address, I2C_M_TEN must be set in @flags and the adapter + * must support I2C_FUNC_10BIT_ADDR. + * @flags: I2C_M_RD is handled by all adapters. No other flags may be + * provided unless the adapter exported the relevant I2C_FUNC_* + * flags through i2c_check_functionality(). + * @len: Number of data bytes in @buf being read from or written to the + * I2C slave address. For read transactions where I2C_M_RECV_LEN + * is set, the caller guarantees that this buffer can hold up to + * 32 bytes in addition to the initial length byte sent by the + * slave (plus, if used, the SMBus PEC); and this value will be + * incremented by the number of block data bytes received. + * @buf: The buffer into which data is read, or from which it's written. + * + * An i2c_msg is the low level representation of one segment of an I2C + * transaction. It is visible to drivers in the @i2c_transfer() procedure, + * to userspace from i2c-dev, and to I2C adapter drivers through the + * @i2c_adapter.@master_xfer() method. + * + * Except when I2C "protocol mangling" is used, all I2C adapters implement + * the standard rules for I2C transactions. Each transaction begins with a + * START. That is followed by the slave address, and a bit encoding read + * versus write. Then follow all the data bytes, possibly including a byte + * with SMBus PEC. The transfer terminates with a NAK, or when all those + * bytes have been transferred and ACKed. If this is the last message in a + * group, it is followed by a STOP. Otherwise it is followed by the next + * @i2c_msg transaction segment, beginning with a (repeated) START. + * + * Alternatively, when the adapter supports I2C_FUNC_PROTOCOL_MANGLING then + * passing certain @flags may have changed those standard protocol behaviors. + * Those flags are only for use with broken/nonconforming slaves, and with + * adapters which are known to support the specific mangling options they + * need (one or more of IGNORE_NAK, NO_RD_ACK, NOSTART, and REV_DIR_ADDR). + */ +struct i2c_msg { + __u16 addr; /* slave address */ + __u16 flags; +#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ +#define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ + __u16 len; /* msg length */ + __u8 *buf; /* pointer to msg data */ +}; + +/* To determine what functionality is present */ + +#define I2C_FUNC_I2C 0x00000001 +#define I2C_FUNC_10BIT_ADDR 0x00000002 +#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_NOSTART etc. */ +#define I2C_FUNC_SMBUS_PEC 0x00000008 +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_QUICK 0x00010000 +#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 +#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 +#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 +#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 +#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 +#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 +#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 +#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 +#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ +#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ + +#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \ + I2C_FUNC_SMBUS_WRITE_BYTE) +#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \ + I2C_FUNC_SMBUS_WRITE_BYTE_DATA) +#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \ + I2C_FUNC_SMBUS_WRITE_WORD_DATA) +#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) +#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) + +#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \ + I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_BYTE_DATA | \ + I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_PROC_CALL | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ + I2C_FUNC_SMBUS_I2C_BLOCK | \ + I2C_FUNC_SMBUS_PEC) + +/* + * Data for SMBus Messages + */ +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ +union i2c_smbus_data { + __u8 byte; + __u16 word; + __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ + /* and one more for user-space compatibility */ +}; + +/* i2c_smbus_xfer read or write markers */ +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +/* SMBus transaction types (size parameter in the above functions) + Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 +#define I2C_SMBUS_PROC_CALL 4 +#define I2C_SMBUS_BLOCK_DATA 5 +#define I2C_SMBUS_I2C_BLOCK_BROKEN 6 +#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ +#define I2C_SMBUS_I2C_BLOCK_DATA 8 + + +#ifdef __KERNEL__ + +/* These defines are used for probing i2c client addresses */ +/* The length of the option lists */ +#define I2C_CLIENT_MAX_OPTS 48 + +/* Default fill of many variables */ +#define I2C_CLIENT_DEFAULTS {I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ + I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END} + +/* I2C_CLIENT_MODULE_PARM creates a module parameter, and puts it in the + module header */ + +#define I2C_CLIENT_MODULE_PARM(var,desc) \ + static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \ + static unsigned int var##_num; \ + module_param_array(var, short, &var##_num, 0); \ + MODULE_PARM_DESC(var, desc) + +#define I2C_CLIENT_MODULE_PARM_FORCE(name) \ +I2C_CLIENT_MODULE_PARM(force_##name, \ + "List of adapter,address pairs which are " \ + "unquestionably assumed to contain a `" \ + # name "' chip") + + +#define I2C_CLIENT_INSMOD_COMMON \ +I2C_CLIENT_MODULE_PARM(probe, "List of adapter,address pairs to scan " \ + "additionally"); \ +I2C_CLIENT_MODULE_PARM(ignore, "List of adapter,address pairs not to " \ + "scan"); \ +static const struct i2c_client_address_data addr_data = { \ + .normal_i2c = normal_i2c, \ + .probe = probe, \ + .ignore = ignore, \ + .forces = forces, \ +} + +#define I2C_CLIENT_FORCE_TEXT \ + "List of adapter,address pairs to boldly assume to be present" + +/* These are the ones you want to use in your own drivers. Pick the one + which matches the number of devices the driver differenciates between. */ +#define I2C_CLIENT_INSMOD \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +static const unsigned short * const forces[] = { force, NULL }; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_1(chip1) \ +enum chips { any_chip, chip1 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, NULL }; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_2(chip1, chip2) \ +enum chips { any_chip, chip1, chip2 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, force_##chip2, NULL }; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_3(chip1, chip2, chip3) \ +enum chips { any_chip, chip1, chip2, chip3 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, force_##chip2, force_##chip3, NULL }; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_4(chip1, chip2, chip3, chip4) \ +enum chips { any_chip, chip1, chip2, chip3, chip4 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, force_##chip2, force_##chip3, \ + force_##chip4, NULL}; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_5(chip1, chip2, chip3, chip4, chip5) \ +enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, NULL }; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_6(chip1, chip2, chip3, chip4, chip5, chip6) \ +enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip6); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, force_##chip6, NULL }; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_7(chip1, chip2, chip3, chip4, chip5, chip6, chip7) \ +enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \ + chip7 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip6); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip7); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, force_##chip6, \ + force_##chip7, NULL }; \ +I2C_CLIENT_INSMOD_COMMON + +#define I2C_CLIENT_INSMOD_8(chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8) \ +enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \ + chip7, chip8 }; \ +I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip6); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip7); \ +I2C_CLIENT_MODULE_PARM_FORCE(chip8); \ +static const unsigned short * const forces[] = { force, \ + force_##chip1, force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, force_##chip6, \ + force_##chip7, force_##chip8, NULL }; \ +I2C_CLIENT_INSMOD_COMMON +#endif /* __KERNEL__ */ +#endif /* _LINUX_I2C_H */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/rtc.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/rtc.h new file mode 100644 index 000000000000..1c2d08d69079 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_i2c/rtc.h @@ -0,0 +1,100 @@ +/* + * Generic RTC interface. + * This version contains the part of the user interface to the Real Time Clock + * service. It is used with both the legacy mc146818 and also EFI + * Struct rtc_time and first 12 ioctl by Paul Gortmaker, 1996 - separated out + * from to this file for 2.4 kernels. + * + * Copyright (C) 1999 Hewlett-Packard Co. + * Copyright (C) 1999 Stephane Eranian + */ +#ifndef _LINUX_RTC_H_ +#define _LINUX_RTC_H_ + +/* + * The struct used to pass data via the following ioctl. Similar to the + * struct tm in , but it needs to be here so that the kernel + * source is self contained, allowing cross-compiles, etc. etc. + */ + +struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +/* + * This data structure is inspired by the EFI (v0.92) wakeup + * alarm API. + */ +struct rtc_wkalrm { + unsigned char enabled; /* 0 = alarm disabled, 1 = alarm enabled */ + unsigned char pending; /* 0 = alarm not pending, 1 = alarm pending */ + struct rtc_time time; /* time the alarm is set to */ +}; + +/* + * Data structure to control PLL correction some better RTC feature + * pll_value is used to get or set current value of correction, + * the rest of the struct is used to query HW capabilities. + * This is modeled after the RTC used in Q40/Q60 computers but + * should be sufficiently flexible for other devices + * + * +ve pll_value means clock will run faster by + * pll_value*pll_posmult/pll_clock + * -ve pll_value means clock will run slower by + * pll_value*pll_negmult/pll_clock + */ + +struct rtc_pll_info { + int pll_ctrl; /* placeholder for fancier control */ + int pll_value; /* get/set correction value */ + int pll_max; /* max +ve (faster) adjustment value */ + int pll_min; /* max -ve (slower) adjustment value */ + int pll_posmult; /* factor for +ve correction */ + int pll_negmult; /* factor for -ve correction */ + long pll_clock; /* base PLL frequency */ +}; + +/* + * ioctl calls that are permitted to the /dev/rtc interface, if + * any of the RTC drivers are enabled. + */ + +#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */ +#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */ +#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ +#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */ +#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */ +#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */ +#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */ +#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */ + +#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */ +#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */ +#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time) /* Read RTC time */ +#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time */ +#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */ +#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */ +#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ +#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ + +#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ +#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ + +#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ +#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ + +/* interrupt flags */ +#define RTC_IRQF 0x80 /* any of the following is active */ +#define RTC_PF 0x40 +#define RTC_AF 0x20 +#define RTC_UF 0x10 + +#endif /* _LINUX_RTC_H_ */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/dram_driver.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/dram_driver.h new file mode 100644 index 000000000000..ed1d20bb2aa8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/dram_driver.h @@ -0,0 +1,32 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * octeon_cpld_drv.h + * Original Author : support@ragilenetworks.com, 2012-07-06 + * + * octeon Dram + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-06 Initial version. + */ + +#ifndef _LINUX_DRAM_DRIVER_H +#define _LINUX_DRAM_DRIVER_H + +#include +typedef unsigned int u32; + +struct mdio_user_info { + u32 c45; + u32 bus_id; + u32 phy_addr; + u32 device; + u32 location; + u32 value; +}; + +#define MDIO_READ _IOR('D', 1, struct mdio_user_info) +#define MDIO_WRITE _IOR('D', 2, struct mdio_user_info) + +#endif diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/hw_misc.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/hw_misc.h new file mode 100644 index 000000000000..4242a5b7540e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_misc/hw_misc.h @@ -0,0 +1,37 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_misc.h + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * MISC HardWare test definitions + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ +#ifndef _HW_MISC_H +#define _HW_MISC_H + +typedef unsigned long long u64; +#define MAX_DATA_SIZE 16 + +extern int reload_main(int argc, char **argv); +extern int sys_info_main(int argc, char **argv); +extern int mem_dump_main(int argc, char **argv); +extern int cache_flush_main(int argc, char **argv); +extern int reg_wr64_main(int argc, char **argv); +extern int reg_rd64_main(int argc, char **argv); +extern int reg_wr32_main(int argc, char **argv); +extern int reg_rd32_main(int argc, char **argv); +extern int reg_wr16_main(int argc, char **argv); +extern int reg_rd16_main(int argc, char **argv); +extern int reg_wr8_main(int argc, char **argv); +extern int reg_rd8_main(int argc, char **argv); +extern int mdio_rd_main(int argc, char **argv); +extern int mdio_wr_main(int argc, char **argv); +extern int lpc_cpld_wr8_main(int argc, char **argv); +extern int lpc_cpld_rd8_main(int argc, char **argv); + +#endif /* _HW_MISC_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/hw_mtdflash.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/hw_mtdflash.h new file mode 100644 index 000000000000..492ac8a98ecd --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/hw_mtdflash.h @@ -0,0 +1,38 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_nandflash.h + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * NandFlash HardWare test definitions + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ +#ifndef _HW_NANDFLASH_H +#define _HW_NANDFLASH_H + +struct mtd_dev_priv { + unsigned int start_addr; + unsigned int end_addr; + unsigned char data1; + unsigned char data2; + int times; + unsigned int check_test_errors; + unsigned char *buffer; +}; + +#define MAX_BUFFER_SIZE 128 +#define NAND_TEST_PARTITION "factory_test1" +#define NOR_TEST_PARTITION "factory_test0" + +extern int nand_wr_main(int argc, char **argv); +extern int nand_rd_main(int argc, char **argv); +extern int nand_chk_main(int argc, char **argv); +extern int nor_wr_main(int argc, char **argv); +extern int nor_rd_main(int argc, char **argv); +extern int nor_chk_main(int argc, char **argv); + +#endif /* _HW_NANDFLASH_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/mtd-abi.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/mtd-abi.h new file mode 100644 index 000000000000..5565326f6c98 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_mtd/mtd-abi.h @@ -0,0 +1,199 @@ +/* + * Portions of MTD ABI definition which are shared by kernel and user space + */ + +#ifndef __MTD_ABI_H__ +#define __MTD_ABI_H__ + +#include + +struct erase_info_user { + __u32 start; + __u32 length; +}; + +struct erase_info_user64 { + __u64 start; + __u64 length; +}; + +struct mtd_oob_buf { + __u32 start; + __u32 length; + unsigned char *ptr; +}; + +struct mtd_oob_buf64 { + __u64 start; + __u32 pad; + __u32 length; + __u64 usr_ptr; +}; + +/** + * struct mtd_write_req - data structure for requesting a write operation + * + * @start: start address + * @len: length of data buffer + * @ooblen: length of OOB buffer + * @usr_data: user-provided data buffer + * @usr_oob: user-provided OOB buffer + * @mode: MTD mode (see "MTD operation modes") + * @padding: reserved, must be set to 0 + * + * This structure supports ioctl(MEMWRITE) operations, allowing data and/or OOB + * writes in various modes. To write to OOB-only, set @usr_data == NULL, and to + * write data-only, set @usr_oob == NULL. However, setting both @usr_data and + * @usr_oob to NULL is not allowed. + */ +struct mtd_write_req { + __u64 start; + __u64 len; + __u64 ooblen; + __u64 usr_data; + __u64 usr_oob; + __u8 mode; + __u8 padding[7]; +}; + +#define MTD_ABSENT 0 +#define MTD_RAM 1 +#define MTD_ROM 2 +#define MTD_NORFLASH 3 +#define MTD_NANDFLASH 4 +#define MTD_DATAFLASH 6 +#define MTD_UBIVOLUME 7 + +#define MTD_WRITEABLE 0x400 /* Device is writeable */ +#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ +#define MTD_NO_ERASE 0x1000 /* No erase necessary */ +#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */ + +// Some common devices / combinations of capabilities +#define MTD_CAP_ROM 0 +#define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE) +#define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE) +#define MTD_CAP_NANDFLASH (MTD_WRITEABLE) + +/* ECC byte placement */ +#define MTD_NANDECC_OFF 0 /* Switch off ECC (Not recommended) */ +#define MTD_NANDECC_PLACE 1 /* Use the given placement in the structure (YAFFS1 legacy mode) */ +#define MTD_NANDECC_AUTOPLACE 2 /* Use the default placement scheme */ +#define MTD_NANDECC_PLACEONLY 3 /* Use the given placement in the structure (Do not store ecc result on read) */ +#define MTD_NANDECC_AUTOPL_USR 4 /* Use the given autoplacement scheme rather than using the default */ + +/* OTP mode selection */ +#define MTD_OTP_OFF 0 +#define MTD_OTP_FACTORY 1 +#define MTD_OTP_USER 2 + +struct mtd_info_user { + __u8 type; + __u32 flags; + __u32 size; /* Total size of the MTD */ + __u32 erasesize; + __u32 writesize; + __u32 oobsize; /* Amount of OOB data per block (e.g. 16) */ + /* The below two fields are obsolete and broken, do not use them + * (TODO: remove at some point) */ + __u32 ecctype; + __u32 eccsize; +}; + +struct region_info_user { + __u32 offset; /* At which this region starts, + * from the beginning of the MTD */ + __u32 erasesize; /* For this region */ + __u32 numblocks; /* Number of blocks in this region */ + __u32 regionindex; +}; + +struct otp_info { + __u32 start; + __u32 length; + __u32 locked; +}; + +#define MEMGETINFO _IOR('M', 1, struct mtd_info_user) +#define MEMERASE _IOW('M', 2, struct erase_info_user) +#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf) +#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf) +#define MEMLOCK _IOW('M', 5, struct erase_info_user) +#define MEMUNLOCK _IOW('M', 6, struct erase_info_user) +#define MEMGETREGIONCOUNT _IOR('M', 7, int) +#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) +#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) +#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) +#define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t) +#define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t) +#define OTPSELECT _IOR('M', 13, int) +#define OTPGETREGIONCOUNT _IOW('M', 14, int) +#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) +#define OTPLOCK _IOR('M', 16, struct otp_info) +#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) +#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) +#define MTDFILEMODE _IO('M', 19) +#define MEMERASE64 _IOW('M', 20, struct erase_info_user64) +#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) +#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) +/* Check if chip is locked (for MTD that supports it) */ +#define MEMISLOCKED _IOR('M', 23, struct erase_info_user) +/* + * Most generic write interface; can write in-band and/or out-of-band in various + * modes (see "struct mtd_write_req") + */ +#define MEMWRITE _IOWR('M', 24, struct mtd_write_req) +/* + * Obsolete legacy interface. Keep it in order not to break userspace + * interfaces + */ +struct nand_oobinfo { + __u32 useecc; + __u32 eccbytes; + __u32 oobfree[8][2]; + __u32 eccpos[32]; +}; + +struct nand_oobfree { + __u32 offset; + __u32 length; +}; + +#define MTD_MAX_OOBFREE_ENTRIES 8 +/* + * ECC layout control structure. Exported to userspace for + * diagnosis and to allow creation of raw images + */ +struct nand_ecclayout { + __u32 eccbytes; + __u32 eccpos[64]; + __u32 oobavail; + struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; +}; + +/** + * struct mtd_ecc_stats - error correction stats + * + * @corrected: number of corrected bits + * @failed: number of uncorrectable errors + * @badblocks: number of bad blocks in this partition + * @bbtblocks: number of blocks reserved for bad block tables + */ +struct mtd_ecc_stats { + __u32 corrected; + __u32 failed; + __u32 badblocks; + __u32 bbtblocks; +}; + +/* + * Read/write file modes for access to MTD + */ +enum mtd_file_modes { + MTD_MODE_NORMAL = MTD_OTP_OFF, + MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY, + MTD_MODE_OTP_USER = MTD_OTP_USER, + MTD_MODE_RAW, +}; + +#endif /* __MTD_ABI_H__ */ diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_pci/hw_pci.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_pci/hw_pci.h new file mode 100644 index 000000000000..728bd88f3ad8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_pci/hw_pci.h @@ -0,0 +1,38 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_pci.h + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * pci/pcie HardWare test definitions + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ +#ifndef _HW_PCI_H +#define _HW_PCI_H + +struct pci_dev_priv { + int pcibus; + int slot; + int fn; + int bar; + int offset; + unsigned int data; + int times; + unsigned int check_test_errors; +}; + +#define PCI_MAX_NAME_SIZE 256 + + +extern int pci_wr_main(int argc, char **argv); +extern int pci_rd_main(int argc, char **argv); +extern int pci_dump_main(int argc, char **argv); +extern int pci_cfg_wr_main(int argc, char **argv); +extern int pci_cfg_rd_main(int argc, char **argv); +extern int pci_chk_main(int argc, char **argv); + +#endif /* _HW_PCI_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_test.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_test.h new file mode 100644 index 000000000000..7a8a5545ec36 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_test.h @@ -0,0 +1,27 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_test.h + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * HardWare test definitions + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ +#ifndef _HW_TEST_H +#define _HW_TEST_H + +struct hw_applet { + const char *name; + const char *help; + int (*main) (int argc, char **argv); +}; + +#define HWTEST_APPLET(a, b) {#a, b, a##_main} + +extern int hw_help_main(int argc, char **argv); + +#endif /* _HW_TEST_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_usb/hw_usb.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_usb/hw_usb.h new file mode 100644 index 000000000000..25938902bf31 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/hw_test/include/hw_usb/hw_usb.h @@ -0,0 +1,21 @@ +/** + * Copyright(C) 2010 Ragile Network. All rights reserved. + */ +/* + * hw_usb.h + * Original Author : support@ragilenetworks.com, 2012-07-26 + * + * USB HardWare test definitions + * + * History + * v1.0 enbo liang(support@ragilenetworks.com) 2012-07-26 Initial version. + */ +#ifndef _HW_USB_H +#define _HW_USB_H + +extern int usb_write_main(int argc, char **argv); +extern int usb_read_main(int argc, char **argv); +extern int usb_check_main(int argc, char **argv); + +#endif /* _HW_USB_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/app/libextphy.so b/platform/centec-arm64/sonic-platform-modules-ragile/common/app/libextphy.so new file mode 100644 index 0000000000000000000000000000000000000000..1ca09deac2582032912a9aefb650480abcdc0834 GIT binary patch literal 632408 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¥eZ4ty91m$?oZ5-Zn^QrgT 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∧GfaXx1drp(GBhCjU6GoJ0Q9coGqNs z&v^p<^}pV&R~oKY^PjJqf8$=dsdW0bv7-;(Hz=HMfE(vx=xhSX+&O!K*kc?W8bm$l ztbM*gl3CZ@zA2{qr``kfBSR$%e#5MQb4E#sz1Ta4w^Y?FYTT^7+DYQg?A1PV=kP66 zk)cCp+{>OFi+$O{N&?Oq1Jj7%`t@$^C6!F~QwMx0VPYH{?0t65SuZuxYoBH<-@EYB z>I@8}6+QFp1gEaZ=hv0!CO&ANXuZ6uA#5eDIRic1iClgCp54=$5LzwY%Kb*U^2I$o z(${2wGs^qNZkYXEJNoX*eHwD#89ICHeMfMX2R}YWQm%Y`k-hb9`zBwW$@kHH=$T*ic{S;ROAsy|RA2y@qT>OKF8yW%=bOk6Bj{&a+T{{r^`dHiw*OZ+Ad1 z-OX)J_tPdFeW#s#p7(*?gPS7Io$a-ODDU*l-snv?bB@7m&N1-6EmCcfcEn}XYx(95 zG-iIA?|UCjdSZF@z_?}eZT20LkuU$hvlKhYH%;ud-MD8TyD+VwY^&9^i~r(Y*!N=> z%b~H9z4_LNm#emT-$UY@qM6AXu5A0kuNp==jaP7Mep4@X8u4@|%Php2AYyMKs^q6Q3biQdboNwPm zIFCm8Exvsj@?*%8@YWXH&V8(t z`2gRC_1CA$7hXi#UHGl)FMR*_OGZp=2K{Cq(j*O^?FOD@PvyJnYJR6e<5u=GM&-YV z=KI9K(!Bc^9>Vm`CG^<|c$FL~xZcTCb^N~m=iZ+`+9IBbKW(jb+lRgfqjb^_&CBV2 zFKH5*D=eRyIS)+q=M%+~-#_?q8+}*sf8mL5h&+ZK_t%+HCg%M8PQla;mF?G)5uEcE`t>!tMi#z4UM@iRT5_W$~&@Aj;eT@Qp=k-R$oir_@q4gxG)>G?mNPa zt=nacQ5BDm;~V(4T6QP2EuRP3ZQo|^WZW*>x8C5XUza>>bM}tQe!KDP=Il9n{uz0$ z?dB{TZ@;87Mmg5XG(o?Gn2W|>&(Vhsz@BStBCIjq2f&G6z3DD}yOwXsC4*M;54qoe zX&v916-we+Q?CosIPQM+9!_xsP?)rx*4SoyQT)IoT>``Fc9t(9^W1r}|Ij_amLDr?36o)zdcb93qV! zUZ)OJ_l0|;N}h1}NqBvpJI*MN9*bU!b_QBLZ8!50dwU-@bT#jrSmu1J zv$r=*87*FWTxswb_WUjJD=e=Fi_sp}@r=Gq%rv^^E$w7I$^#ys=2{~^4p`da@|w)@ zIv78_Ji50}OyRhayh+dR({}?W@f`Mizees`Jilr?_dD?w)t;x)b}Z7W{rhKU1Q++1 z5m;O@Bi1jbG5s}3aD+>&{bCq3A zbCnJxxqg~GIz}?_bYRRueAXePiyJ!d=FhsYM=x}=N4?4Gw^`L+XZ7#<+_}D`Ya7}| z*~MV~2kA`Ak9UQ6dq>Q#lh((4R?(P0z0Lg|x-CVtxhGY=A@3%ht*+YK%N^U?!v_AL zUEuG$&2=gF=snOZM((RfXUhE&o{hdMYb!#3?kM-A25!~gzojeQ*~s4zEl<{EhHi@o z`9*QAvI}!njv?!DJhyn`G2d1PUvsg>jIr4HqVL&^t)fxb&l=|w7o*p;&?rW}lSyaF zw}fXyzB%6@-BG?{N$X?2llu;s5Aho|1EEn2=3b;TF~6GX0`u;Um=BQF$NbgL0P|kx z6@&S2q%$$6y28A-Bj*2WV4m_BVE#>!nE#^y^Nn3${(DEv>kQ0&KLgCS6^VIy0p@eM z!o05|=Iad1ySP7GeVz@CVszsI(wVw3g6B@#;Cmf0PbaOf&yR6m4CZBgm)2Um_@ze9 z$d2RZ1g1xt!rSYc$?Kf$C4b;xv8iJzrx?B>q%-;Y-wj>x)z*=({sv!5isY+s{fa+- z>5MzveU_;MU}!0#&-@qZ5{4cB9nV%*edYldf5NcmyOiIv=Vy0;zw6|1fws`jB|&vfoeL3(aD5=XTPWx^pSdowkXRj^7AeX5ik(eKBp~ zAo?EtCNzq{d>QFX%qQ?{V9xm}WgRh}Pg-AJwsL=%m{YaTC+>3N3=2sue!<>_IzmAv>kk-fi)qfYW=M%mqT1EJTuahoj z*pi>|+*0ThPI0lCKH-Z7)-QI3_0W96=x?D{jC>y@ohjcXJR3TZlW%!P`QC3}KC&~+ zo%)2IZu4$~Zc7n%d%4OtWPJ|LR#$er(#3DuylV~oJGt*nr~gg69sLUQis4~~Fc>@x z`iIYcwqE52IetcV9v%+6|W}#t2!ulE?_#X zJX>A$)$B!<{+WICcMU#1;Qljd6Ye-MdJXi7;bERI7(7hi+2A4HzEXFEJY1;!Ub~k5 zeTF=wrb4e69!?SlgNG2$1`m1dxum|MZ5plo9uKRz{|tGE_JdwAJaiKVgNGdtr+zLRZ~MH`_c?1x zv|n0lNo@K)i#6xphOdSE_IDd+SAO&JHs5J#sOG16Vh8&0qb*PTa8|529jc0sf`?YF$dYy}x#;^y?B64N z*)4E&;A5?0&8;2u*N1$($eoYRrD>Nt?NyoFaEmc7qNk?5k8VN!dEY4y|3sm zhECX9NBS1`*r==DV~sFt@^hFfPq2G}$?`CLlXMAhzlG-dPvP16sD0vf@bFl}30jxj z;H^u(I_+UH*BZxo=dMk0+l~0X9650QJbK`Md+(Q&=VRT19{dSBPF=N~V6TA>=YHsk z_TB#dRpV{>d(Qij6Ybl%e^m0aMjvfm817?jKB13gjXGL3NII9qp7TA!9cruWDVRSU zIqAQ|!p0{WODx;Z6C{si1$)UZDXp%^c|xGXI#=yBY*}Zh&91{PARpejZIZP8MX!ba z>*Gbg+hFyxUSyBQ4yAp!mz8;!^|&=waQ-~XRoWh`?PraH9a=bN^N9BL32|syR_Kgd zJ-Sx;fL`zR(z>YJH%3I?!mlibelLUmk`n6#%UL5nA}T(_!!@5$P7;46LRziok1USe zG23dJB-~}t4K19#xel4^;#*)V!cSE_$sP^rVP>p6&`TKM>s;1goS^TkLE}Z)@-*~V z@4urP^v3XOWt=k0D#^;DCv>|noV)p_&@JWv9+9W3Y69J_Y=Lf#)oniQWoEKG_B({OOpMs&?p}#Tu2T zp*O4_YYe$ho<+Z>m^SqH467TvH&i=T+U@tu*!Pw8Dcf3hgr>YSj(MeZ$>bX z*sFDhF8w{{(!0Hekz|G)EJZt$-- z++pzl2l|XI`G@wQ@NaqbueFg~)&DWn|H0~eH~L`K`Pck9@9nOYa_U@TdwAYEgl{Ac zs~wvj7HjUR-iLQl@3(frw|tl+^yTAxTD{|^XfKJQyCX_s&GKpF%hoct8N0QCk@(*mvHSs z!*J$Gm46ujFQc8)=8u$bBfnVwT`>L#`?-Si)qaC>+K`E9S)~w_|5^@=kU{{Hsk*^YF`#SlAEQsLR~4?idM%)A&7r93P;}`+7&3 z9%R2tnDMLD!L@jMRfbu^=f4HL+2nh$cg&ePj$9JUtfd@bkj&_W%GVxnd0F?u$fjCo z@U6kOVFL&D?a1X^^*!x_VO-aHxU<(NMi~)s z3M)3j;r+9~xYolM2cKlv6-MnzlRgBIaj=a2X{-l69eJ=vt2u~%>bX|WC9VzyV*Tu3 zx}QC)KA5RlZne=*zP$yV3MP-V&1Wmz-+Q*4|5g6*>C-a$PH`>!qm)ne8=_nvAAS3g zwTY;`q>{ac(Byr8cfIxF8+x?evLpD>ElwXTzxg`qF#s*Cw_eD71^t5jw7%6^M2TkHDk+fw8kzOUebK+sFLP8+uQGo zuN!0|quYlqwl)k~9N-t^7vfjKuXIEFsU8mI`0&B@?Aky^_`$ei_UA&G**6ciCoT-P zS+uudaqFG?;D5o*)J?GJ?WG^I&+L3%xa<3uVw2GQ$HcFrcU(K9clMyV>F>vWt)e4e z;rHz;H(oROs*TqS=Kdmn7xOEjUEOB|?8w5#wyFEuH%+1aT|yg}T3_n)1F`9)nHt(| zl78_yel^yh`3d^7=lBf;<0Y4Gyr#w)IzQaknyE7&?_Cx==QVK6 z#s>AJQ|N>AE&>00S%+R@^_(yN>>++NR{!}el>LxHhi|WQUt?9w-{;Uj+QF*-A`6e~ zKZSlxbkrBtSOex`3rSl(e+&8>;J;^`JiX>8(QWZpWA&LI<6gKU3y1Wtv5uUtezL~u zJ3rx+({H}|o*Jw7d@GCLi23aGo4FWzifat@u=iG(W!4E{VaC4>zuP|Z67Rnj=JvS$)``DPo%BsoAqPhm-gw#LOSdXf6<9uq}i)Jh_)=7 zFzdepW8ZDC?4`lP4vnt^ivw$BUpaen4Sl=n(yP@TAh?V%1L$ zW&A{aKFHW_#q*an)dYVyFuv|(3j5b6RR#s_ODI{W6k&8$NqwUvImRw|4YB9`#pWn-hlp0 zWN$zw0Z+svPfUcZ>bb*X)%U~S<)4dHzYc%X;jbkgIQJIDV(H%DrgYG1imwV~(hE43 z!76P^Jb(G*WMX7>Y(T78ew2KcsROL$SYP*9KF!p=RyKW)W;8mom+#9j>ltdgB3a-3CS$oPk|oWIK_-1_`Y~SmF-l+d>FLLL>BlL3 zzfVs;*-JlJ=_@}yeauTAQ~Gc={V1Q`s`YC|!SAykzn4$1Z+?bx>*do+nxz+EzR#X8 z`0g^_IbObVN}3Y}-(9A^&`W=z(&zZ@GJV`jA6NPu-(9Ak=cS*g^hNM}m6!f1r5}@( z(+K25d*B?92l=cw1>8 z%1PoEgh(_uf0@)Wk9`WS=SLo3YGu z*=Nd`AIogxc~N)k$OZIe4|4v%uv-IHC;vj9b>jKeORyUoum#wG9qB&drqGhmnvzx1 znys1VS2tqMWDn-c7=*%O_R8uCdDQP+7DlSmwvu8tU;SYOkNyHiuYq zS*c|!CVke-a{2Z>I+&Ni8L9pe)dI%-(6uE9e92dyi~dj=V?iEp1*vpVtVEG`!wN zxr#B2rEVna4r2*tPpUhXxB{ArId<>ey=l+5Q05k%XIqh`2g)qFds+9Uc4&XGrAPHs z>IcWj{v$K^TY6yFq@DC5!ZVIED)(;qL1sJlGiIzTt8Cg5d4|1hrB^25xh6o|fa@0I zKe(y3S$r=2>g>t;`!B8fYh+7RHS;Hfn}W@Mq5Kb##VI4cTz%5k9@R_QU3rWgF}V7A zjrn;VIpFLYTHwu>$H~a!9^~=m-qlUjcT8)p1`j;huT!TxKWd-34P192<6ndEdhq}a zi@MHyA|9%;JSfiSpOYrtszM*7Z>#a)W`qK^yI0xL7JdTdSX_#fmKP#q%cE$Bix zr!6Nt$ivu+Lk;*O_+!KO2bOTU4>FDbQ7P+P$7vDcPc&iGyLeR`vyr}0e-e#y7i zDxS$$g7kX6hUe-Tmi>w&zuY<=<{(q$$k6k%cib67hOEIDgzuj?+4ZX*LT1|Y7{PZ- zyyEhyx(y?jc!kxR*ugu+j@c6#?{77i(Y9M|xULN!4}Uq>GdR6#L`#pXAM*5+B*Fx~2lRuO2?der(dT4DESG{2z<)#Ro)bUv_Zb zb#2VyrRrCn(OkFcjOM>H@3*8D9b;@m3~IYWyZ0CD$hNvnByJtK+nd`goIlk#UFjA3 z(>Pt{$w)?C`TJx?!o=pJZ>w*!Z0TYJu^<=w7wj!T`W)<@=2Rp7Ec*|Xv!$oU+mtWb z&*-_2_q_d!_EUPU@Sf+^*uT?rfA6`i#(tb<>XCDTnD>2Qe3NWRFcu@uQ=ZcN?2;-s zzI1_Q?YofQyR13d|Dk19K3U?-kF`+tFvf{1sW%7X^3nDl>Lsr(yz}xuGHlPBDxEK& zIkG{ii=cZkzxNr-Ty$57z3A-{do^VbMiz69cGE$7pS3(--^Tkn!;N=ig7$ayZj|wE zd(d94cTwYAJY+B7o#?1sYhTD-#Phlnm1ZzFs#4$PIa$RRPG=3!1~rd+jrT5q{Yi(0 zq`r}RZk~O7+aw29d8s|me_zJ9Kv)x{cBB8UxA!htYG3NV3w!TgF15exzZ>bjYb&*9 z`tPt=4!z25_SybB^4@2KCj}VKIR8!QW>4q8SOA}kYc+lLW5em!Ld-pL=FoZISwuYU z@jl&cWV%EAJNe?>?2}19Xa4n*eHoC~p2$1$I(A^r_v)N_a?(%eZmX^q5i7gs^&Sqb zC~4y-_Oa==_C@~O-F|8f&vU%zw(j=t^nAPbTnPp}6W4RnPcE~6rRRTn&li^2kLda4 zzV81E%j{q3`4R8=?lL>2XX1ZO{>^3fgL>}Y&nv&oUZ>|;@42na{)wKi@t!Mt*!S=( zUK|~m+{6BmvDKVK*KfX=br8M`-shd~#X0 z=+oG3(9k$v`u!pLy=Yc1(P&UzeMFjUU2N`Yzshs%vGtxl4oO`!!m@Yh-RRsq)$Jd7 zS2Kt;6xg0D-MZcm-7LLTz3i>ZJ0q7@^nRyzXXoCDUbE;8DWEs(hEes7 z=lrn2QRUl3EJn8BD&_a|;f9-!u^%gJOW}U@6{M-nVjY-L{y9duH{3ibzr1bz?2D8q zi`C6@o{>kgyJ2`wySi6@tzXHt-E)q#&vf!$=jpE2s0>b>$~*OstZ8w4S|>lT>*{|N z&+1ipfPFmwONN>oSakDH`=YG_9BgwIUDr0t z8vM4~4n(UeHQc8K9<>7p53&C0AC%|w^WFe^P#1WPETA!G-5EKX)KYFM)?P-MIrK$7 zPOZ7HVgv0U?=N7yA)O-1W8dkFJvMB(k2%5MSYmGLE!*jblij`b461L|PXCC$ZyoEw zXw%k(3)8AdEilh`q+OCwD*5fm#KVppv}BYLz=$Wa^j8^^Y^N3-kCnUf6m$*(#4p&v--uV zk+*YJ+=5!mR%~}_V(M7Mb%MRDnRU!Tv3@C~zN~ip5%yE`&GK`UU+*2c{C%KZ7w>1+ zT7B%t`G57P)pp+hm1TBag8#?$u^-`o_rG#CZ&`(1m*&5CANyy8|AqO_I?}GCP2OMl zUpfDU`LCsq{o}&_#_?aA|H6IkI}86ij{g$;cTQjX2mI&rvih&b$-X$4>XJv=R;+^f zeqZ}Lh50Wbe+&6H_O+K3{&y|^rTH)2*Iroo->v*-^|x#L^|P<$zx$E1g%AFqu8gzp z;_A=IyX#`C)S0A9`e%dm%B^`(%=TLTBYv*6Q7QY!tl$2`z5gZm#Lu1gClLd5{9o2i zs9yc`e$p}4^`)d=`exDq^eQf&65n%4(0Y3|{`4!%?X_GvwRzY`>+0XTdXyat`fI?g zk8WvDe=A>|G0~Vd;1n> zH*Sw*=#QJ@7e+QqU$sUj&O42{OITCWim$qs^h)cDw~1v>#TH0zYCp;wAz$FnBR0Ey zy5k7(r?aBOo69q2|G~HT96p&?i?^nG7Tp}M zcjR}6W-e_Ah7vnkyz^jI_Z+ci{mHS+NXu%v)+%qBFfZKJ-pz7i!U@IpVst@B4n4s-W+6>AKzzp<{sTMte#IYKTDp-gwrx%3mTk*e1nHQ z!1(q2XQ9P-<|*c3gZxijU(NWg*@`h2LVeSZY+S@|F+b*^H-?+)Gm^<7;$*=;CU)FQ ze}ZhUx1O)fELmbnb`5JoR)+D}#wEn3Ymmbo-R{8+*J};r$-$Jj4^mefhT^`C<%o_;neb7fg zcT|Hh5*}<1o)>A;f5WVhGrzkU9E{a=Tma9j8QWHZc|UwVM!p{r(~4g@c+J8qC*Vg6 zObPD-{PD)S=~JF^eM-$$R4^V0gRP}oZtl@+<7$^$+iR0=24@+ozO+VCb*472^@(w3 zEbWfJ^nXPEb5>!1Hl?;$IR4a}m*yRf^}h5C<b#H$lJ{Mw4z63uwO`yuBD=*`GuD_lNztRRL|!rag6^vPcnUHCl$8(FrvbPZ+Ld*{uYJS-5HuUNwJ z-lc02Grd>{&+!++O~F;A&0+GmzJ_^5nY+KpJx{O1J5Mj@eJ?5${WW!p?b^h7zbWiM z_Pd6AsJjopG@)rXy4i}KyNmBBIeruC_mIV7I{$88s5Dh*3$$KY-!<3&Ny|NNlsTge zW8;j4O$}Qu|Ej?j2dKlE(b#+BnheI8+h@@?1g4+luBDc*UlHAoPRkZ1v48iGhFE!X zc%<{Jd8mwq?PV>+)%QU|=k#&bxHDg!=KGAoD&1*iou<}uS^8e1vyaHdMSqn&r?qgc zHEp)PyWhz?%PuEJ*~yK>t)nONr+ON1sld%dMAM zuU=X{YM;=#9G`Z4;G7&yeJpi+5?3Ds&Y5|fK_Aukz1(kmg`)kDWmxeQbS6T*jbcsL zgPfVC^DOt^zq#M_@^x~cbM|9SC%fhAr1Sl*oKCi&lRB?)IJ5)kV+4KFnzWthQ2QuX zmzH|^I5n$}8mCl5kAv?d_U~r?--#|x9T|u&4O-24ZNMu}?a)Gx-2DkTJ<5GoNBjLs zJLP`|kxch>ei1rANFG=yl<4Ypi6telrIbID;VhL^}bLyvea}>7$gWEcv$4ZZjZ&SvG@rhU7~m)E6FTzh)^(0oGrrp``d+BJ(?7iruX{LO zw7te^{!nscKfzAg<|u36nZs$H^uPThBcG{yqlWc!;g_mdLw9b(3Z402!kgx7sGhUMz^wM(?@6OdG^2A=-L3+cJ2$6I69`WLSdQy z_`#nqk#FnqoL8P}OY^?%m+B7&Y*ZFQch)kz2?oCFmn!_OpO0rBdY0w4KO0b^6(AK;_L9;!T%5NA#;uCy2kfZA-?cI@p*dm@5;|? z@14lc8Gn_eehj8OogSIhY5WWKd!RX48Gc1kI$aco=;A^Qd?R%ldREY`XwQe z-KWl*-4@~8)8X{D&KQpM-0B;#)iZDQYy$haQtA`l#}3Qq2*qNI{oQ?Q`-q8kumz62 z-s<=RrtK-f6&-l^xUj(nuKGj4m9qgFYr5@A{c|9-niyRY`8aWe@d4IZTbZTA>Q=K} zYW(85<^*H!z`{D#NDY|3%k$f_cF56PuYW|Y7IL+imq`Y#N%((`9MxY}xVkWL=h>{S zVmvH=R_D@cyb@=RTZI15V!ZOymGR9}`L4~DE5pRC-F{iV?KAfh&tOdU-}K$;W2nK9EuRKK#po8Toj@7lJR#4!edUwoYe4SbqR3_gZ+$%otL*1|{3<0HZP9OwL8@XiKj zdiYD(eUb7je2nVff9zp=!@-z4kJs-L{zSi-#<%iqfMh7%6vMdf-cJVU*^g&@k7rYt zd>X!v-wZ8uHrs!M(BrKnWv4&HfI+S1d3i05j-D0eLwkG=e=J&aYp0Uh%#Ep^~GvTx0hc~oPzi!NU z!2Hu0GfD=xl15kQ&Wo%0PK;MK^q0>1aK$KzldW3t4Pq_$UoWGlONkqW?+;|Ct4(3j z(GR*Y1S58-{??5*dG!pPJIEJ5xvn{k-#2$xZ+i}T6LE_*H#avd!_Rp@eg4Uz=A;`7 zZ7}!$wRrKXp+Ed&&>gGu>)y8`L?bdK)I*$cLmbT7mtJDA4xaWjmGwB-vsM22&YC-y zZVumGVh7oSIO|@%NyOTTpcQD+cU?-o{VsLk%c`gH!w;)YvhQUN^8orzOQU7=TEae# zv(S5|EcUyz?;~?FGTBKQ*~1v)49U@1w@mEe@3e>TfoU(@%sMf(cuYZ`t@nMwAJ zQD*90VvEAz$X3sWT?>Mo->_LP-_|2>|s>-lokqyJexM1ABt$W?Xb z@apN}CCKS*bmJnfVf;9Me5E$%&#$Dx`wV$^b+6lCL09EiCBY&2cFXPCe4GJfXDtp4 zdC0-*emhU&l(st7CxuF=GmT~Zag)V)10iHwnX1HwQuh-SbM<{9e;oMnqTf3{(CnLH zcSu*1ezoM(J<)Ix_@pl}V&!>zi&*bH5nYn(k0dSY`crXY#5Gf_cglzZDQ-L(y?h_r zy5w(x4aq)rnQsNHOuWKUT)JVN>|vFqZzG_K6{+-yfcr_XT+a`Pj-YI8^Y9)R*i+FYdtgYBP?Lof_{EQcv-pv@0WR1mt}SsBY80ahtH^d zQkAu`XdFenw`0V+nEa0N)QS)t(dA2Pvz?_AvGuU_BNA zb4+O;Vh)HpBIcV)mul{yJoNz2x_+DMf@e<4oX>e0gX6KW*J5`D5!Zj2xvUocdy_oG zeekEOjehKB-EG6{EzgW*erS+gSDI+J9a|>8UUOyK|KmkdSu0sf46cs&XFcn{r)_{Q z=S-fTIptcJH=+3kvAjK@LDBWldkT8OQxCnVloh#Tkljyh6FiS#)3g`edH=*9dmS`( z{?47>OqaO)T;Pt|c1KdgPp=ZARht^DWnK{foO1o6{bFpsjiC zcJ{CB>J_;DX2#v@U*tQ7p_DamPMiPjMfQkS6BnpX_X@IC%-XlBd$3yPX)sTk3DH*G zZPhn`2BiK1AG*#UO^W;7$WijFMV1lP2-V&?%$7_o+Rb-dnXX!ntZL6<{qQ#Q>cC*T zm3h=>>B}@P1Fh)Ci|T17(`YBBZh#-BecXba>&UZ0awgwy@~FNd7gpJ4d2;>-c1rsx zSzoOF(eZKPmOIzS_-n!k4(5u~&mGJasq?{nqlftw5A&OSr(Q42Z}ggaz3{hyeNV62 z>elYH)nRzRZ*{P@_F~-!IQD4o893hH{EuZv;Af9u+*vuqe)m|b`Asm0XYu<3_rQE z*MDk#V`B^J`zuC$f9_D~dzDw;Eko_P0f~k)i>Yt&`1M^+9;d#C9%XC(RXTOeLFzlk zcT)ZO9%s~d;NPilaCBDRtzdHMJAG7#`X10(eM6_y`kr!hUVZO|?p@^f>sx(nXMLjo zUa=tme|)%R-TUvtV+W83jt3AAXoB638Ez>gH$^RYJ z0Q977#&z~kgqS_&lgXc)&YFZ_AG0T=U$-^%pEJwOv8wBdNtDdwiv1|LmMb=-*Hu<^ z$wKZ~15t7zSJqdQTw+zTw!yBgiP~K?HyoyoY zD8}!s{b|zLhi+O|z*u9XXq{70JyNu1R#exr)**rqJuAlE4B|;s;VB8-2-1wDj%WSno^KauTFd$>^|z95p?@mhe#sZv zpG&-ECS?r7@3Bskk2^56`eb*#PrM~5?_Sght14R_MsULk#pFmP`X8`B!9VDpL{8gF%n zpLn;}2F3Ks;Ol3!P3e8_v;xC|O~ zq<2rT z&-z;N#JWw<*1L!`+`hRqvEv)Ok9F5Kw98X^cFNu~+@8mKjVt3JYeF{9yb<;;(#+<+ zWU29f%t+_`#VVu3c)xd~y^i$f@jlFZm7)Aj8OdYpvw4rLx>_t4@0r^K&4^AE6qs8EJ>nX%i;-l;h=*(K=Hy&9jmH=PP+xRa} z?yg_AD)PiA`vgz!FA-C*N#7m{;BUEO66p`|my}~;;-_XJ*sB1%&F&eip4%-}J#uJC z(@y4bBI!!b1(~}!P}(->y;hC)%Tu=){9MSr{3u_qt{}g#H$o%g=~x2Z&^^cZ(AqBf zBJwq?DWh%q8za7uXi)!18|vSm*a3cWv-+?)()xNN{~~htXs3@IN%{{-FP*v<-V|rh zIY-FK=`Ut;^~W#p?C7W;U#+7Kw9Za3Nq;?Ahe?CYlFmuPdSMf*U?wra7q+tw)Z^X1zNjv>`zK?Qbk)jMi;~>hYrm-8bk=huJ@{ zCQ9e-pv}jTRh)W|&Qi{*NDJeH=f>E*sXuIaCLx>3d#m?YTjTwIA=eMqhwKk2hxWQr zX#@Oqj`y$w;(3Wu|qoVOgXz04O zfR@JJg|yxzW+Gm#)yF#Y>P}5G{1$rE`0_Q~t*hhxSUU!-%^uC~aqS?#LGHN2l%K}f zSsAt*Z?~SFX!t2~FD(5@!^7}A+LO^S@Fe-{f|vV!8ND2}$EjVx{|@>c#T+#zkWBrw z%3lvw<#*(|?^t_;m*;8nY$uOwgmi5Uv7pGc#5!AInKo?4&SghzXvIb}Vk364pH}-h z^gZCuqa*5T^u5^O_&gV}S1F9o6B}wZ4WApEtT~G%p{n_A{H`Lkz>~?e0y!u9btdN_ zuAKXQ-jVaNGuhjVJS5xM9-Z+8bgWM4xN^0Q8|Tp33Y~LBr!i!og#NcVIxsM*{#3Lp zkF+M7?$IB@wL{(Y$*()V&g#x`+Vv`H?g@4^^lOo4oVMQ1nJwuxf$JsLT_ZyFEUn)z zt5sZC>wAg+FfT~|@8YOPMZK~Q-1f;`YdpPvbM4gY%Ch#ImeDycdbW1U2V{)L{Se|Lk#p)ZJ2?|Z zb-o<@vd_|?Hf*%7M{_Adx|G!;&S|zOPx!{8M~VkHw9{@mI**Zd=FpLi7ag^C*^(9L zVubUKccbeGXe6**!=X_}o{u`w-{sVu%2nRT*FJAAAdf}4ipShwl;dL+&TVF%mE-Ko zy*y>)SwbFR>0o=POQ(#M6Ku^l2-g90<&W%jdWw3Ho~-72k5@l2FvPHlrmYBr(XkWp z6J5Il%}23cKMJ~b!a4~%aV9Zt)d_Z8_3#+HG*;CkqF`T(f>SMb_f0yPQpo{u3ULk*ga|m@N);jhr zh@V?MzAi1`i}{hx`Fd@VYyZBKXt)u+(si-S#fs%q{tc9G{eAIE7lA?LBa0@L9oHFn zoKyOCj)m0@juGc18ZH(Nc=@tNQpIMP=#m5`uVR`HOpWL+)EE-q0u5sGWb}K+%iJw5f->mZG zhpBIK;$Jhz+oxhzmi?bZLp^%9i+$Q9V3U2n8hq+omh<0-fv(wZvIbrc!Wb`Zlw&hDdAIJZiOd0GTRBS zTE8P4DqA?zA8sSPaHtJs?Zo1V_E*91I_dSkux-_&zYf;PC)u+|7gL>r^DNS@r5?ug z)SSW4Xe&GfdIz0zGi&hi6q}gZgR_sRi$IS`+>xN;>kZ?~x1~BSj65amN#06ds7$o|c7@|d524Q-8m(izyY5!^KlML)r*vA2@8|1D`klX~y;v(9TOM)dGCR_?l#cwn zk6zhe(*2PBWH&M@EboAqzOcN1c>T{xuZ}L_`dv?tcY!19>CFL8Z+3ZlWA&TN-rlN| z>TB!Sd^4N+l74@Sy1Ey=DaqDXRq6nFwvlERx}$n~YeqqxeQmORfP8Pw(Ef>7=EulJ zded3`jik*w_4jhM{ZI0!{%q2J(uFOZ>!-I)v0J_LD@Y&m>U$+;DOqPtan_%44%*um z&-j6En=4hD8ycNU{j4|Y^*&^#_a)(*8$zm6>RobOBiU2u`pc=X}w}oooPG7m| zi%$F2Icu%Zev@{XAoi!eEk@s>{zd&q0KY}gi)LY8=~t|g#8S{9^(i;>#UD~kPUjE6 zLmC|#!TO=s+1Iw~UDZWZ^mX>ON#5*5v0opK4SCpV-u=B#?n187)`w%wNql+j{eITL zKRERxu7)4DU3@0-#bi6>i%FlwgFiO-4sAeobh&KSRW)|qj6}mGcxgiqo;c7x=w|rC z7H4FOr2mdy(;vuY?e=B*_b=L~AXCZfztNZ9p`S{xdX&ABjXgm7k^JQ+L|&+I{Hhhu zsHeQ+y!!Z0^2#TRGj2|E_FWi#OZN&i$EQqxsqvC?UP|{pdTcsmJ(Awqw@o~M&*S+L zuJ?L%w)?KHj7@;!js3KL#zc$-9lrN~BgPo*4RE}PT%9_6&9Y?!T4(0;Q1jipT3y*o z?mwholB{E%oWJgsSyP0ZRbHoZP6zBd&Pvn%VbzOd#d+zD52g7K$yxIuyTRr64^uV1 zoXqzqq-XHA3|Z;i9m!bvO*t#ABj+i>oSeP#cJ{hptkxBXx9`w)HI|MshL$`hdAyYw zyzLosf&5=bk1YH~V%v^9-|*!5p(9UsoSBWGOb)p*l=EqGjxJS2$D&IF_F>D!*;f2*$Ho<3T$cwkq(>mOZSuP@hdZQ(J0DwNGGP z3O{r49T#z3fNWl2t?zz+OW7(3SLu^ykrB z|5^2Rn)6k+u-{Al=hE(G|2brSfd6)qzOes1O?uoHm9EpCS2PY=Epv&Vc)sr)RCC`-r-eewL6XUpGtblRe#h4P1(U5mRaS*+)*i z$eCYhUzUsYX^jDg?e^FBjXk-n{~~rweQ7Pi2aN%nwFs;B&#;<*i!N$iRoIDfR;0e~ z@KlkS#nqp8mVU;m%LIIBe$e4-2EHRYcB=TQ>~7a%Yt~(QioNWFM8jhEV$XMZD`}SV ztT^C${(BGJPBZ*MM<=iCZkNE!c;n#Z-P$3!*zv+tJ=V&{KBPnBOJmd z9FgP7IHQ2`YAAEWiHU{_p+gLl*i-)c2IS?$oPe-@|0Ma<&ZPhF{g-4(TWOskIlA#x#Z-~w#_{BFW39oI z+KKe>HOg`2S&@3$!C#TO%fPR4gk5@Q%2PONH|FHIY%=pn&~oLOi-Y=l*g>Ak3ytOE zlRQuMi0;Jxtdam>vweGTnn-3R{aISM@Ez9-?`8@5{%lvU4(q2zI>M(^8LEUOO3(HLFF6f40BIk zx1OA6_{yQkS9y`|Hu6cn(kIDkxhG%wtEYQ-h8TEuxozFiSIJd+w*dXqx(Vs29)mX`qtK5M=4oBI#*WC!wH_LpPm-<|A=j+levUl8 z-VXBkclBf)OJK)bVN7nSNy!M(_hw6j>^2;l}-O<=sW&A`F4}O5&lKz1F+STHrs#VpHSAm zNLfGoZSqP7zmH60JG1T2%kQ^8(NLZ?eCEiMBeVLk4Z52D5{<>sxEmV9=*j!&hodXU zTA4G*-{SSl;~m)yOqCk)SGl4e?o3ZM<@BVH81M*a6}HFyoB`RTjwnC$=PG`Tj{MZ) z<#c$_{5(GUMD@!@c(`6)`N>^(G3L`;-yXNl_NBoVXWeGDe@1p;Xi5iap)Vb9Z1KGQ zc1STn$4?%ZYJ-+&|ADLTgLpI@J=6Hvrzt%UEk_Tqhfd!Ft!(>F4zPDacZ=#!b?5i{ zC&F8v1OrCxR`o=IIF=hgLp;_FNI!-oB} zJzR|ju1~eU&^PVxdg6E4`sqE;UJTX__Ln>z?C-pRSsC9CjUYH3``fjj>-uM&pZl$> zdYdS9Nx5_!2IE6d&FeV9B&`ng#@Y&dy*eeLDo zuSos(Ex9&(P+YOf zm(Ak4f`=kkb zJxsj~OrL67p>5jMx;ch?<5l)Cl+|HeMjqc5WXEMsRAuE`4~?IZ&l#5$>)Yb5$hSR; zd}+_O?dI?^DD~&>bhHVb`nJ1sGH#v7zDnA2r@rmM{1#~JCNJ{dE?Hmi$$AK~cGg*T zKWnV^61}>D{d}H(%f~q<{1+JIgZ{$6>iHb2R99(ZJnZ-!l;gB{d`9^m>nCM>+wHO& z*5)DhGvJqRo98=_&yhX(Jl|nEahT>v`OvKV?}yfz9`65T9M%GjM?HKiy1-|S*L{4Z zPt*!c&z^0!tfTC;U`us{E$7#4k6dz87T0cQNT2>nzRvs__6DaE|9F3dm01IQ;{6le zZFKilEOYQX`zlt=UUxn|>(w8}Mtewd^Q$M~`lW4dax~!q( z+r)}xXm5oV7a4&syDZoL){)PTGnJ6f*N6AXAE!PQkC7jn?tTXPP@WpZduI(O>+Iim zFb_;!?zJ zOE!EkBIt}eIr}TM>!pC58E<7KKqKt=nMXN1R;2z(d+>d2$tpn^33Oig{dk}FsZHnV zV?Araj)0chC=+Mp9mbhTOP>2lr?z+}X+?K3*tO?0ean}a`v}^*1_bRZ_|I*R6{$a= zH~Yck%>Nm<_AFw&;Kd@7jCuSqfZ`~^_U5;V|50Y1%oh){8(FvB>c%y5`r@xA9IrLX z?w*`o&^cqn z#QIzOIWWc{qA%RC!NM*47VD`;A@f$~kHn5>9(2Gke3|vk zoX6*^+empbTWrc~$l1C1B4aG(#PleWMeEKOOl2=)eU@Y=Os>8Tw|_`^k4R4oWTWx4 z<{dOYwi~RP9~(`4_ZW@o$RA-%cNOvx&rdK$bacIdh9h6vw$}%3&&Uq09-fu)a`5zk z#!nqxanD;wvJO_?snE5Bb7W)ao(2Ef=kLp5o+pQsJvnF&yfno8DD{v)|K7L-Id}Kw zBE5Q${Dq_S4Cao(DH*69EY@}V_0WJUrU?u6d$w0b#FVwCpQ5jF(ng;ld5dPJI(q*I zdl}`P41L;C|MNSMx37!7tRmLPoSew}BzaZlY-H`kD+*+tS6`&>P+#@O*uR8EC1rOJ zr^wk9Kc40F`C;<;eSQx|E`w74wY;M}>7>uc?sw1H_YurrXJ|`@+~-4Mq&xTR^!bZD zSsaZl%szh-@6A5{Z(vlPztO;Y&_17X%s#)BGV|ICeg5yk-=WVZpI?7n_4%5+|B{D$ zA7d%?`M>h;t?U9{i=kgmpHDevpFg4@zt3L>whn#1kFAS7e z8~Nt+Vo++|&Awh#q~51rywJlMHL#j`Vah$*_uvE8Ql9i7yMBYdXW2~F!BOrGwP`c{ zL|R`bI_qDSlkX26-mii8De|A_;VLn3z2VN=tP(!)mNaxCYjaF&)U#vT*(cQWR3 z{93R)=wVvO^@sj?oC{*jlkicJq-70_yB-I+zP~yO{jG(z`aFxhG+XH7TPfoX@WqgU zzpf+sA!pJ;tCF?ftG)K){J(H&W^-`!8lAiHjF-n*r(DlE<>?bA>-|37OI9~|_|EZU zrhZyH#EI_;hvX$3&YB%C3Cq?CoH*BZ>xnV;H=y$t{`6N%}QTlC^k@aIL$J%?zvw^hjTeTP6o&VKb&IQP0{~Vna7TO?x z+nLkD=U(uQ9(*gR8~aq)V?+B)aCTT2y{n=vXrGQL$CfH_u*sBt^IcMZoCrYh} ztd&`HAwRxDvE!nTre!LhJ&iq$oFO!$KGSlOwdTP3AZOCYCr?E7$SqorpS7#I_5~yw z)W=EB6YLFOT?unILsKIhSr1LUPkP1}+K;o!B2Sq0bXt27mT$rwQg-dZdt;rsl-4EM z^En_j02#c(w@hB=%=9gM%WXAS#Zw|^RSPG5Hv2&E~07*3p|m`qVI&y*z^n`|+~g~s@?F~x}+Dk=ty!v@I)!9iJ3(JgoFzN2D^ii(Cw zMT?4xii(Pox~Zs0$*8EP$hhyDx>r##cHsSezOMI=^FD9RVI1@G$Ct;>p66Vz*Xz1o z*LA(F>wR7CALm?p?YWdI_iatd>sI4_J1ws%y^Ck=e*Z9gfJcmbyu|O*)UBNIq+R6u zi;a7|E<5p8@{r$s8iq2)q#kQHuhL9^HWM@GN)Z@3z2kJLj zq#pcs^OI%_SohLQQ{UahKrV47*H>w$zKsRf9zTRX(q88fH*!Cn+$SbBa@_Tjw{64T zP1*Fm;rPASh;M%OSn^wOQ=ecB%i6VvXN$9_C*NIhtB2<&E@BL6jGM>Seu;5&k-GjN z>2mKU_r+eT_3o1ISX0k?NT0HIrX4RkG5rzkE1x#oMexdEp7^=Yz7oZQXp_OI_EtH1B(owvj&kEzcHQQMr+RyGUJclIs{!-iOVyydm1Z zl=*v?dF;y}zwC!uM^j&k9VuHomU8^x$p2aL`aS76$mRYOX~Si0H=T0)T-xq)=*s=7 z(hqV!owVz;>{n(sACJc0L-bPxWl0`7c}rVAOI!aKJL2dC``m!F*R!4-d*0aZ$y{&E z@p7Nj^|ZOHJ!O8sf%h-HeW&_P7RGkpKZ!RP-}Nt?!*T5*;;#9HUofWRUMR*u+C0Yt zncMcLHcB{g8I*Gz(hpPk)x|iId!eK)WSmL6yw_~67V4mlZaH55-sXKb8u59-OW#(% z8}znk`A%>-ACZPXa-CqS%74R&weT@>P8a{Eu=;KX+1EJdPAM;I?409TjQI=`Wq2s# zO39C79P@=d@BBhm!tPUVr|o3CagQzcA8t5tky+NvdjiKaE3Pux$BO@sV;c3k=vpaD z#-28pdOZ7m{FVS^g*&Fn+$;AT%6(qahtj_rldrSa8eV*r>tE7-Z@{;&(yv$3=W-mB z`MI33WDh!wp0f3(9)BnLL+D?DzI?ZY%n70|<%s_KuovBb$9`kM*5f(&Sc^?FHm}7- zu0u_6e(}Y3vv(yHjPbSM#EZ0nw8_WJwy=*?#J#h&10$floh}JxHkPpz4JU>T`!@OBp}*osGj(XkUY^TmUDWrjZ>Jq^A)kNnJLk-sCp6km z>c3y*z2U?rDD}V8QGdP{?u#{~2iO17koAA=KRN$LxpF_K?D5J}zLw9I@?A;GeeTAF zIxC;QWBPmupJku_CVYO!6+GL*{49CiNq!rNmyPqer|5@MnO7SAU!}_7e!6Dkxqx-m znb#z)G5T-tb=ntSepvg;&FDz~z5KAOxwwwc{jk!P?mm3@{muK%#}8F@4bO6!WnXWV z&GAag?n*MsjyB7F$tt_ZDEl&ECvl@u_7%&@zQ`<_XE`15Q_eFlCmE+w*B#_1eKTwF z8_+uE=HXafO8G%!lYFM$%o>?Ey6OYmqcoHzvD&9KZa*&P|IbtXvf;#pncoR$&9Oto z$OM};|_&R?;rKru zjynD(`pUm{?eSCDQOBcVGe7ye^VffJ4Zmmct@S*c{hRDlQ5#rSmF}D$Id5%lw z200I=(f332JIAQ6m}6GvZ*||X)JfLe+Vl;oUfCaF{ZGA=-x)j3>?hBT;%D8|Q{qSB ziDPH*Gv`Vz?H#6{w}tRClV|T%^bpe#<=uR3uD@vV|vMdCY$vpF>)JwmUYZC zGR|JBeBN+knq#Bfzb@;WW*KM9e^%XPP4GwN16k8Z9LZRd@%23U|BYvR*lVcyS>|M! z&x4M~83^Tb`uJ*-VmNgK#;q*DqjyHf`Ra+UJrJZ-v&JA@XL|T1Vy!tB)The>FcO+<5#L$ELqK{IL33%5Oo> zF5h?Kaq%Y(ALJR!P=0qarbGF?*5P+Ie#;;)RYj0pVxJ^5RH-;3XW3FG%PdTzge zhrZKqITvWPcQoTv{I+dq>zB~aq+jKHj7~W>oBqZ@>-nS$-+ zXY7^2&is6p!QR`AeD?3YZO8?)3w9jLAd?d)|8^>x=(R~?X7xv#w5`@oj^8v1%!erEiMPDy!XRc*;(Z&gjn zLv>ZY3JDEYdR;}CS4GUSe99Z@eI;lc_M+#hs`ngesIFeMzR_c@03hZh4(cA{e?sjH zgv-O)50{q$XU3xUeoS8^1u-p;>*h0)o^6TruyV-Jf8fj zBNZyE3ZGFIX_)&qdG8l-EyGP>o)NW!u|?}qaZhUFrp6uWe`Az|(Kl)x(!kE&oO3G6 z>bwt?)m4x^@n#NQ{4naJM!4!@$7eeh#9w!M$>Fm42LkC8jlMu04t*=#&dbavDBa4- zVR!hj%sRxJsV|>Z9+s||UR!pkqNJ?6yrRCoq~2Fn=aW3-FQmMtR^qyZHYXeD&l1BA z$_bHf`z-l|lUx3{JP%Pq`JaeQeJc9VAY{OI$a`3B?PB5m!+@r^VSm! z^$pb`G4nyKq_)ggUa6G%&*fj$kt!n}SGuwjA1c&Qd6}J*Cx_{9a@*dRyKOah`F1{M z(6jTaudS$%8P?^molh9KZ7;{L5)OfuN8$2Wg`U-aj3-|MQ=IxU+ui6kx}&`2!HT*t z{>qqCnK*I?wy&gzP_&%aY30aM|1K5h%g%Ka?I0(B0*g z6;SFTe=a@M{t@ccG~l}{ALW;k&mk3hF1e$ekn&)AtCLssmwdwONq+U!6%~xq8gE5- zJ@IQbdXis7g(IU7^;?bHju@A{HR#>1hyGNT(q__dN;><^Z)f>X|0o0ZW1 ztVU1rlj(iMc3wel*-KQarU_9W$v>RjvOiRPz&^yRl+T&;to-UL>Z;0QMH|MSaB|E3 zfV8hT62?B9JjkAfjxi~oA)giWB)_*d96nHE^-u_ZR+5W-{m~=k_DBz5zmi<+YwHdK z24V>NmE^X)nzgM;gl-R&&uaCoiNocOl;^8pd{_Zzud7$NZeO-9*tE$b$HJ|$ra8om z6@RE5YshlcVlDIr;SA*%mLUqV%Q?e7VOjnKrU5PFF*l@={YFlZ$X{4}X3B{4U7O@H z=5OjtF{|=NEv)Rlw3U5${|$Y2_TlxHpIlI7gl(UIeoz@<^{s`Ds|v0dQ|o3k=BzD& z>L+KsBe&Ph%gX!z(SA0q+#Xx1-sb0^dQ1B_)2)4+nQrY*?Jb-u-Oejix|NqSuqn6q zQI5|l4@=ifUvWQ+zrk|XeipgCC3Nt)$ENGB?K33wC^{<65}= ztZAq8U4AROaQju$kFfh$XVA0r3$_1QJ+-uDQ)%xl zq#<4HDE+Kr%&~}9?QM?B75BaPBW7Xut)@I^-x{2+HHk0t%WjW=hH}g8zpdABq{>@W z7g!j%>M42$s}5Aum2kSC{?Os7DpS>^C+)EsJ;~2Fdu%S)L*%oP-1gfzSroedXWD;T z@erZjvVA)FD1XB3(}T-dzE59fALs^me;M(n&Oe0TrWDx8xsopKj(KcAsw6H|###v|o)pBkxO-)4TR(UW!wyAL<> zSxGMTXWW0A`K(4y@(a69H}hFZZrNMgqEPW2cArlEmi>zRZ-*ae(zEglxes^b6Hac~ zhunud?8C`}?8EK9-TADbC;5flhnxAVBp3Uz`*72KCArv#-G`g@E6Hv9mGx`%nxz|XWHZz07pW_5wG>}A?r<@^`_i< zvu&F#+_udYZ`)=oJXG;EOZTB8_WK6o+GO&k1|C=Cl46lZ!$+%f!TyWqM?D9*Y`amD zW>HrkQ`3s1Dh)d}HQbLqA3YmylFO1xz+D2haz#Y^g2*kodm!1iovT(2o1H@y%%SG`Jq zn#WVXbuy2q$+NHG(B`ezdko%SGTr2j2Dhb}+-h>0$v0}7U!_0I8e~msvXH^<(e@SQ zr*GSuo^{>Uv|ZWPZB5^mnh$SIbNH1FL5UECvhk7=Kf4lvzDo8 zy3Xs}yxz>~3SQ^)I-3`H=xcbPh*(3cA=VJ{*ovkh)({(i&0vVv6t9!K=6U&fE%73Q zW?nYl&BWZqBCEZ5$2cwxwFa{!qnrawAEF9Qiz(nD>)q>fR#94r{_U zgCQqe2<&xCo?*J4qlq^~?t!B-z4x!z*sgL*9K+6-S3ULKdQZKN1E_~m(^79pNp0M^ z{U#h>6iU+eU2^~<%aBzGacvf5Nr+bw#~R~bfv(N+-^se=*i<2Ge!>8-%~qlY)s zh*k~Kqy|=LMx|8J)|C6UZr_o9e~{P9l((mbQg)Y|pL>T{+zmO-22=B|3}0^v?YiGr zU!sl#YLLkxmo{~&96gNiOj`LBZ(C7Cn)fbWWg!i=q8@F%qFh>hxdNfBUC!kH`s8c1 zvtriA%4chATQtWwBPD9BwuZlf|XWml_UB>B*bwIsPus zGud>j2&rMg%&O&c_QRt-GSSKnK07pTRoNjm(6qY7lJc_ZD)Uyl>-{SJavs8 zQIss|eC!ce4Rgov{di$ytzufOLhHG;II_RZ9{Xl#m6??(Uez1%`wB94WNI%&%Bqc9 zv7N0!VL^=$TwsQ3fHT%;v*)(5BMlq^j~Wd`mYb!yn5s5vYuB9g2Bw&%#fnjM=O zQ`lP7bNfgYA8+Dg{X;nw_2sp^^|0W1y&)Cd+{3lLqg!Oslu!4mjr{$nF_gr1^UakH zVO5_@N{HZgC^0|N^Ws9b@;IRFRH`_9pu+2|@MhOGC~v*gMQJ*f%FF7@H(vDLg#g` z>~K}}(UO(3q)TrrE8in+5Z1H9RY%UOLnb-fWU5x3%$~j0tZ)jKWw{n7C8TIJ!&R1ciQKQPK9u=<#+wS3jgpsK#W2+IU-Hz}hiMKRz`6bE zkk1}!J$o(FJF*F9B(o|Z5~z8uuacF8N4v9DE_Zx3G zc~Q%5%%km+OF^VFeIKY1xv>N>V|-a3O8ew&qrnR0WQzFA0noE)n^$IR4hvzs%PY>9E_lxm@KhDRz{GYZh8x911cd?TmKDHK!mmlFn$xyl&a7G%}1HrmqDqmA995g>-H>mBZYMUA5m^ zFRcLNNdN|y$B186eW~e1;bYh`7H=>X!+OjAh84_=@se!~WhVaeGgi93+)-yOU=pUB zz|kONAO{~i)@wU8HT=xMr|rtswv}w(oy#EOKVyU$1I!p+=HSvoKcN%B0$HBi;j-KE z$97zaauO?&b-g;PUGu>DNNp;ZrXz4)t;-3=z*60MZYQE_WO8zD6P%9^89NWQBj%fb zZ9@|5u(AIzA94DBravMV= zeP!BtWP{1mOdgibN7QN2^;*r5s)~}@>N4NKn!3X`xjvTF9lkzoGb`Q$We3Vi%IdG* zx;ZVqBF(qC?yZ~aQdgtg7>TmvTr=O;;`||BT4OlZ z!)c3tL<56UFBQh~ZV{Mq{?6E>$U#+gPKt2_Ve`!r4YF8K<3uhhY`)nTChN6_wCf%$ z<4M7qL)TH(7O1Jt=G4I(6QI>PKWtsCwuKb))SY)wO_>WhWdW=pge{3+~91k_}cTr+6wFxj^HQ7MH;s zk&C_>AG=rcBuqW_biHH};an_byWBE&tdiN5Eu2b^prR@#(HCQLns~+L5gv%7oLbf+ zazazBX4Mjn<#?G~8}=03zOS(4w%nXOJ4<%$$;#bljuWnIa{fyG;lxdeZ_8B zHMVmSAK6h<$$4*y6*d{UM=J{C@TaB%xvI-|5k!2P4Gfv!5GN!#&ea?|sJ@1PM=)8P z%SvZ?deS0IxiPG5`9kuUMi0~L< zIby|!a_E&DvfUYZD^ymFTQdHoaI4^Xe6RYFhF2>``(9`javWv;pJXiSyH_h?Ybm16 zc;ofI)Sy--9tmIjgB)#NEqCd%RA*+~nH9l=<&G!Et>UkChqmigW&8P2Ryky z^j~TK8pOCa{MD|$aU$*iU9PWYdm7V#MCmI&5HM3qU9AZ(kmIW{>!}mDQsGz2y;n1@ zpph;gj44oBLyCE|>M!}J19XacIkBwzp|Yd(o~^t8rTDjIKW8oer3~#!&za+^))IjO z)~nI3fqA5%Hlj*f>lM{0>b^MUqJ~;-rDcgKSEyfcZZZfZcbPrq+nZz!#oEeV$VjWM z^7aN%wZ@~0L~-mD521fKP@HWhwX_4}6;@B}^nI0bim&8wgRi17u*H5Qt);S1=L@90 zBkI3e(+l%HPPNiiwc{IKBqT}<`73Vv)#m?7hJ>*)HSSoThs+b`^bfbX%S{2kqsDo4 z2_$t#xt$zABzmj4159o)w>?xv*?FqQiewq1npn={;i!+TzSU*ba>YNQ6a4ZZmSDyxoCk*O-rbDdIu=>(A&dnQMs zu~Ar-%sgO!mybIi)#=jB_8LCCd3Y5&7o$_d7UEbQhA(C%C0P_W9v=)_kiEiNR*dbc zu~u6qw;L;r+_vYNJ>12Mt#~M3`efWw6jH?)0_uB?+&S2}+mAWAHEjRRtP#Eu#7X-p zO;tjOsmt))G2qm*O=Y#U>Rw6Xrgb9@*Ic&tO;guu+I?qf+TeFi>GQmwg|TnYw3P3j z(mk*V=D=oHEa~4nrTbtXY=>j8AI`y1nD&EH`ZV;7p3?m=`bVeq_!K_F6xakaVg8R# z>7~#!c1mxCW3U6}{p6J12Z!JYOn>2&J_U!N#x46jFX9*UjFS(Xhox}pr>FE581u7J zdN=HY!_Yf{Kd>6k!wHzMh5Md=aY|2zL$C;Xe|bu8gfWx&0ej&9Ecn$aeFDzGdD!u5 z?62edA%25BoPtHLWeR(k{9EkdC>(&bzr!BJ{~mid025L*t#}%H81o10VLxnwr7zR2 zF!PVJD@>d@rH{k5|30P9!IA%=J-2cn^#7jH)8O!*PU+l$q*eYO{Q^7xf<5g2EB3JQ zZ`i|$IqYHjKd|4XX#RLhRGY=T7Y57|el*_bljMI15`~+>@dFk< zwxAEfgvY4|9EW~5+Ce?uOus%sJ>WbnhV4&c4^P5Q=zj`(Slfv`9D#l~0~0gx=V|Pr z7Z$@I*aW9xJB)dTc!DW#7*4=RIPekjf$jWQQ{qnaK1x0?^EvW?zHah?86U?FIQ0qq zfbl1=hvT2Z9-i#QK8yMJ)7ZoI&tMPdK8rmp{2cah@blQi%r9aOhrf(HEchz+*|f(X z_Au|8*vn^rfTs!O4`UC0L>%q!6Id*&6GIL*A2OMAgIIQBC05{#W;UV<_IjXg~KU+iJmEcP(|&)CEM|HFP4 z?R64+*!)lIVe&loum!fm@zdDDR6q96yNEqZU&4Mj{i$OQlh*J9O0YHRwCK#02bNFPwuJ zmtfBqCFfm=J?w?~aQ^bsdNmw*-D$lQ7G7~$?-jY{v_1+4t~{;J!knbjdh9L4_omZ& z3T$~j_Av2k>|t**_OS07?4j>k>|y*Hu!o%~*xyRMH)9V6wqOs_Qn820Td{|U+pvd) zY1qTj>#>J3H(;O7ym%w_aAF7cu=Y*Z!{nQ=hv_$C4>L2dhn;X*(z8zM(YGLp;gW6vDAI8H0m<&(C448b|X}tiJ zLNDxqjc^RM!kE3M^)8qR`(Yy-fqifi&cKti({r}dZu{DFzE5vIaEm;+~E5%lb*ona+x zhF!27PQV@*S4exoJU9lM;56)m^Kbyh-a)%U51fN(Fy+qEdLAr=#jpd`!ZFwaW9~Yw zcfd^83mf4O?1STQ2F^gw-KTXwEP`?SXfK!qM_@YCiij7O4ohJz^uZo@3{JsLm~hW& zy$=?^VR#Hqz#%vb=b^Tr@qI7-4=Z6Z?1C9^0v5oy`{;j|2OD7%Y=wQW3r@p+m{3gr z!+baiTi{7J0HX_uKbQbL_tXEd5N5(wSO|wA6CO|*bN8ZBpikDCGUA&qHPA1@2Z<}#{}AmWY@}ad-%;Z7KKORp752V^xDYns zKkRuY{tMrQ|HZWDyYXMxOuxde_Yjw`^WSJ!;lsqm{nWFCxQ6ZjPQM7>OMAh=_c1Qu z%rW})E$}~xOE~eLvlbpSq1d9d*r>IbVoLj7QA z7xjb1&*FDE!|9{=4d-ApoOzCZgk#;r104Ps@#Mvyk24eIMPG?;PfXMuW;f7 z{#W3~r|=)P_ToRx|1|!?qR%i64l>?8OFzP-KKc<(!)`e7Irm+`+6`2c>w$*(Z};lx*&za;%@j6XOw$ox?SzfK&&(Qn|t@SFG# zM}`cL3@;rL5f0%fMJ>Q|8Fz36}^8x&XUO4by)DyOiP*3Rl9{p6! z`2Id|4by%=Jz?r7^%VY)dJ2C;ydEaM9}|Z#e~fy<(x1@&(Dwpy0h?aL|08@JXI_Pk zKV`m#Z7)$C?D-k(T0@*q(5|ri=foH6`33zA`+iA#!GTHov6i^~74r@BPvJK#{4IKL z{`a((r2m2Xy^VQ#7QbM|pNJpfpV5Oof2FJBPMfr6}cIy)ZG_uXn%^I10UI@kDR~`NC9~ zx6ZE@!F*T^XJH5Q#*i=6&hhIraQr;Kp7bF3pHIH9?E=5v14}RT>vOO;9{EGm8y3Nt z4Su~B_Fm-Ir(nXxem$lUzZ3j=25h{y0oz2|pwq4#6Zi4pZO^?0~WF zV7`PNn7N4`7lb{q3HHG@I1Bq>(d+&CBy5LT6a5X7q4#RPUI4qH4_01_e=y+<)E}lo z?VZFijECtk8D_u?mPU!hJ{JatW zpchs{KkS5wZ=xL}9nQkZn~Cd($^Xs7AsmK{uxTgx!((s+PQpo8kmc8-TVS?dPlFvf zv_Fi?#V^oLguoI0F;jOL?~vmvAH> z|6%iO=u7%u;u2Qgi9W1`G4G>YVIpk2%dh9dq`QenI1hW_WD)%VkKKbm$7rv6{dy)G zybph1-2Lc5Kb(ZxTm1S-7!9NU1ACYOhf44VR=>}$_rcWvWE{eY56}5)CA2|OQ?F-vGm=9pyllTQEpT__96W7n65A$FSY=lLy4_3peXK7!U@Eqm9 zlQ5x`dVP#~!<>(kKaB1nf0%KCet`bZp!Wg#qmO)H{^zJSEdD%k0TaJKKf`V~C-Q#c z=!5jz7s(eEeu?&k`Cq1;pl<-bVcb_~&ky1MAnggqzfQhz?iUjAJFqH`l*d^ z43lB?xBYrCOn%<4AA?=P!~u-|4&w*Tf0uZM&EI3Z9A_SdnXv8q2uIg1>c^nxHH-QX?1D2;JAYA6_z3+D^WX?O)p#iAbfQQFV5sOQ6!jf;8<9Dze{=*mUi4-2na)YG419Bx|FYvKIs7xf-E zc=e(_4KtGQtDE`fnnm3Uo3CBe+hNKZ$OpE-IXD45AH(m>i+VAPyN-5&v)dN+VL1H8 zMSTK}r!DF+AIIM91AAyE zn0yQUeu8=7R`Q2auo*_@(;l!84#0xj7WG*;2NOR--1pB4B6Gi&G{c&wFvgtbqg2YoQ+v$Wrni+Tnugaxn^dSM4_gk!K3 zc0NVD;b13m3|pV39)0-rEO7_>pbw^e6u;mw9D$wBQ65a{rky@VKfz2m4lCi%$7omB z^>O@zNuMBp=n~Z-rF+{t;#&0p7!2IVK$C3`?zDzm8)E{Pi2R-PAU9j}Oh(qXwQ?L@w z!IAF~?*ruXec~7P{eb?2@uT<)o8T0jg7IIW+#lix?D-@0gNZZb552G-cK?0e#>FZ61EwxeU)Tk^;1nE&1*aKDunoq2U86zp2WG-z*autS$P)1Z6LjVS*bU>q zfjUfw+L|TZ3p3#{m=?9955R6X1v}O*>2cqrf1{W54A=|{;28A5(X*EH9$33>NuPk# zXD{ioL*y5;q-VmEbC&dGIK6&J?}y&lC4CmgoVTPWeGC6!DfFJdq<6wuI1V#jyQIf_ zn|Qf!Nza45uo*VRFX_Y3vtdb(ejfdcki*7{k;9k-{D;GE4(4CFq4UH|c}bs!v)3=_@!v)N2HFKS z-9&ppfANyu4UZk7{h+6keE*C3!8F(di{UJ6frV8|dM}KAEBde(#*eUWd4PJskt0ib zD=es?-Y~9~{Juw=!wfhIt6}fkC>Lflk`HW$(ch>4U;=D8x}@j8)+X8s`e6@jdKdaI z`rYXNfO!`tz<8Jf6JaJyf`u@rc}Z`A#qXg!81rwmH}u0PSo$#jjgn6b^@S7A3;Dfo zy&Yz}Z%H481^+?+{*ZWiKYl?^EA0o9KY(9w5>CLj52E)Y%Kgxio(|_>CG2fm(mP=3 z@g;o(#(#K8pNAtb`N!1jktMwdrnb|6a2gK4jz^dD8JP1J?L0<)FbDQNPWiC3gL=XE zCx}Cs_$1~3MCNnKhb>Q0K1}bVd^ih7VAs=>4-226{1<4Kk5E1wgvVfQ7v;mGXDJ^} zz=Rj+kB`#NF!Q-3y%C;--LSWNNgsnFz4$rK`0YavdOk<{!{pB|>3uNu3&bN#?X zlFt{H^nBO_eX#ILfv^{wDQ?12B1l_8DS4!-8+22cy4@9vp!4u<3c?>gV`9%s7D4uod=v zhw%ujzsq=pvoPfseEu)|gR`&`_Knak(Dyy+@k`p_`_uzYLNDz40p&vPDD{8|KU~uN za1^FYQm-FTE=>C|<-!>_2s_7^mtet9mh{A5;r9!)BbU>9tU(e-gybdIja{15W=x}E{2U@h!ESJ%5?Wh~{xl-KBb?Ef;a zz#KSyo~}2+rt@{Z7iPxk`V@@5fO2PPf0zebUyB|rxKP*oi$CK}$Xtxcz z?tw!vAI4v#>(wyv67m;09D=oQ9CpGv=!Xe^rhP8Of7lNTV8Ug(?iD8LdYkZaT_1#T zuhaDzSP1>F8^-+~?Fo}$(G|L$4*f76c6rDLj=@G4yHVF$VGitqb5~MtnE!gpKS|td z*7auCoQl72Xe;HwqHVgK@)yQE%!Jdh5?1b@pJ6{7g9C6H4rNfUzY^CskuU6p)iCB} z@`q!vA7;E+*C%20PU7Nk^efDReObC*43n~T-3P04@CWwi(%y4$m#!DWuHCxc31jo< z7dQyDztf+4C>QoYA1t_q_Jb#3^glR$-Aenw_rIs9Dsvx0uI4h79>yIUhMh3~UR@uB#j}Da@=i04fwaLVPwA;jO5DH{UK6Bcm}wrE$t(J)Q+giM zcAn>XI{KNlS&u~R{q?V2JWrD1d3kxIq7y9%=AWcD@k%7UH;Okq&&zx|=9#k-dE3sb z?`iH=g`}rGz3!Q_N`Cz-m7mD_dBs1&eXh_dbC)TXe8+i-Jjsy9?Z#5lnYJ|#>6vSI zv-7;TsJ-W@beciS`^fV2MAB=!PU&ry{sBWjjn6aBp3-a0{O=`yX`g)3Ge3GtkCAl# z#Me^N(nuSV1hbBHj=D4>pGGb|TXn5>)TIk~$8+5CYsfusHS01!dTKZK)SBtVX8IWE zZ6VTUNI&UH7ymTczTji0^j0Gu)dyt`|2)VCkxv_P)fW#r?28@pQsfiJ zCmi-ZQ|=+H8F||$PU#%_?fN&Ga!C>&yU{7^Ii)942dlrM@(d-B4OTR_0Wqvsk+;0h_Rg+e2*r>R^$B}0`@&V-1=agCS^!jJciMk`; zQxWp%Po2^`4SUrt6%PAGzTxeg*je^2$$#x1T^hyMlZkdF^My+b2Xb z_pKmLN8b3^@b*Q>{VT{DkvI2+x9>n6{kib+0p!P4kWV0w{d{=)dE{*?$P>W z6A$mfv{qh`$qHHKKV-yHJJZ}D7&v;4aP_VH)4zWKH-H`>P`PeYzKd`ho$ zmR}UGFGTMB4#zLUf1~|A5|I0lkNlS{H}ZGL+mWYypE=oS|7^g%A9)AQk2E>uPY2}V z$me*D#FQKPJLGf73wVAcoPY5g!1{TPMCN8IzM`H9D`gH6w=dK-4Vk7>M zck|pwp|k(?2l5|BKEd-K1y27y9FWf;kC`PtA^F!necm&#S(_TA6lC1RpTqit=Rsr* zggh?C9Cs;ZdW^GPnSp%sk$3#v9(StWo#U<=c_Gi2m}>#mFV3|%JKIL?LfKXyIsx)8qn6y*7*c|OKyS0n$2 z1NrA8&s+>YuT&#%U$V!IVec3>t;i>Nz9x;inRZw5wdV%w{9WqIwAI4`VaXrhrQW+%030TcJ@NZb*IE_z9}zu*x%_W zzZ!YQ3ihq0Je++m@<#0YjP_UKBI<;r{>Wq2b05C5eaZv!S>#RUF6ik-`x|K)&v3i6`Y^1O&s{)vD*ANgebfE zzk)mkd43}KJIBvXBLkT?@{y-s&hs@!{&9Dk^M;r77Si)sa}l>jzx^cOR}1n!&qCOF zp&NPW#_;tXMm~zX$l33Of&8bDM_*;Pi!tsT?GlZjCzHtESue9;C9ac@7r&n8IgEO# zcD42>BA59w?rNUza@w1VWs!TuK6!!tF@NTI#p`JI7Ubi|&3%^9Z)V4ceK+zPo`aKp znq~iPhy5_}*JH>V91SJCIwcPWf}r~i(5GYNS=&)bEY z7jlp%ZV5l`yvW!nSGslIJJI6&g@}aHa<-^F^x7qEd>L2B3 zziH&rX$#hR%qZWn9*brZ)Vtk|KP7h_my(bdU(dYZ^xv@_%t7wEVTJxjK9s&f|07So zaX~L|^l#L@K>KtfuiUYq$2rT-3do0%7riNT`^vbSM&6&n^HN6t$K6RhNL=|zpC`T3 zS+2QB6M5nV)az#EJHt-JjdPEdfqWi$IQwF;&qVI9ckTh3ke@`}B zuATFB{2Enpsn;O#zFmRi(JtyG>Eomike+Ikn|h0xK1=!-=}AVqIxiySM8B4Kk92d7 zuIg#+(M6twynVMl{#AShjeq2MdEv*O7x^sm4AUPupL3hheX1W?kjLz?o$IMVHV|)}NPk&$`?0JeNs=P>lT8QCn{0?~pek zpMHm3z7Zde@;i~|y=x)td5A&eJ&ow$Q)qiTU!eSAa6sOK-17*>J?D9d z*BIri@sB*?DdNW%fA)EZeltD8SugW|DSnS5FY2_{OGdjo)=P89^Pc8-XXLB=ey8D< zn)l)_<#_vyEm!tVc^Y!|J#wbeKdUe z{m84I<9TwUU5)%5=OM0sd4@FP9iI$;o}mzV z`U#Fp#`!HHuD)fg2c&;|$dmZKfF4KtIj>i=Bkx6CY{*snJC7^<$Y+oj82d@1e_sgH zZyb5T7sK1nAumK8Zr+W@$;vO;>phjfbG?^_Jn_q%hj8}aTLa}6BJUlr``7T#5uZNf zBVP$WZ?z+j`&xMa`;q4(4|g799Qowe!|%uDkQaP2{CSZ0%c=kK;m?DlAy4^k`12rz z$oodZp9k?t{y(tybE{nLiGH z9wh#C_`iZY4Y_B`UUwPu-cBQbnYRj&$Npsbd5~(-i%1W59;6j{%ecJ{Rr%H#*{XS| z7rA`@MYwv8BJV;T?mWmW@`;!1b}{A+N4s$8TN|Dre`j2m1==kIdFn61kBfZd)5xox z_Kx!))nY#xem&fZya#!>^B}#*6Mh~3Jjf_=Kk{(L2I0=tbWChw$=INk{jn05Pb|dleKlXahh!4klF9rGd|As%VHd9H>%P;y~x{7+Q)UnKgV%>RPz7Jf*#|nU$ap^8JDxjtN&)ttM+-2 z=qnlTq=!3?k%Tm+T~ zmDWdE+?rrthDl3vrA?4lP&bNbRn+LTMLpS0+;!R3ySmh4KKBrV^Sc9OJO($XCDjeb4r zZC6?XX?>){IP_9T>n1JQk(NnXJ890?C?svbl~zgGBx%lan@ID!^x8=CL`N+XnXa@P(!8#;BGQhz(yB@8 zb)_|vHs(reCvDD^)q;vnE%uz?GJK?^y3&r3R_IFWB(2ev z)<;^WD{YvxAy?W2Y16K>S<+(G2m7L3%dy#&7EfA%D=nEcpDQhcv<_EV0cnG-G%smW zuCzwdqR$QZBFFJo(vlr%GR@FMS~ux=q!&m+mVJ*YX9~H;H2XZyBT;hKDaQcBW9U|+ z>la<~T4UBD>)OxCel+^Awb_qHb*wqO{@1_y*~Cv@dU5@u;< z#BL6|Mq|y^yyoe+XU@-h;GsHAWt4eUtS_Z2P%ckFJ00oZXMdbe#Rfx+l+iD!OxRh#c^nJVwYP^L)NT zhWB>8ACFSC&XM|8NUZ~v7908g*=cNMoHo)-xvIe)k2<*ACN+gVk6XQsj4gigR?EMD z@7Xcxr>=kRdSre3IgiFXcJ|}zI?j3``pLCVMIDmXaW;KX*5p}_#I&EC{ph;K z&dPl}x?}AVQ3tU5d7#t9$42auH}D;6E7_GTx9h{MAG=7)o53#sqR7khY++A?-L%8c zT&bT_v7gS|B3u?V}Ci&x)o(*CX3mw=rxcu}OB%AzA9c_IOl7@ElGE zXwh$E-Ea-xFB#6}!R0pT*o<5onQztDw7+46(TT|(G0wQ?+E3&)_JAa zWxgr0@+2lYu$#v&lD?Af(I3cIy^Yk1lXzO=P2t98=>3xTmyTV=&Ef1quOF(hiGDNR zyDH@_+nZri6x?4@P8T-S*hJC}^OF1z&GFM^~NjVwVbnRTd4Q^?* z*pz1R9iK+b2I45ov0r#{javCT_le?TFSeQ4k(D=vjh6Gu%1hiqn_wGBn-pNvmCJX; zQf$aRmYTW7ehW4!yCN%R0GnBCR$Gq5`Ybk$yZQcDciTJnYBkHpaMGLDm*m-d>p-75 z?PRa)82i#+#n{ba7fJiIVbi;3_4Sf++U_Upke|BluBC^nPW#P5sDChlhJBD9g;1?k=&S(`Uv zQ(G9BZ@t*0-x*msQ`kh`6EP-e*S7vkLI053uVl#-1c`j@D+~7LjDf69Y zC+m;U+$Y)AF0)>d!8)9F8(c%*-4wXVK<1~YUd)c8OBC_#~_mPS@YNwl&;=J z+9D;3m?-1>{nvzT3$@~Qw}ltGdF&!R*2wSaj2wu(ym9Qh%Okgo&E~v@H*!C7uq&vD z?3gI+*@Ru(L9VBUZ%n==Dfl@H8NHv)BzDirg+Khdp3rXJrKEF26pY$k@=ZPKlrdKJO!)8_wsDj z`J%X8WK>U`qM&siMJ_|_kqc6ROHt~&i|c$*93})InY)4QW_wm72Bb!Dr|m~ygfd9+AhXXMf5|7l)R;&VE$0@9k^&scKAk7_&R zO|JO$#JZ?^amle+!Y+wdE4Fzb;CC^2PyeasZL%MUYF{I#+RUr95>N8`UOx0X4ZY>Z z@et<`X0Vxz&?a#YTjvi(R!#vny%E~9U=#nL$jTYOrU{$gaBWabo4NMc@;hd85tJkA zTF))aGj05)i&2hiT`LV8Sl3D)7N9?XzM7YueRzAI4<&XQ(VIa}hJgGf^J*n+g0wD4 zFrTBd*3dH4erm>m_%(oT{&D-dyYeer*4tUK-VXLF5&aqT+dpi!aklY{o`jX$0w8f4 zb1TQNFZsT}`O||&pj5!H7 z$DEUlUd%`AwTw|m>pFP$l3al)-b|OQ=8B^kljFC?4 z=eoFdBMJP;+}B5%_AI|)Bnjp{(&~N#wf(~p*SU2WlhfFAVAEsR1m;WnljrbNY=~a$ zUiMTU<@b~fJvIOGU2g4br2iaaFAcqF^g0YZ*PI}Sn?NI{pd-HnIF5d^p&uw;oimcd zaIk(m`bp36J8N$JTnUc6Abn}4Ve}i(cg`gfq*ao(Y%NHg-!3_r^^ti;erGVJ+deNC z@DJU0ICQ1`Q_)TO82dV-PhD$oHsb1Lk3b}djTf7-kK1$AavP~qz(ndbrjlQj9Q!$Mb@{O)0%Bh7=J{03qMX=)tg*!NiRtvbf{ z_(@(V=(M0CZ6<%IyfR7aAgx&v%yar`99!oDCAb}RlQ{EXBfo!EDK@)|xmeBfIgiTM zOsTGkL)3|0(uqKQJf!uJmOz@!yViJRp4(&jDfy41lZuWxrd5Bcd!TY2jlRRo--DhX zJ>MDflHY1KZ>f}LBe%mqjQ>^`Y@9_T?%YR94 zM<*GbVPg$td_PjQtXZ>VF`FxkSy{`fMBUyfuc}UCTy`zq| zSap;!myb>cI*o=-puOlHp5Ih;l(_Jr*NWbtLr+bYYGUD=X^g|6S`&AnoA`PAoUh7L z>8g7)qj>tqP?mg0#m6t4Ip0)t=h5v$x7+Z+I3_vAgUl0-@sNUE%3b8&&+ma6HZEW8 zkP%_uRO>;f82wT7I}CkmO}ZaN0%Pa7;&U@PnO_XP-et|N;(|5Cq~OY$80ZSjcN9YT2J%c3TBt6*ccT5zHHyyquRq7Q;)5cZ^AJ8 z!$aOP=;jZY&z6|$T*fGeTVsr7q7#dAwdgb&=RJ($jyhM8YoA2PwGTX_^iJ@BN7|!+ zJi5PTuTKMOL)niyjysL$NQOX-T z?nS>4{rGRv*2db+)i1Jv3yc%-qXqqxp%C*1>lJHm6un;bn$TA(j`qk(s{W!#Wf?#`WZSXl8(eFgR3;l84 z2gSS6my2})zoo9D=;w^t*Y^Vcs67*P4RK7f9Dmiv^7e(g_I=abZ-6#e)Y zSR1+L0yP%pylS8h61Q#W=e)=~W#~K3LrL74_j^X=EQ?zyYZTk!@!&YK&#B1W9D$Y0ooPWIdYr*kxHyBs_U>&f}MMT$1z1>)J1W>Y~mK z1(X+j_)&ElBai+?bMHhp63^45dHIE{9yzY@Cu#Gf&9CLRBpqq7CGu<2@F8-tr z9@1jh^P7&6V2&S0j0atrmV67)??7MTQT~Kp()vl8H~Q3AYuRHkhjRup57|RSmD_<$ zV=Vr;<3`24H>fkEk4Dg+eht478L|w{3w5lG%9K*e2Ud!)U@?QQ_{Y#0T3;AtLm13lMN%Ny;wTb98l9qs;#Jv3F z@Mgt4gph`}JMtvTqToGVA%Qa3uNf(iK__jFeY6>;4#+G4s zF~5V0FV=jc;+1(-Zuzi|gHn%lbjQ%`aFn4oljixEDA|+*x>V&~jZNAmb}R+P1No~S zHP=THcOB>sqdR2eAEe9LPDYzOnxzd#&@a4xsl&Kb@->&PI3&|E#4WGk>iyY-PEi29aY}D z+f^R=vf5R2+t3|H*F2XVRBttfnQbJxgXj+MJKjUQcjqeu)0yuKy7`;c+YdDd zsED-G)jTtben&FDPi*9G>>r%-Og+v!`ccY|ALnSjCU~AvKB+R~p#nS1)V!36{`|H4 zW^WX>%hnUi>rje*`{vcxp$+}wE&K*6SVSW0S}4m^<&I2-G3?KqK)!hkjye za61Lgp)()L64}vCiP$7pFqduRH?&IdV|SLwC}l8^~KOgxF1@=HFTL=U0(;4*4Y>NElFuCZv>QIEy@c8?srv$*d&j_jN!pB_)28nIZR3o5`EiDTMU4@5R39x9y)M6V;z_ijfRVuNiEmdrT@><$r zyI@e-@*u5<3+B)7d+wi|nI+(c*U#_I`(+_>@0|IbbI(2Z+`n^YM!BBAp8&oC_#+nC zB1dy&2Jnth4HtcSP7V6&tMMIc!sAC}U8raQBH%}Pod;S2aMjYk$AV~#BW~9|;Sx_g+jey1fInv;(wT{|72-A@rhZ$wB>DP0;7Vu3%falsgs+R9 zBi>%;0>2da6Tn;73F3X|9MjoJb_=lHlH_FP1HYeiHu17ApyCySSImX%Lr!74lsnKJ z%;|}*n~G94 zD`;h)onbE_L)_4|$v6Of&2^>>lG_bh1!xqfABCI+I0`Dp_{fB5Rp!Glo*_(bu z+W}etI8Dm~trN5o(8?_KG}pfDeS*mUm!aRMdipEvWoHiM>#5~2Z9wfo0eDt_8htV1 zHebeAQm@wqaH$fw1He%mr0tY=uQCYC31FbMT^8CFeczDs)dF1MXL^!e)7uZc>$CBC zE7~Gd6Va85o?i8%0mydUh4KORYtA`d-i$1#htUtMXoVWih~N)NOp7QIB90U3JTn(}%8xZS{=(dI%g+JUFXQiS!? zp*{F~&zWm&z*@EniS^6^VD|&tkeEKOXo`eb(z6n{f-l6|31Ms9wtZINDD4K|Rs&aL zv7g4#yhz)G?AHct)2+#kCkY<~KC{YR4}@&tME3T8@ZNjSMke4*pSG{N5WX1ry7>e6 z(^=|39q_w>-vM6usHg+x+yj+>T)hFDZ8yl@4+*Dc7QYpzYq9U;Lq^!v*2Be z&;~4s*UJx;UjTdr_%4|TiKiu8;mEZ%A1(l<8u)qD=(l9~$~@CpM7FYGZHkr*tOGpC zM-%wMw_`3~@e8vpKXdJL5AYpdjJN%kH4qwq>b29^NXgz0Q~%*v47+^^b=^AGiEsTA z58Ib)bQx8N%%o=tc+2kS(f0yG{w!;Rwpn*R@JoQtxHH~fB;t)vkS)w+K#Y-Fz*AI< z@rZTaEyfseLyBFsRvS_sjDoM?u5;Hx%7X`uNgHrhTbp%|R*g)B2ww<%^lmlRQ}f~L zXe>g?QyV&G6z)w^M2<6RfX}Fl<8AlzL{A~xU77?5CNKD!z*7RA?TFKl%Bc;sF3`%I zIKg`5O!_#OcnyKr6;MLc4Q$lBe&m~fwiR+F;77sRv)J@=JvO2;@!X4gwghtti;r68 zL=orRR4VbQO96O_z!SO`;}prG?w8W7(h}ODBX;bFX@8tcj$4+1ukt=~-a@iMpjCmU z)+`5xWA`AN-}3!_IHRjM{MY%>AMy*a}+j^=o7Mk2>dbdho#PE zt~HR8SSkhCYzKJCzZTEunQdvrd7~{&@Q@Fk0AJJ6INzCRVZ-l6F&eSCkl@Y#3jF@- z_C8gZRpb-TgW2@Nh8v|b>01ll!f)XI0^)jnBKBm7akHoeYTQh_MMPAjxfy)T;A@h6 zqP;zPniz1XG%2r9@Ums`^|yq)%8Ij5JR)#rUj6m3F?bu3O4pv(3h-tG<7-Wp=M(g% zXxvty(y=5JTdhHY$#L6S0&Xj@(PW8MJX zpv@MSi{>%Z{7xq3WHZSzL4_u7&}n&(T)zVqn{Vjak}FxlXpxz)GrGDkJOL^G)e21#fK#^JYssCGvr~WL&2; zl6AHP*xZrx-jpr#L>w6QZAL#;b;6KcHFWEc>S{G>6`wU`i zfidiQr+wZ_y5@cjC`dSWb-lHf_)ko3yCC&HwmC$+<9w0KPL$Mi! z(g}k%_c4^0#U{d!vG>`y-b{$<$_`-5*TN4hZKl}XAciYqy-oVPrT-}g-wE*TZp8f< zIhF_;Pfp&HJ$r4SF>B7cN$W4%;E(t=Uhw$DSx;m(O)$QWG!yQ!QF~vw6lrh3I-4bJ zv1Vs0k0->_$hHMF@DhJL_;Vu|(@OqM&&($uacp|nF?(&u(fE*K-Gh$xD;={pG&mv; zIPj{SH~*|V3#|SHz~2u3B^%*8h-)9k-1>TqIcUfs<|zk&2?J9nF{0hnV;VhA3gDXS z>zL1ch^$;-P9!0#47j4l&#l)IU@Cz5Fuj_9YyJ>f9l-4P5Lwhd9s$nv1jY&0@huID zF{*vs880;PibHD!BKzcg1MNr?#?^>xTZ=Vp%igt8U{ap6&r#y-FRl8@Hc71AlFWMG zYk+UJ$Q1kGFxsF2Ak~E?V0wUYNgvVk3?Y_oNvgI>_`_~s_iZ}6-KowW1*RLA6EaP+ z9~FZmdP$?HB#oW@%h1+7b?$N^xh25$0GEth%GVO$JDTl%6`DMeFEJyPV_`AAYX-LB zTRrj{P~Z*VZ#!r;pq;He@`2e8Od~Koh@;HRJ_WC&6hk|j%38)#l#i4k#-&g9=slsP zeW*#an@6l276IQ0e6nefP3yoD`F4D*-%LX^ZZhM9ivYKMbB}(9lzHET3SQZVa2>$a zKl9lL@zKQU^2dkF^CH%_z|rMwBR;#t(w~WHqe%WR_DNpDp$FrFBbO) zoJ$u2dIWsipNsb^3FE3+YM+OE$t>NIPiXQ*dz!Zb{YD$+t&oSbg>7`7sh7FPHs!$e z0M}r_3EQA=rICQHx702Lfi3@j+>WAO7c)7t55rjeaVJe4tnCu{_zv(M1@94=j_`3| z3$+J>@?mjt767grJk39_*By+9puX%k{J>;9fVD(mGNoMalg1{8ekOu+F2MC&xW0tS zYG!KG@uYu~uVn27jT7gr%UnNU!}!R!jTw)pJJTFioxulq9e8_w1b-bNc+Glg-dr@q zHZ@D1O?)ljYwN(;=7neH`wHdP!bdiWg0JIE*eE4|Pw$CyPIp?(M1Gfnf?M)8bIp=2yB*k^6A5b#$`5Ezt^I(~ zj{>_N*anMSofo}UO)@Mi=3{%YTcL-pzi@J+EE`?IL=d-Hm2 zlxBpsDT!z^b3$nMPo4X|N+~c$fk6;2XRVL*z6!NvO8_c8jj^B9UDh4yzOJLmv*^O; zVG?UoCfd$c(&Gc%D>FnIy3VONrWn|^&7o<%pvr(tP4k+G`F%SOFUulxSYMVeT5dD#BGJ5t=t8k8dq=p zT_EHi`$203ts8M&??ibBpA#dLxX)3UcpgFf|d#@ELN9mFrHPY zbDreVp?ntt9|8VIlKH3szHCJAS=M;O(}eNzAU}uzUoo<`zgfzczE0Ic=Yz6tb}w@O zA9!|wXP>NB(pSaS8@)zCo2JdIQ$839qBxW0 zJTo5=r&uwy3|qulGXlOH;Oj_C2Yn#El_;9{TwLn_t~|9@?>RE{!B~^NAufQxdGU7? z*wtft<9kYo#{L8TVxdu;&j76!w5l`Oi+F=c_kuz&rmeB0{-zAP;jz8v>~Hdbs|W5V zaB8oV*~g3ZC;PoE!nXh)NCzHq)Mqh=INSXe(qljH<-pfSyeS{{(_?k=Gqwif4O8xi z-j^Ys0`TktPejT#%T(_djyNk#Kcn^&?Gt!%GkW{;FTjb?e=glGayAT;vmjXy!@%Xw z=+*bO&9zwZe3AVbLn^-x;FkbjO1j`jKCut97SODHxt@QBw+&dvMeI@d*++V9<63hq z6%YK#=1a)U1GYH7*EW{XeVn*+Z;@L8Yy+_6q?C1!%m8bs4ZyYn+nv}SV*k*&)=)+M z!CUpw-uU_e(e{B>2U;DajUTm(M?l*HT7?|1R?VV4ir5Bb?L6!3%WPslQ6LOIy}b8~ z{Y3eYS%hniSM=&Jw%OLIeS{IG*sL3`+FtO~fhTxnuWb)f1860M=wr{wKQ(w*un_&E z*^d-MPCM~jh5X1mDxVb)FD#lv&kE>QU5WP?8MO5-VM1F389k6u@$ugCTEirp7JU;w zTZA^+qPOU4#4TAdj-ee~W`hf!0REPMukmX5C*s;S64x#xz_bBVCoyLIMf;$~%>i8N z050|+vbuoDxaPxUr96hd9Jpecrfv(a*K=d4$N9k2Cn2i>xQ-8zwG@~GA0ms|`AF9q z@b3qI!-wjM`{+v7VqlxWm-DIk_*wXm7@ttvM6bW1jeI(xnWO9jeDIU*U69cR8JiK; z?VDJykTS$vTYC`AL@d(^Rt%P$2>OqI@9p0s{UX7K#XE4tY$V>%8@Az}7=P42M$=94 zHr5>1ow4_UMyIl@$ZpNx>jqyKab3ouy*LLS`PF{#m6rF~)?94$&bCj(^hs*tGB#qJ z0lXnge$nj;lZm%Rss$!Wrx@6r&tP0DeMzjVmxxCvX`jO!T35%d-ZS@{Q94V(n^_UB zr^2qHITwy)?$aSVv;bRsbG+>l_QOyT!-htuWt+HlDNp!%6nvgrdiA@3Wm}-eC!%iO zYcKE&%KzhNL%Wib0nq|FTf8cPnD8Tg8o|fD0y}3Rw9S<|hbQVoKDZ0`vh~n^q`+IAo4wu~ z3p@Rkpl!ZNWx$$H$C?KyFYId&PiK){=piWIdBCQ8>)iP!Tsd&LN#K?OSCRy7GjLVF z)sVi*??f9wPrWJq$Vc`7*9=^n#L0Gw+Bi|@XWpYA9`+>04Nv#lp7k`_3AAlAcd#^w z#8UvCFnC&JI-*XAd0PC#cvWVb3`{ZpYQW?9HhfXezhoJSH#?Syx2)2HrG%bseqxx| z=9jofN^A!AbTRczZy;*vD z6AUJ|{8W%Cl%rDpKDeh_cNOdC>=qdYAEZ8vBEi>`Ck zGZ;kUshpIl}oOt(xR{Ep(yvDTK0@H4y{reXByB`nW zqv%}MJ7@t>jzvgj9)!BkmLJt+sS6SzHy>v|%@39#s*<7>TyZveiw zJw8@3brnqZwP7mj?ZC%?Z*d6umUfN?gu)9c5nEZ4A07o?%?nuXkYkmwLvEg?72@~? zppAIbLBiH)QO9zhMmx3x_cG4OTYCmC<*ypNftPyqGdyPg#2C(g|BKq!M&LIC?~(aS zn7?3rPGx9mlPQhe;Hlr4TpEOr0pBwSeD1d~SLsMzeg*KZmy^ebfDa7<-wu4r&ytsa z1o-eE@R^%YFMgi9{8Hc}gTU7V@86ZY{1)Jw2Z7%Ye9kYDlTYn{=NWV%z_%i<>#Uwj zlDnxPzvu@GfX)47a9|At(mE`5O10NX#{s{2?SCf~Y`Ca(iAn>KY=j=&dem(FlgTS`{pZ8kw^7jMZ zHVC|@1!K$KBrm@Z`1V2IYk)8MZF2IdK1P7=0KRR2`dDhIkA&R?Y)R+9{ik(8TnubC zu={}ZdvId=Mud1~N4#X0UU4{!Uam`!G3=p98V#5GXIi1PY&`^3!bCksX`pK zH^!IUVhFN)TKe-%YiRAl)U@~;M%zF>NP9yp^FUz9#<}Pi>$;N9Qw8uR z27wO&Uw=4x`R%~>3<7@y_~6^g%g@}3@!LDe;i*hYfe!({N7^>2G9kVo`20r($Cn4b zcJQ@FZ+A)IuTD4Jkde$P?=;r2VXyGU+2{8dzQ7<5?DYF3&nchJn*%j2VVpD*nbT! zJ<8h-@Rfou*)k%YZt(0M1P_%{P8<5KW676mIq*l5#FI`9z}FogTt3>t!@85_p?n+# zPZ&JO)*1iz;S2vr9zPHG$RO}bf%pG2dHJotHxB}T0Qj7Dlb4_J1N5VVz!w3ZcOp6Y zRL-@)w*jyEAG1vn>;2*$+FfS1g*gy-n!!`?Uh+J&&an?X>}34jyV=j_@tJrt&*Ki- z1#W$&fOx&nW1My#yrk3>rVZ4Eb#`thUjx`#o zf_{)({>1nn_$uIoV6)BL#rhfTSU2zeb_2T|*ks#G(f<7q{G9OR!0%2HPd?B9 z{Jh@e$I`^p4xT{Y0QYS~T@v?XZ8u?w=O}m@2Ejvl3H%7<4<0HKn{5YJyCZxV@U{KP z;Yp_;@ZG=Gky1z*kM|i|?Bz8>IXc z^AOOI@ewNXBH&K|pKO^EPaSv~E=Zn-^x6!b3}1435q=-=kwM^HFQF~=CojJM_~s<> zo=BaZ${ zJXcTK_Gp6{>AM=&n{oXd`((sEp2T@7iKBe(0e{UUeeric6D_J}#fa07^f&=pBXHzn z*bgQ2(BGa4fRyob=z;51h_hMhUGHlRdfQ1VkplQD1m*xRHAFBm_`IaVP}-Hi1oHai zUU!@mtq!zG(5exqAK9=0v{ulV11EE3dNkM~yOgFf`r@q^=Mc6H*x;qfVGjUXK10n( zlw7i1qFmC;gGv+lNT1x(h;yR(K`R5T3~~AqEg!VipwZZmencw)tqruLf+A@Zpk?Ow z$vwxQXW*|Ev=$4E;KbhmdckF;e-bSMS{Z2M7xW`qD`@qg>9pxu2WU;8wUO=Aw`s&n z0L8W{@#+ZqI*BI?S{AVklu_@&!hV5%pZCeu(;86WnVQ?^&8fuT~N-TbfNTTPmTqEzygXs3KTX zz$lsW*9;leSNHWd8bXE`Uw`UMCGm4 zh0%6kdVbA1iJ-dS|0UL#i{oSMGuN4Dg+Z;YQ2ERQK4+#`|8hX9QnY%+<73u!hG@q1 z^Y@g`5O7Pt+aPTv@;R3Zg7SKUe!tff;-y)ZLKOL=basQky|k}?o=m6Pcyh+3OXsf5 zqkF}ukpf3Lb^~_+I2YmY%g3MVS7zeODYPa$}kuUBn^IS-+! zyGV}gR|(7kU{)g@&pYk^6?0rFF>}sGx~&Gj@P%&M|4*dMRySms{868)0a( zq1`#DEh>Ui(Hj%mew9DVeG*Z3Yk)2JWS@K%9=y~ZECp@ezxBnxQ2`Pw#a|=nEufcL z>a=*bm^r5u{Q&hZR-e5q;hbbeA!~D4Tvo!oRz3hp)#1Zrl|WYBuTdVKQf;qlYZCNA zgCiuF_g)iT`A2e=Ku*QKV?76Plxc!avQBOk4;onJ%(Riga!TdA19EyGr&h|b)la>@ zo!Wpd;EHcj{kB!_gm>&H*jT;6usuD3UR3!ajTbAy+XLP@ z$!p%D6l+MdP^JAJZ`V=n2-&9*d0L+g5G~m+myw=V*7sj03Zi|ZvuXv#Or>5o_rF06k*tJ zu$B%?nFTXztr$)SjL1JQ-N5Ml6Ri-msD+jT+C0!YLF<;XOh36VZdWnhT>@O>=7Ig` z^ML9(1Etdptm_tYyiBz1pp}E>p>*&g+HTNFLDM?sf_4D3LeT06WZEnK=!i}yfXklW z!e4=oCPU#oGUmh^^z?2ce?DHEP^!70ItUwtsn}Mm|m{8_SJh(Av*Hod9o?k)1!40~ zT8S?ROb;+Ah|`bk&L-Jb-O+Jhay20q`XpMO2GPk^$j=@ae8QQ+&7#FG#CUq^ig zK2z##^C7xkgzLM{a@~vTmAKx4>n`HQk7#wEwI$FRKx+n#`Z@X$E}~@XdXxcLD`-1_ z(=@^oeHZAh33QTm0Q4r%bDcQByW(fjL@wdwf?^=KkRDsGJa_{*+1LLD`rInCXL1}$ z&r8rtGw4ZSF%r28Y01*9$<8fG)n*fphZPQqVf8 z`}A{kX4{Xs4t+F1x3y%aCBPQl9j`^nr* z(`K!m+IZ2Nbvcz(3aWO?c3>aLuj$jz_7~55a@Z!fkp0y+|4c~yC?7q*c^9hnC`I%B zC)OQ6t0fSACHTt$tp&8)G@Q^pe&&;tHeEPt-399>mag?T`Zi=nCTtx4__!xBn$qbV zD)yNYNs;N*LQd#wW_cHY9t3SEXi+uSkuFBla`AMlxci33hi&gaCVRJoFX!uMTP0uF zZ1Exn^$^u9rb)~b zfbU!md&=@ey|h&;F##f_tnGU~_*%i&@c`~&%XAX?@CYVl+#Kvt-lO0Nu1rohva9#^ zs2dL^XV)TN_dS%nooa#a2_=tj0zT)F3sQZZ+U-eJpw1h^GlW z;YPGw1Lp^m_s`qPI{=c3Dk7rK+(*um|N4((k`~hQJ&@vIHANi>t zv=gAIXWpu2$Nf~jU^e3X94TOZrm`4(<>1>N>Fe*5{Z1SDjkHZ;XNi3pG=P~)Uk9Ow z48(?wx9tsvN;?7>)lC>9%e+^~b|L;^Au%k(%iV3MmxH$xe7iPbO=cucW~K(6Gif1g z*4n(rOJ=W|zW(Cb8*(GlW^bJO_(f0TG)-9o0ru9)`ANqaG)Nly4Ow8w0z(!UvcQl9 zhAi;^kp;Tnp@AXh=PHzEn3Fv!jiAq;Q|EfY>?i6xMZ#F{=Mp(upZ|8ah)q=I^)qO| z!kAB;>#^Ad>O82f)4Buw^!4}p`tPQ5F-J$}rW5>P+hsUR1}u{%1Ng~Q7<*mmH%gMl zyDlk8LpJ&yxmF@+_(i`M4G8hekO7n0Gd4k;ht|maX?lH`JlA@9uaUqJ3a`hRef?7Z zLWS>F=Q`bPb^c0;ly^#oz#+yc#N{bVSV>mWmR7_tM^njt?J@`E8i7^(+D?Z8kwFw_nVwF5)# zz)(9d)D8@_14He=P&@E{q8(`Yl-^;2)MXKn8iW1`R=o*i(Am$cIS+opsyE}D2ftv|n|IEGe|d4#fxSHaRd3jpn5pPB3G{T(vDc@+ zE|DIn$NLe_q?2s=)hFQ3L)9Uc{{a>tU-<82qgpY0N@S&{{b|$&Sz5DmiVx4S^Ceq# z+KNp+N+4Oj&DWZI)K=+zhKWihHo;BT*!jjJGMwc+V&NkRdLLjSJTX1OQd>-P>t7<@ zxz5QZ|BbFdi2hf|IIx4UKjSZozeD(I#a|Ep{uQ#jJuDV>wL4~nS1*dJHe%m&HK)B7 zYjg#RZVe9$ws*7GI#+}RV_mLbN-(z46^ik;eimEn3LfePxMj}H*alZiVKBDd6=v50 z+?LM(Zp#nGm@CLKg3bxC21M=;8u!N<+(F|Lv9P<{!D8QZha5(8nmhKGJJ?+t3%Y}Q zS-8v*$?$YzS1Gh=ky`zew0c%()oRgdtI+DG*2xL1qmTvQi7ZE)#^6$wbf1e zI_ehra)(HQTj|LVf#w-XlXlW1nDJ0Je^Dggh`r=$W8RR%8{6p$vAWm`uE_kW5O15s z5N~!p8T$#ey*KuvFwqW+&Odd9^I3##YDT)p!JEw?=_x6UBaa>p|m+v29&wYo)GZd>l2bL-r>MegjC zdag6VKHcVE?d;RB>zrW+DyBXywV!^%etJEf!bEtt&qN=4Jm_buv3vf9%l*vj^|2o# zbpFl99zpmQ!^c)5y!OvNwglk~ZXdf3;p4#9BYgHfANwl8rnh};>y z9~+18^80;k0>Zz1&&R5OJN#uIyA9#LKjCB52p^s0V_!r#|F1swdFWA+<74v?PVxBI zjpAJDxEgVz)5q2ze5%;T)*(#2S6hA@mIMu{MORi+t<{ z2$yC0*mi^yuQu_*uK7MZ-wb@4k8MI|Op^NDA77AsC~ zL+$8D4}aPfW9iMQPSAsRi~vUuBN&?!Wc49d9A@Q_50*7&v6h#s+Fq_|@9&R!rUd)@ zLwD~9yS$NSGMY2qYsql8&3vT2qcrB75*+`}(DmKn=Ql($Z)$e_w#8c-3rq<|mqm{M zv>A`7=gw@qsk!~$3u3ttGBebFfA~8kkzxJKP4ip+_SaZlpn2r5@MZns{Qg)V(0=nx zu|PH*tFnX6(r|Wuq@%fgQbDXHJCv~u$F_-qBk->*wqlf*c@fg{8FNw6?9)Crqur0v z@UZ~GFv7HE&=F=JbmgH`@K=sM|D~Y+%Fnic)X%>A89!@8_$`D_P4%-|I^l(T{cObV z;YC$`b|=ms!FdMwUP3&i;vQUIR1CQ<``J`nyAN@%ir<5{q2hIjJ5>DF6QtZQ_p|Iu zKf3~aL?c;i=gVtP-s)$oz%vQ7SykZOZekYWd@W>W;X(RO5DEW`h z^0O}kH~e*AfO8`3M|#VUzk89-xl8@57<>lgE<=9T154+_)cNl(^Rs_bm{djcA~Zr0 zm)a=#NWaI5k?srd-h6o4g{XyoKkLR{|2E*C!{4KbuR$Ju<7ahI*nAA)pgTZM1OE}^ zMdKX6od)leh|If7$tIb`vwk)f_&J~j5qBcJ+i!tB&p_69V0T=bjcZS1$D{OHB)(dR$a$wL3Ilk>@ z?}49qn~*lyX7e&Xdkg8tpubDW2qegGK}HGigbN@qIv<@l9}|UKx1aTa-vNInnN`Jp zwoA!%!QO;16vj}P`2%2Fz>w^XRd(H$y^J#X8T@1yY`O>Od>1&SM<(QW;Zxp~e)e{* zOzUiNJSc;&Cn@U>7bDF~)HBFr9r#mx?B|F>5B3ZE{nF1~M*U>F@dv$_2kEQwb5Qv` z4BD^p2O2|}(sdW|Pa)ZfZ0d^0^MUeBIGxW(f=wvDbe;T-{LBkGUx4<4hKSNL(0cQW~x5S_)*4F5gU`r$T-d>1jWDGU0jv`Eq^<^#pmj=3Ay7tQc(q zu+%1AyBTy`3v|ddve6clL&py2=ugm5)IEiBK!*0$7h$hmDAO9~N%;>T|JqOKnxS|o zU9yQ6*RzqPl^$4*dXB&E03XD)kKwNv*nH^cRs08`(>T%QDSHo>n3+%aC6O%IIqd$)2Q7W)wOZsIy2f2)$e?twbBSaXlCMSg-F`j=Umm z(wW+X9l#VTeyuBoiFPDEAw5fGK_A$QWRmZZp4*`(=@z_I(nf&xBhX$@x<8AM_^oDX21^MeTCTMtuM zg1V>9X(UJIG$NzxG*YB<8krqKTl#H9r;!-ZpHcKyMc=CEH1c~Lc!OaaG8+DgbdSG@ zwtu~!_4I=7^0N&M(!NHgpPhidDZm)O=0Rr>pMyRY@ll|=VDrZ$TyX1FbZ9v zFQ2CJvDuQ35g6C1d~Ai>Y~) z=VSe>UY#Gux%NlWgX-X3*moynXr7(GB;u*89y*3T2I*1gP`*O^R6cW2p48sZIK~6N zC0}r;^EY6(VK}FDiQ1T3{TQ!W{7u_J_~Z=flQSTXY}4um&t#0t!B5xU&y&~la9xx; z>JZr?8}h_?syrWyI+Q(0(U5<_q$%2pxBcvCv_m7A@=?g7dO2y9J)A?T`5T6aI$dZyo%C^cxQO>{`qXNspsa-Y;QaZDS|&UH~~G5PngG3lY-4yAgg5 zVJ$)j!bJ$5!MOBCkH9xt{H&!6?Iv{HwFBb?=(FdOa*VTsqkaA*+QJ<^mf4Q^Css=? zK)4vIDt?6DEcCHS2;aY4_R(2t9-J0Ln|^H;du`Ns779&ZoM*A$V4l2jBfY}_`2cRk zD0)ADW!@}kUN%P1{->@M46PCjtrE~kdUi2-;b+m~A>Ldyv`RoL4|*lxY_t2JRRTX7 zS|u1-B^X*I_`i3RpdTZ12S$L;VPyG7jB51^aA=hPBVx=#hgJ!ORtdx`ce7=NHezU% zU}%+KXqCY6KYW$o_YS#AAZPfvD}J7<1hnVjYR=c!QSn3+Pq8}h0 zjF;vjJ+XR+Rp~`nVFeD?q9?HGgw?7*D^{6~$yGo)e<+HTx)snBaYq))aFblsWg!`6 zJ&dw@UFxv&E`-26b^+w!ZbpcBe9(Ohuvp=Xg6CmP!|FKE(!lS64Woa7-EoaprG3C{ z!I&;OOX4*x>c!m}#m^y=?$|W!giWxrR)BoaT?TQEYjpk)u0_LAcLR0`L$CXfOL`}4 zKzCU#B^>hTg-svo0v;jdI~!w5I`7BI9jz$p)jz$$DpuoR@3bkB{}^z@x0PX4JKLh0 z(nYUIo@cd5Lq_=jo9+N7;$z`EDt6W}uR3wX4yV6)RE1l(EGmcFUjAx6wv)Jvp=9x8?c|MlLh8JhBr{-s| z+dv!k&vfRwX&kG#BaJ=3o_Hs)_k#F?o}|OL4$>ow%{L&s3V)!xT<^uE z#Q)`N432=|B`|~sZwmX9^QE_Dt==+wwxWz?&$AI*?pXQr-N6^ve(uG!H{qx*UC5pf zq`Y{zl}@JY>8Y zEZGtQWz&|2jaR=}y5$k$)sA^vRvE84O1B(#zFJ?hg)w4hPLk$kmz?b9L3T;yD$dx~ znBx)_NlOFvK5T#T}FQ zs)KyeBmAI)uZo|prqln3pRVD}4*n~~U);u59plDl`ErBr+|5JK;V6H0A`h?P$4+r5 zc1-B7w}~Cw~dwqPT!7smvOlq9wt5)(H(0{{?QM_8l-{FRnFIdjk zALl)NRPH}s&R4?zKj1r^ijm5K@j@X)#y=j9dw5#6K$H2T$_{SMljv`CbnR zxkeCCpwM~igWNNnJNEL6c5>qyetJ4(KMDsc0jtHEq;24PSfM3 zhv_s!oIVoeS%>&0gTI~24?V*3xAIm$AAT9nzlF1>`L+yxd?c?h_@)$oi;F*%&v$zG zKUR{>w^j0;!}w_tKVHfE*7KfT?XfHQ#ZyIoui#fk$skz^_$Dv!^7937b(EurkIJS3 z-8PyZOXZ(g#kVnTc=!V=xN{r72o7_Hau{PFZ(bopW$3rE%9!n!5qe@BzdQS5(6}(_8-!_gv=j1a};o`<*?zxjY zk8}10_a5h|H*?Ro_!};2tB+sGZ}#$UrE(WwZ}7?66kwPHxOnpf?i$HGVBE$>H482W zKR!ZmrEnvKE*ZxuFU|_ie#d{$_}H=hV_W%nH?K|M8Qb{BMZ6}3r)=X_iFkDicWvW^ zh&wnFT}H|#tetzABeC{NE7``!{PdIEQba*FE$>bL}s11w> z?>c^pf1#T9XYq;q`NMzU(Mmpv@dI=Dn-jTrI=>9%dz|M~@SH;K+{CZg%C{D9??*Yg znUKsYIKSCU2({kyz>|V5ypf2ReBxm~^?gAUad_j~2bG)kU&wp=sQA#=RIlPwP@r9W zZ#8v8uUK6CM6vhx0fb8mM%{(O!QWw6=C6>HyQ3ofdpON`y=WQ)h) zSiE?c06_kVRs8R6x=Q1~bQ$@%&_s+gX|xF<2DEQ68j&I%D`xGV7!{d&Ph{9VF&EpN zzo_Hgj#Do7>-n z^J{z$WH~`uoBvpkgB^9Vu2854pLJW~Yshkf(wP5PuY>)Un;i~?dKvrS8sEw+Cn)Rk zAM10lV{Z0#DAdQ;kJk7e%yNRVKL4?P2RrU&?}S2l$o9u;d=F(gLD>NL#jL6HCMe(T zaCEYn(Do+|$6huQ>b>A_yv}AqpBEjDH`q)lu*2cl$7UkMpE?}>$z~#nmmH4Yv6+y$ z)8Y6%n~B-P^S$zU@pcuyq{3Y)d_{%(RQN{~9#r8wDmVUY?;RCuEbZ&KmsRJcHewJN+S3S0bA-{@vJeda*_Qx{IATv@$S0X=Rmybz)Hir3&iUStTbpZGGL{791Q>M z@B5kV6NKK?oa~We2X}NC0OU`T6?_#$xHjy^nZKNgAE^!;_ ziL^Yok&#Hd)NPDQq|I;};}dBgaT^m7X^Hh1st)}IV*z8FbDV3Od)%;b!^e46k61l& z^{CY;t4FW?-(XmJp98&DK!k{h5KDF<#LFo}7*Js@WB+QEL|ZlpTLsa$1n}374@x;G zJjeSu%1Up(wPex4`)*%!Yw2gpl1K!ZBYo&swKmx|a!9;Bn)yLz25C4#P3qX3bacAt z=yKE1J&caShSPDlmnyesEFDLr(Q#xt9YI6ED@fbLIN6>NXNIIsC zqGNgr9WzGLaa<}L$B&`ogdDWD4t5b89aHIOOrxVSmyWKB>FAzL$6=Syad@T+N6$n$ zj<|r1BYkun<)>rHg>)P}iH@mRbR1LQ#?gB@9mifl$FwWym|jT7jH~E4?qhTu|8Y7_ z(0)YzMGi=zSNop|b5xkA!UBYvPrMfd=M)kjg&q|WADt5)g;qWcA<(>{I9#G!P#h>1 z7s|zfqsL9h5yR*>ayT7Fc?}%BW9c|HjgD#QbWG1c9|RNA(J`Km#soS#JuVzQBj`9{ zBppYNqT{H58%J+89mh_lW7-rtrsoX9G4moiPMk`|3#QT0r}K#{h|vs%E@)1nSA`iW zq|S@z0Tt#T)chcWVT2qIrH;g%1^iMy!Y=S4!AI9cIgA;>a_IWV;qsfsBSy&Ywc%rG zxQoKD9h?PpQ_}KRPskk`AA&IN1Yb( z5eoU|R|P5Mq2GC0V8KVLFTdi-1q-fNa9Q>3R~1y>cG+!LUUAjsg zIIEezxQ5NBzW=Vp_kUT2OBTs1Xq^`?y!$TO$*s7y==R$A#GqnzwM*EHg?BB)amnrV zIDQc)xOR8-{3Y|*jN5B&{oVv9tvVVVih3t6iKD1bmUFrTb`swt z)coCwUxzuVKgMclrG88{1^g=Up|gR*Zlgsk2=)f zd6a0gAJyknpV3vv_1E87)L{)Nho9D8r=!C;xJKV_)aUv;jyfzRX8cHh!f5@8M!$0W z>1%YZzZ+gq#6n|8;2Rh$6U0p6O zf|nqgzb0RHt~L2m|6sxk+BCloI}-TycUzBKEBSHD-}cjdI{bA4zkYvb%cmrN#f>)h zc>U4T-y%Y?wEpZVH8^-m^5-7cNEzyMHFX~%%0!wZL&aZUr^@k+g=V##h0F>R|65if I;)!YfFBWcQ-v9sr literal 0 HcmV?d00001 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/__init__.py new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/__init__.py @@ -0,0 +1 @@ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/openloop.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/openloop.py new file mode 100644 index 000000000000..0dfb6b267b9b --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/openloop.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import inspect +import os +import sys +import json +import time +import syslog + +from plat_hal.baseutil import baseutil + +OPENLOOP_DEBUG_FILE = "/etc/.openloop_debug_flag" + +OPENLOOPERROR = 1 +OPENLOOPDEBUG = 2 + +debuglevel = 0 + +def openloop_debug(s): + if OPENLOOPDEBUG & debuglevel: + syslog.openlog("FANCONTROL-OPENLOOP", syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG, s) + +def openloop_error(s): + if OPENLOOPERROR & debuglevel: + syslog.openlog("FANCONTROL-OPENLOOP", syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR, s) + +class openloop(object): + __config = None + __openloop_config = None + + def __init__(self): + self.__config = baseutil.get_monitor_config() + self.__openloop_config = self.__config["openloop"] + + def debug_init(self): + global debuglevel + if os.path.exists(OPENLOOP_DEBUG_FILE): + debuglevel = debuglevel | OPENLOOPDEBUG | OPENLOOPERROR + else: + debuglevel = debuglevel & ~(OPENLOOPDEBUG | OPENLOOPERROR) + + def get_para(self, type): + para = self.__openloop_config.get(type) + return para + + def linear_cacl(self, temp): + self.debug_init() + openloop_para = self.get_para("linear") + if openloop_para == None: + openloop_debug("linear openloop: get para failed") + return None + + K = openloop_para["K"] + tin_min = openloop_para["tin_min"] + pwm_min = openloop_para["pwm_min"] + pwm_max = openloop_para["pwm_max"] + flag = openloop_para["flag"] + + if flag != 1: + openloop_debug("linear openloop: flag == 0") + return None + + if temp <= tin_min: + openloop_debug("linear openloop: temp = %d less than tin_min[%d]" % (temp, tin_min)) + return pwm_min + + pwm = pwm_min + (temp - tin_min) * K + openloop_debug("linear openloop: cacl_pwm = 0x%x" % pwm) + + pwm = min(pwm, pwm_max) + pwm = max(pwm, pwm_min) + openloop_debug("linear openloop: temp = %d, pwm = 0x%x" % (temp, pwm)) + return pwm + + def curve_cacl(self, temp): + self.debug_init() + openloop_para = self.get_para("curve") + if openloop_para == None: + openloop_debug("curve openloop: get para failed") + return None + + a = openloop_para["a"] + b = openloop_para["b"] + c = openloop_para["c"] + tin_min = openloop_para["tin_min"] + pwm_min = openloop_para["pwm_min"] + pwm_max = openloop_para["pwm_max"] + flag = openloop_para["flag"] + + if flag != 1: + openloop_debug("curve openloop: flag == 0") + return None + + if temp <= tin_min: + openloop_debug("curve openloop: temp = %d less than tin_min[%d]" % (temp, tin_min)) + return pwm_min + + pwm = a * temp * temp + b * temp + c + openloop_debug("curve openloop: cacl_pwm = 0x%x" % pwm) + + pwm = min(pwm, pwm_max) + pwm = max(pwm, pwm_min) + openloop_debug("curve openloop: temp = %d, pwm = 0x%x" % (temp, pwm)) + return pwm + + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/pid.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/pid.py new file mode 100644 index 000000000000..dcd129af9bb3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/algorithm/pid.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import inspect +import os +import sys +import json +import time +import syslog +import copy + +from plat_hal.baseutil import baseutil + +PID_DEBUG_FILE = "/etc/.pid_debug_flag" + +PIDERROR = 1 +PIDDEBUG = 2 + +debuglevel = 0 + +def pid_debug(s): + if PIDDEBUG & debuglevel: + syslog.openlog("FANCONTROL-PID", syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG, s) + +def pid_error(s): + if PIDERROR & debuglevel: + syslog.openlog("FANCONTROL-PID", syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR, s) + +class pid(object): + __config = None + __pid_config = None + + def __init__(self): + self.__config = baseutil.get_monitor_config() + self.__pid_config = copy.deepcopy(self.__config["pid"]) + + def debug_init(self): + global debuglevel + if os.path.exists(PID_DEBUG_FILE): + debuglevel = debuglevel | PIDDEBUG | PIDERROR + else: + debuglevel = debuglevel & ~(PIDDEBUG | PIDERROR) + + def get_para(self, name): + para = self.__pid_config.get(name) + return para + + def get_temp_update(self, pid_para, current_temp): + temp = pid_para["value"] + if temp == None: + return None + temp.append(current_temp) + del temp[0] + return temp + + def cacl(self, last_pwm, name, current_temp): + delta_pwm = 0 + self.debug_init() + pid_debug("last_pwm = %d" % last_pwm) + + pid_para = self.get_para(name) + if pid_para == None: + pid_debug("get %s pid para failed" % name) + return None + + temp = self.get_temp_update(pid_para, current_temp) + if temp == None: + pid_debug("get %s update failed" % name) + return None + + type = pid_para["type"] + Kp = pid_para["Kp"] + Ki = pid_para["Ki"] + Kd = pid_para["Kd"] + target = pid_para["target"] + pwm_min = pid_para["pwm_min"] + pwm_max = pid_para["pwm_max"] + flag = pid_para["flag"] + + if flag != 1: + pid_debug("%s pid flag == 0" % name) + return None + + if type == "duty": + current_pwm = round(last_pwm * 100 / 255) + else: + current_pwm = last_pwm + + if (temp[2] == None): + tmp_pwm = current_pwm + elif ((temp[0] == None) or (temp[1] == None)): + delta_pwm = Ki * (temp[2] - target) + tmp_pwm = current_pwm + delta_pwm + else: + delta_pwm = Kp * (temp[2] - temp[1]) + Ki * (temp[2] - target) + Kd * (temp[2] - 2 * temp[1] + temp[0]) + tmp_pwm = current_pwm + delta_pwm + + pid_debug("delta_pwm = %d" % delta_pwm) + if type == "duty": + pwm = round(tmp_pwm * 255 / 100) + else: + pwm = tmp_pwm + + pwm = min(pwm, pwm_max) + pwm = max(pwm, pwm_min) + pid_debug("last_pwm = 0x%x, pwm = 0x%x" % (last_pwm, pwm)) + return pwm + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fantlv.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fantlv.py new file mode 100644 index 000000000000..ff6d1982f40a --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fantlv.py @@ -0,0 +1,223 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import collections +from bitarray import bitarray +from datetime import datetime, timedelta +import sys + + +class FantlvException(Exception): + def __init__(self, message='fantlverror', code=-100): + err = 'errcode: {0} message:{1}'.format(code, message) + Exception.__init__(self, err) + self.code = code + self.message = message + +class fan_tlv(): + HEAD_INFO = "\x01\x7e\x01\xf1" + VERSION = 0x01 # Version number defined by the E2PROM file. The initial version is 0x01 + FLAG = 0x7E # The new E2PROM is identified as 0x7E + HW_VER = 0X01 # It consists of a major version number and a revised version + TYPE = 0xf1 # Hardware type definition information + TLV_LEN = 00 # Effective data length(16bit) + _FAN_TLV_HDR_LEN = 6 + _FAN_TLV_CRC_LEN = 2 + + _FAN_TLV_TYPE_NAME = 0x02 + _FAN_TLV_TYPE_SN = 0x03 + _FAN_TLV_TYPE_HW_INFO = 0x05 + _FAN_TLV_TYPE_DEV_TYPE = 0x06 + + _fandecodetime = 0 + + @property + def dstatus(self): + return self._dstatus + + @property + def typename(self): + return self._typename + + @property + def typesn(self): + return self._typesn + + @property + def typehwinfo(self): + return self._typehwinfo + + @property + def typedevtype(self): + return self._typedevtype + + @property + def fanbus(self): + return self._fanbus + + @property + def fanloc(self): + return self._fanloc + + @property + def fandecodetime(self): + return self._fandecodetime + + def __init__(self): + self._typename = "" + self._typesn = "" + self._typehwinfo = "" + self._typedevtype = "" + self._dstatus = 0 + + def strtoarr(self, str): + s = [] + for index in str: + s.append(index) + return s + + def str_to_hex(self,rest_v): + value = 0 + for index in range(len(rest_v)): + value |= ord(rest_v[index]) << ((len(rest_v) - index - 1) * 8) + return value + + def hex_to_str(self,s): + len_t = len(s) + if len_t % 2 != 0: + return 0 + ret = "" + for t in range(0, len_t / 2): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + return ret + + def generate_fan_value(self): + bin_buffer = [chr(0xff)] * 256 + bin_buffer[0] = chr(self.VERSION) + bin_buffer[1] = chr(self.FLAG) + bin_buffer[2] = chr(self.HW_VER) + bin_buffer[3] = chr(self.TYPE) + + temp_t = "%08x" % self.typedevtype # Let's deal with devType first + typedevtype_t = self.hex_to_str(temp_t) + total_len = len(self.typename) + len(self.typesn) + \ + len(self.typehwinfo) + len(typedevtype_t) + 8 + + bin_buffer[4] = chr(total_len >> 8) + bin_buffer[5] = chr(total_len & 0x00FF) + + index_start = 6 + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME) + bin_buffer[index_start + 1] = chr(len(self.typename)) + bin_buffer[index_start + 2: index_start + 2 + + len(self.typename)] = self.strtoarr(self.typename) + index_start = index_start + 2 + len(self.typename) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN) + bin_buffer[index_start + 1] = chr(len(self.typesn)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typesn)] = self.strtoarr(self.typesn) + index_start = index_start + 2 + len(self.typesn) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO) + bin_buffer[index_start + 1] = chr(len(self.typehwinfo)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typehwinfo)] = self.strtoarr(self.typehwinfo) + index_start = index_start + 2 + len(self.typehwinfo) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE) + bin_buffer[index_start + 1] = chr(len(typedevtype_t)) + bin_buffer[index_start + 2:index_start + 2 + + len(typedevtype_t)] = self.strtoarr(typedevtype_t) + index_start = index_start + 2 + len(typedevtype_t) + + crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start])) # Two byte check + bin_buffer[index_start] = chr(crcs >> 8) + bin_buffer[index_start + 1] = chr(crcs & 0x00ff) + # printvalue(bin_buffer) + return bin_buffer + + def encode(self): + e = [] + # Add the head + + def decode(self, e2): + if e2[0:4] != self.HEAD_INFO: + raise FantlvException("Fan tlv head info error,not fan tlv type", -10) + ret = [] + self.VERSION = ord(e2[0]) + self.FLAG = ord(e2[1]) + self.HW_VER = ord(e2[2]) + self.TYPE = ord(e2[3]) + self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5]) + + tlv_index = self._FAN_TLV_HDR_LEN + tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN + + # Judgment checksum + if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2: + raise FantlvException("Fan tlv eeprom len error!", -2) + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN] + ) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1]) + if sumcrc != readcrc: + raise FantlvException("Fan tlv eeprom checksum error!", -1) + else: + self._dstatus = 0 + while (tlv_index + 2) < len(e2) and tlv_index < tlv_end: + s = self.decoder( + e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])]) + tlv_index += ord(e2[tlv_index + 1]) + 2 + ret.append(s) + # Computing checksum + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + + return ret + + @staticmethod + def fancrc(t): + sum = 0 + for index in range(len(t)): + sum += ord(t[index]) + return sum + + def decoder(self, t): + try: + name = "" + value = "" + if ord(t[0]) == self._FAN_TLV_TYPE_NAME: + name = "Product Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typename = value + elif ord(t[0]) == self._FAN_TLV_TYPE_SN: + name = "serial Number" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typesn = value + elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO: + name = "hardware info" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typehwinfo = value + elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE: + name = "dev type" + _len = ord(t[1]) + value = "0x" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + self._typedevtype = int(value,16) + except Exception as e: + print (e) + return {"name": name, "code": ord(t[0]), "value": value,"lens": _len} + + def __str__(self): + formatstr = "VERSION : 0x%02x \n" \ + " FLAG : 0x%02x \n" \ + " HW_VER : 0x%02x \n" \ + " TYPE : 0x%02x \n" \ + "typename : %s \n" \ + "typesn : %s \n" \ + "typehwinfo : %s \n" + return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE, self.typename, self.typesn, self.typehwinfo) + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fru.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fru.py new file mode 100644 index 000000000000..d3f3f1b79ce4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/fru.py @@ -0,0 +1,955 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import collections +from bitarray import bitarray +from datetime import datetime, timedelta +import sys + +__DEBUG__ = "N" + + +class FruException(Exception): + def __init__(self, message='fruerror', code=-100): + err = 'errcode: {0} message:{1}'.format(code, message) + Exception.__init__(self, err) + self.code = code + self.message = message + + +def e_print(err): + print("ERROR: " + err) + + +def d_print(debug_info): + if(__DEBUG__ == "Y"): + print(debug_info) + + +class FruUtil(): + @staticmethod + def decodeLength(value): + a = bitarray(8) + a.setall(True) + a[0:1] = 0 + a[1:2] = 0 + x = ord(a.tobytes()) + return x & ord(value) + + @staticmethod + def minToData(): + starttime = datetime(1996, 1, 1, 0, 0, 0) + endtime = datetime.now() + seconds = (endtime - starttime).total_seconds() + mins = seconds / 60 + m = int(round(mins)) + return m + + @staticmethod + def getTimeFormat(): + return datetime.now().strftime('%Y-%m-%d') + + @staticmethod + def getTypeLength(value): + if value is None: + return 0 + a = bitarray(8) + a.setall(False) + a[0:1] = 1 + a[1:2] = 1 + x = ord(a.tobytes()) + return x | len(value) + + @staticmethod + def checksum(b): + result = 0 + for i in range(len(b)): + result += ord(b[i]) + return (0x100 - (result & 0xff)) & 0xff + + +class BaseArea(object): + SUGGESTED_SIZE_COMMON_HEADER = 8 + SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 + SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 + SUGGESTED_SIZE_BOARD_INFO_AREA = 80 + SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 + + INITVALUE = b'\x00' + resultvalue = INITVALUE * 256 + COMMON_HEAD_VERSION = b'\x01' + __childList = None + + def __init__(self, name="", size=0, offset=0): + self.__childList = [] + self._offset = offset + self.name = name + self._size = size + self._isPresent = False + self._data = b'\x00' * size + self.__dataoffset = 0 + + @property + def childList(self): + return self.__childList + + @childList.setter + def childList(self, value): + self.__childList = value + + @property + def offset(self): + return self._offset + + @offset.setter + def offset(self, value): + self._offset = value + + @property + def size(self): + return self._size + + @size.setter + def size(self, value): + self._size = value + + @property + def data(self): + return self._data + + @data.setter + def data(self, value): + self._data = value + + @property + def isPresent(self): + return self._isPresent + + @isPresent.setter + def isPresent(self, value): + self._isPresent = value + + +class InternalUseArea(BaseArea): + pass + + +class ChassisInfoArea(BaseArea): + pass + + +class BoardInfoArea(BaseArea): + _boardTime = None + _fields = None + _mfg_date = None + + def __str__(self): + formatstr = "version : %x\n" \ + "length : %d \n" \ + "language : %x \n" \ + "mfg_date : %s \n" \ + "boardManufacturer : %s \n" \ + "boardProductName : %s \n" \ + "boardSerialNumber : %s \n" \ + "boardPartNumber : %s \n" \ + "fruFileId : %s \n" + + tmpstr = formatstr % (ord(self.boardversion), self.size, + self.language, self.getMfgRealData(), + self.boardManufacturer, self.boardProductName, + self.boardSerialNumber, self.boardPartNumber, + self.fruFileId) + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + tmpstr += "boardextra%d : %s \n" % (i, valtmpval) + else: + break + + return tmpstr + + def todict(self): + dic = collections.OrderedDict() + dic["boardversion"] = ord(self.boardversion) + dic["boardlength"] = self.size + dic["boardlanguage"] = self.language + dic["boardmfg_date"] = self.getMfgRealData() + dic["boardManufacturer"] = self.boardManufacturer + dic["boardProductName"] = self.boardProductName + dic["boardSerialNumber"] = self.boardSerialNumber + dic["boardPartNumber"] = self.boardPartNumber + dic["boardfruFileId"] = self.fruFileId + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + dic[valtmp] = valtmpval + else: + break + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] + index += 1 + d_print("decode length :%d class size:%d" % + ((ord(self.data[index]) * 8), self.size)) + index += 2 + + timetmp = self.data[index: index + 3] + self.mfg_date = ord(timetmp[0]) | ( + ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) + d_print("decode getMfgRealData :%s" % self.getMfgRealData()) + index += 3 + + templen = FruUtil.decodeLength(self.data[index]) + self.boardManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardManufacturer:%s" % self.boardManufacturer) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardProductName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardProductName:%s" % self.boardProductName) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardPartNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardPartNumber:%s" % self.boardPartNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + + for i in range(1, 11): + valtmp = "boardextra%d" % i + if self.data[index] != chr(0xc1): + templen = FruUtil.decodeLength(self.data[index]) + tmpval = self.data[index + 1: index + templen + 1] + setattr(self, valtmp, tmpval) + index += templen + 1 + d_print("decode boardextra%d:%s" % (i, tmpval)) + else: + break + pass + + def recalcute(self): + d_print("boardInfoArea version:%x" % ord(self.boardversion)) + d_print("boardInfoArea length:%d" % self.size) + d_print("boardInfoArea language:%x" % self.language) + self.mfg_date = FruUtil.minToData() + d_print("boardInfoArea mfg_date:%x" % self.mfg_date) + + self.data = chr(ord(self.boardversion)) + \ + chr(self.size / 8) + chr(self.language) + + self.data += chr(self.mfg_date & 0xFF) + self.data += chr((self.mfg_date >> 8) & 0xFF) + self.data += chr((self.mfg_date >> 16) & 0xFF) + + d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) + typelength = FruUtil.getTypeLength(self.boardManufacturer) + self.data += chr(typelength) + self.data += self.boardManufacturer + + d_print("boardInfoArea boardProductName:%s" % self.boardProductName) + self.data += chr(FruUtil.getTypeLength(self.boardProductName)) + self.data += self.boardProductName + + d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) + self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber)) + self.data += self.boardSerialNumber + + d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) + self.data += chr(FruUtil.getTypeLength(self.boardPartNumber)) + self.data += self.boardPartNumber + + d_print("boardInfoArea fruFileId:%s" % self.fruFileId) + self.data += chr(FruUtil.getTypeLength(self.fruFileId)) + self.data += self.fruFileId + + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval)) + self.data += chr(FruUtil.getTypeLength(valtmpval)) + if valtmpval is None: + pass + else: + self.data += valtmpval + else: + break + + self.data += chr(0xc1) + + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + + self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:] + d_print("self data:%d" % len(self.data)) + d_print("self size:%d" % self.size) + d_print("adjust size:%d" % (self.size - len(self.data) - 1)) + self.data = self.data.ljust((self.size - 1), self.INITVALUE) + + # checksum + checksum = FruUtil.checksum(self.data) + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + def getMfgRealData(self): + starttime = datetime(1996, 1, 1, 0, 0, 0) + mactime = starttime + timedelta(minutes=self.mfg_date) + return mactime + + @property + def language(self): + self._language = 25 + return self._language + + @property + def mfg_date(self): + return self._mfg_date + + @mfg_date.setter + def mfg_date(self, val): + self._mfg_date = val + + @property + def boardversion(self): + self._boardversion = self.COMMON_HEAD_VERSION + return self._boardversion + + @property + def fruFileId(self): + return self._FRUFileID + + @fruFileId.setter + def fruFileId(self, val): + self._FRUFileID = val + + @property + def boardPartNumber(self): + return self._boardPartNumber + + @boardPartNumber.setter + def boardPartNumber(self, val): + self._boardPartNumber = val + + @property + def boardSerialNumber(self): + return self._boardSerialNumber + + @boardSerialNumber.setter + def boardSerialNumber(self, val): + self._boardSerialNumber = val + + @property + def boardProductName(self): + return self._boradProductName + + @boardProductName.setter + def boardProductName(self, val): + self._boradProductName = val + + @property + def boardManufacturer(self): + return self._boardManufacturer + + @boardManufacturer.setter + def boardManufacturer(self, val): + self._boardManufacturer = val + + @property + def boardTime(self): + return self._boardTime + + @boardTime.setter + def boardTime(self, val): + self._boardTime = val + + @property + def fields(self): + return self._fields + + @fields.setter + def fields(self, val): + self._fields = val + + +class ProductInfoArea(BaseArea): + _productManufacturer = None + _productAssetTag = None + _FRUFileID = None + + def __str__(self): + formatstr = "version : %x\n" \ + "length : %d \n" \ + "language : %x \n" \ + "productManufacturer : %s \n" \ + "productName : %s \n" \ + "productPartModelName: %s \n" \ + "productVersion : %s \n" \ + "productSerialNumber : %s \n" \ + "productAssetTag : %s \n" \ + "fruFileId : %s \n" + + tmpstr = formatstr % (ord(self.areaversion), self.size, + self.language, self.productManufacturer, + self.productName, self.productPartModelName, + self.productVersion, self.productSerialNumber, + self.productAssetTag, self.fruFileId) + + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + tmpstr += "productextra%d : %s \n" % (i, valtmpval) + else: + break + + return tmpstr + + def todict(self): + dic = collections.OrderedDict() + dic["productversion"] = ord(self.areaversion) + dic["productlength"] = self.size + dic["productlanguage"] = self.language + dic["productManufacturer"] = self.productManufacturer + dic["productName"] = self.productName + dic["productPartModelName"] = self.productPartModelName + dic["productVersion"] = int(self.productVersion, 16) + dic["productSerialNumber"] = self.productSerialNumber + dic["productAssetTag"] = self.productAssetTag + dic["productfruFileId"] = self.fruFileId + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + dic[valtmp] = valtmpval + else: + break + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] # 0 + index += 1 + d_print("decode length %d" % (ord(self.data[index]) * 8)) + d_print("class size %d" % self.size) + index += 2 + + templen = FruUtil.decodeLength(self.data[index]) + self.productManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productManufacturer:%s" % self.productManufacturer) + + templen = FruUtil.decodeLength(self.data[index]) + self.productName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productName:%s" % self.productName) + + templen = FruUtil.decodeLength(self.data[index]) + self.productPartModelName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productPartModelName:%s" % self.productPartModelName) + + templen = FruUtil.decodeLength(self.data[index]) + self.productVersion = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productVersion:%s" % self.productVersion) + + templen = FruUtil.decodeLength(self.data[index]) + self.productSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productSerialNumber:%s" % self.productSerialNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.productAssetTag = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productAssetTag:%s" % self.productAssetTag) + + templen = FruUtil.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + for i in range(1, 11): + valtmp = "productextra%d" % i + if self.data[index] != chr(0xc1) and index < self.size - 1: + templen = FruUtil.decodeLength(self.data[index]) + if templen == 0: + break + tmpval = self.data[index + 1: index + templen + 1] + d_print("decode boardextra%d:%s" % (i, tmpval)) + setattr(self, valtmp, tmpval) + index += templen + 1 + else: + break + + @property + def productVersion(self): + return self._productVersion + + @productVersion.setter + def productVersion(self, name): + self._productVersion = name + + @property + def areaversion(self): + self._areaversion = self.COMMON_HEAD_VERSION + return self._areaversion + + @areaversion.setter + def areaversion(self, name): + self._areaversion = name + + @property + def language(self): + self._language = 25 + return self._language + + @property + def productManufacturer(self): + return self._productManufacturer + + @productManufacturer.setter + def productManufacturer(self, name): + self._productManufacturer = name + + @property + def productName(self): + return self._productName + + @productName.setter + def productName(self, name): + self._productName = name + + @property + def productPartModelName(self): + return self._productPartModelName + + @productPartModelName.setter + def productPartModelName(self, name): + self._productPartModelName = name + + @property + def productSerialNumber(self): + return self._productSerialNumber + + @productSerialNumber.setter + def productSerialNumber(self, name): + self._productSerialNumber = name + + @property + def productAssetTag(self): + return self._productAssetTag + + @productAssetTag.setter + def productAssetTag(self, name): + self._productAssetTag = name + + @property + def fruFileId(self): + return self._FRUFileID + + @fruFileId.setter + def fruFileId(self, name): + self._FRUFileID = name + + def recalcute(self): + d_print("product version:%x" % ord(self.areaversion)) + d_print("product length:%d" % self.size) + d_print("product language:%x" % self.language) + self.data = chr(ord(self.areaversion)) + \ + chr(self.size / 8) + chr(self.language) + + typelength = FruUtil.getTypeLength(self.productManufacturer) + self.data += chr(typelength) + self.data += self.productManufacturer + + self.data += chr(FruUtil.getTypeLength(self.productName)) + self.data += self.productName + + self.data += chr(FruUtil.getTypeLength(self.productPartModelName)) + self.data += self.productPartModelName + + self.data += chr(FruUtil.getTypeLength(self.productVersion)) + self.data += self.productVersion + + self.data += chr(FruUtil.getTypeLength(self.productSerialNumber)) + self.data += self.productSerialNumber + + self.data += chr(FruUtil.getTypeLength(self.productAssetTag)) + if self.productAssetTag is not None: + self.data += self.productAssetTag + + self.data += chr(FruUtil.getTypeLength(self.fruFileId)) + self.data += self.fruFileId + + # To determine whether an extension field exists, the extension field must be in order + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + d_print("boardInfoArea productextra%d:%s" % (i, valtmpval)) + self.data += chr(FruUtil.getTypeLength(valtmpval)) + if valtmpval is None: + pass + else: + self.data += valtmpval + else: + break + + self.data += chr(0xc1) + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + d_print("self.data:%d" % len(self.data)) + d_print("self.size:%d" % self.size) + + self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:] + self.data = self.data.ljust((self.size - 1), self.INITVALUE) + checksum = FruUtil.checksum(self.data) + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + +class MultiRecordArea(BaseArea): + pass + + +class Field(): + + def __init__(self, fieldType="ASCII", fieldData=""): + self.fieldData = fieldData + self.fieldType = fieldType + + @property + def data(self): + return self._data + + @property + def fieldType(self): + return self._fieldType + + @property + def fieldData(self): + return self._fieldData + + +class ipmifru(BaseArea): + _BoardInfoArea = None + _ProductInfoArea = None + _InternalUseArea = None + _ChassisInfoArea = None + _multiRecordArea = None + _productinfoAreaOffset = BaseArea.INITVALUE + _boardInfoAreaOffset = BaseArea.INITVALUE + _internalUserAreaOffset = BaseArea.INITVALUE + _chassicInfoAreaOffset = BaseArea.INITVALUE + _multiRecordAreaOffset = BaseArea.INITVALUE + _bindata = None + _bodybin = None + _version = BaseArea.COMMON_HEAD_VERSION + _zeroCheckSum = None + _frusize = 256 + + def __str__(self): + tmpstr = "" + if self.boardInfoArea.isPresent: + tmpstr += "\nboardinfoarea: \n" + tmpstr += self.boardInfoArea.__str__() + if self.productInfoArea.isPresent: + tmpstr += "\nproductinfoarea: \n" + tmpstr += self.productInfoArea.__str__() + return tmpstr + + def decodeBin(self, eeprom): + commonHead = eeprom[0:8] + d_print("decode version %x" % ord(commonHead[0])) + if self.COMMON_HEAD_VERSION != commonHead[0]: + raise FruException("HEAD VERSION error,not Fru format!", -10) + if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]): + strtemp = "check header checksum error [cal:%02x data:%02x]" % ( + FruUtil.checksum(commonHead[0:7]), ord(commonHead[7])) + raise FruException(strtemp, -3) + if commonHead[1] != self.INITVALUE: + d_print("Internal Use Area is present") + self.internalUseArea = InternalUseArea( + name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) + self.internalUseArea.isPresent = True + self.internalUserAreaOffset = ord(commonHead[1]) + self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( + self.internalUserAreaOffset * 8 + self.internalUseArea.size)] + if commonHead[2] != self.INITVALUE: + d_print("Chassis Info Area is present") + self.chassisInfoArea = ChassisInfoArea( + name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) + self.chassisInfoArea.isPresent = True + self.chassicInfoAreaOffset = ord(commonHead[2]) + self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( + self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] + if commonHead[3] != self.INITVALUE: + self.boardInfoArea = BoardInfoArea( + name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) + self.boardInfoArea.isPresent = True + self.boardInfoAreaOffset = ord(commonHead[3]) + self.boardInfoArea.size = ord( + eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 + d_print("Board Info Area is present size:%d" % + (self.boardInfoArea.size)) + self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( + self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] + if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): + strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" % \ + (FruUtil.checksum( + self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:])) + raise FruException(strtmp, -3) + self.boardInfoArea.decodedata() + if commonHead[4] != self.INITVALUE: + d_print("Product Info Area is present") + self.productInfoArea = ProductInfoArea( + name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) + self.productInfoArea.isPresent = True + self.productinfoAreaOffset = ord(commonHead[4]) + d_print("length offset value: %02x" % + ord(eeprom[self.productinfoAreaOffset * 8 + 1])) + self.productInfoArea.size = ord( + eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 + d_print("Product Info Area is present size:%d" % + (self.productInfoArea.size)) + + self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( + self.productinfoAreaOffset * 8 + self.productInfoArea.size)] + if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): + strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % ( + FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:])) + raise FruException(strtmp, -3) + self.productInfoArea.decodedata() + if commonHead[5] != self.INITVALUE: + self.multiRecordArea = MultiRecordArea( + name="MultiRecord record Area ") + d_print("MultiRecord record present") + self.multiRecordArea.isPresent = True + self.multiRecordAreaOffset = ord(commonHead[5]) + self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( + self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] + + def initDefault(self): + self.version = self.COMMON_HEAD_VERSION + self.internalUserAreaOffset = self.INITVALUE + self.chassicInfoAreaOffset = self.INITVALUE + self.boardInfoAreaOffset = self.INITVALUE + self.productinfoAreaOffset = self.INITVALUE + self.multiRecordAreaOffset = self.INITVALUE + self.PAD = self.INITVALUE + self.zeroCheckSum = self.INITVALUE + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + self.productInfoArea = None + self.internalUseArea = None + self.boardInfoArea = None + self.chassisInfoArea = None + self.multiRecordArea = None + # self.recalcute() + + @property + def version(self): + return self._version + + @version.setter + def version(self, name): + self._version = name + + @property + def internalUserAreaOffset(self): + return self._internalUserAreaOffset + + @internalUserAreaOffset.setter + def internalUserAreaOffset(self, obj): + self._internalUserAreaOffset = obj + + @property + def chassicInfoAreaOffset(self): + return self._chassicInfoAreaOffset + + @chassicInfoAreaOffset.setter + def chassicInfoAreaOffset(self, obj): + self._chassicInfoAreaOffset = obj + + @property + def productinfoAreaOffset(self): + return self._productinfoAreaOffset + + @productinfoAreaOffset.setter + def productinfoAreaOffset(self, obj): + self._productinfoAreaOffset = obj + + @property + def boardInfoAreaOffset(self): + return self._boardInfoAreaOffset + + @boardInfoAreaOffset.setter + def boardInfoAreaOffset(self, obj): + self._boardInfoAreaOffset = obj + + @property + def multiRecordAreaOffset(self): + return self._multiRecordAreaOffset + + @multiRecordAreaOffset.setter + def multiRecordAreaOffset(self, obj): + self._multiRecordAreaOffset = obj + + @property + def zeroCheckSum(self): + return self._zeroCheckSum + + @zeroCheckSum.setter + def zeroCheckSum(self, obj): + self._zeroCheckSum = obj + + @property + def productInfoArea(self): + return self._ProductInfoArea + + @productInfoArea.setter + def productInfoArea(self, obj): + self._ProductInfoArea = obj + + @property + def internalUseArea(self): + return self._InternalUseArea + + @internalUseArea.setter + def internalUseArea(self, obj): + self.internalUseArea = obj + + @property + def boardInfoArea(self): + return self._BoardInfoArea + + @boardInfoArea.setter + def boardInfoArea(self, obj): + self._BoardInfoArea = obj + + @property + def chassisInfoArea(self): + return self._ChassisInfoArea + + @chassisInfoArea.setter + def chassisInfoArea(self, obj): + self._ChassisInfoArea = obj + + @property + def multiRecordArea(self): + return self._multiRecordArea + + @multiRecordArea.setter + def multiRecordArea(self, obj): + self._multiRecordArea = obj + + @property + def bindata(self): + return self._bindata + + @bindata.setter + def bindata(self, obj): + self._bindata = obj + + @property + def bodybin(self): + return self._bodybin + + @bodybin.setter + def bodybin(self, obj): + self._bodybin = obj + + def recalcuteCommonHead(self): + self.bindata = "" + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + d_print("common Header %d" % self.offset) + d_print("fru eeprom size %d" % self._frusize) + if self.internalUseArea is not None and self.internalUseArea.isPresent: + self.internalUserAreaOffset = self.offset / 8 + self.offset += self.internalUseArea.size + d_print("internalUseArea is present offset:%d" % self.offset) + + if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: + self.chassicInfoAreaOffset = self.offset / 8 + self.offset += self.chassisInfoArea.size + d_print("chassisInfoArea is present offset:%d" % self.offset) + + if self.boardInfoArea is not None and self.boardInfoArea.isPresent: + self.boardInfoAreaOffset = self.offset / 8 + self.offset += self.boardInfoArea.size + d_print("boardInfoArea is present offset:%d" % self.offset) + d_print("boardInfoArea is present size:%d" % + self.boardInfoArea.size) + + if self.productInfoArea is not None and self.productInfoArea.isPresent: + self.productinfoAreaOffset = self.offset / 8 + self.offset += self.productInfoArea.size + d_print("productInfoArea is present offset:%d" % self.offset) + + if self.multiRecordArea is not None and self.multiRecordArea.isPresent: + self.multiRecordAreaOffset = self.offset / 8 + d_print("multiRecordArea is present offset:%d" % self.offset) + + if self.internalUserAreaOffset == self.INITVALUE: + self.internalUserAreaOffset = 0 + if self.productinfoAreaOffset == self.INITVALUE: + self.productinfoAreaOffset = 0 + if self.chassicInfoAreaOffset == self.INITVALUE: + self.chassicInfoAreaOffset = 0 + if self.boardInfoAreaOffset == self.INITVALUE: + self.boardInfoAreaOffset = 0 + if self.multiRecordAreaOffset == self.INITVALUE: + self.multiRecordAreaOffset = 0 + + self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset + - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff + d_print("zerochecksum:%x" % self.zeroCheckSum) + self.data = self.version + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( + self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + self.INITVALUE + chr(self.zeroCheckSum) + + self.bindata = self.data + self.bodybin + totallen = len(self.bindata) + d_print("totallen %d" % totallen) + if (totallen < self._frusize): + self.bindata = self.bindata.ljust(self._frusize, self.INITVALUE) + else: + raise FruException('bin data more than %d' % self._frusize, -2) + + def recalcutebin(self): + self.bodybin = "" + if self.internalUseArea is not None and self.internalUseArea.isPresent: + d_print("internalUseArea present") + self.bodybin += self.internalUseArea.data + if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: + d_print("chassisInfoArea present") + self.bodybin += self.chassisInfoArea.data + if self.boardInfoArea is not None and self.boardInfoArea.isPresent: + d_print("boardInfoArea present") + self.boardInfoArea.recalcute() + self.bodybin += self.boardInfoArea.data + if self.productInfoArea is not None and self.productInfoArea.isPresent: + d_print("productInfoAreapresent") + self.productInfoArea.recalcute() + self.bodybin += self.productInfoArea.data + if self.multiRecordArea is not None and self.multiRecordArea.isPresent: + d_print("multiRecordArea present") + self.bodybin += self.productInfoArea.data + + def recalcute(self, fru_eeprom_size = 256): + self._frusize = fru_eeprom_size + self.recalcutebin() + self.recalcuteCommonHead() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/onietlv.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/onietlv.py new file mode 100644 index 000000000000..4e8e868a108b --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/eepromutil/onietlv.py @@ -0,0 +1,451 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import binascii +import sys + + +class OnietlvException(Exception): + def __init__(self, message='onietlverror', code=-100): + err = 'errcode: {0} message:{1}'.format(code, message) + Exception.__init__(self, err) + self.code = code + self.message = message + +class onie_tlv(): + TLV_INFO_ID_STRING = "TlvInfo\x00" + TLV_INFO_INIA_ID = "\x00\x00\x13\x11" + TLV_INFO_VERSION = 0x01 + TLV_INFO_LENGTH = 0x00 + TLV_INFO_LENGTH_VALUE = 0xba + + TLV_CODE_PRODUCT_NAME = 0x21 + TLV_CODE_PART_NUMBER = 0x22 + TLV_CODE_SERIAL_NUMBER = 0x23 + TLV_CODE_MAC_BASE = 0x24 + TLV_CODE_MANUF_DATE = 0x25 + TLV_CODE_DEVICE_VERSION = 0x26 + TLV_CODE_LABEL_REVISION = 0x27 + TLV_CODE_PLATFORM_NAME = 0x28 + TLV_CODE_ONIE_VERSION = 0x29 + TLV_CODE_MAC_SIZE = 0x2A + TLV_CODE_MANUF_NAME = 0x2B + TLV_CODE_MANUF_COUNTRY = 0x2C + TLV_CODE_VENDOR_NAME = 0x2D + TLV_CODE_DIAG_VERSION = 0x2E + TLV_CODE_SERVICE_TAG = 0x2F + TLV_CODE_VENDOR_EXT = 0xFD + TLV_CODE_CRC_32 = 0xFE + _TLV_DISPLAY_VENDOR_EXT = 1 + TLV_CODE_RJ_CARID = 0x01 + _TLV_INFO_HDR_LEN = 11 + TLV_CODE_PRODUCT_ID = 0x40 + TLV_CODE_HW_VERSION = 0x41 + TLV_CODE_MAIN_FILENAME = 0x42 + TLV_CODE_DTS_FINENAME = 0x43 + TLV_CODE_SY_SERIAL0 = 0x44 + TLV_CODE_SY_SERIAL1 = 0x45 + TLV_CODE_SY_SERIAL2 = 0x46 + TLV_CODE_SY_SERIAL3 = 0x47 + TLV_CODE_PROJECT_ID = 0x48 + TLV_CODE_SETMAC_VERSION = 0x49 + TLV_CODE_EEPROM_TYPE = 0x4A + + + @property + def dstatus(self): + return self._dstatus + + @property + def cardid(self): + return self._cardid + + @property + def productname(self): + return self._productname + + @property + def partnum(self): + return self._partnum + + @property + def serialnum(self): + return self._serialnum + + @property + def macbase(self): + return self._macbase + + @property + def manufdate(self): + return self._manufdate + + @property + def deviceversion(self): + return self._deviceversion + + @property + def labelrevision(self): + return self._labelrevision + + @property + def platformname(self): + return self._platformname + + @property + def onieversion(self): + return self._onieversion + + @property + def macsize(self): + return self._macsize + + @property + def manufname(self): + return self._manufname + + @property + def manufcountry(self): + return self._manufcountry + + @property + def vendorname(self): + return self._vendorname + + @property + def diagname(self): + return self._diagname + + @property + def servicetag(self): + return self._servicetag + + @property + def vendorext(self): + return self._vendorext + + @property + def fanbus(self): + return self._fanbus + + @property + def fanloc(self): + return self._fanloc + + def __init__(self): + self._cardid = "" + self._productname = "" + self._partnum = "" + self._serialnum = "" + self._macbase = "" + self._manufdate = "" + self._deviceversion = "" + self._labelrevision = "" + self._platformname = "" + self._onieversion = "" + self._macsize = "" + self._manufname = "" + self._manufcountry = "" + self._vendorname = "" + self._diagname = "" + self._servicetag = "" + self._vendorext = "" + self._productid = "" + self._hwversion = "" + self._mainfilename = "" + self._dtsfilename = "" + self._syserial0 = "" + self._syserial1 = "" + self._syserial2 = "" + self._syserial3 = "" + self._projectid = "" + self._setmacversion = "" + self._eepromtype = "" + self._crc32 = "" + self._dstatus = 0 + + def oniecrc32(self,v): + return '0x%08x' % (binascii.crc32(v) & 0xffffffff) # Take the octet data %x of CRC32 to return hexadecimal + + def getTLV_BODY(self,type, value): + x = [] + temp_t = "" + if type == self.TLV_CODE_MAC_BASE: + arr = value.split(':') + for tt in arr: + temp_t += chr(int(tt, 16)) + elif type == self.TLV_CODE_DEVICE_VERSION: + temp_t = chr(value) + elif type == self.TLV_CODE_MAC_SIZE: + temp_t = chr(value >> 8) + chr(value & 0x00ff) + else: + temp_t = value + x.append(chr(type)) + x.append(chr(len(temp_t))) + for i in temp_t: + x.append(i) + return x + + def generate_ext(self,cardid): + s = "%08x" % cardid + ret = "" + for t in range(0, 4): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + ret = chr(0x01) + chr(len(ret)) + ret + return ret + + def generate_value(self,_t): + ret = [] + for i in self.TLV_INFO_ID_STRING: + ret.append(i) + ret.append(chr(self.TLV_INFO_VERSION)) + ret.append(chr(self.TLV_INFO_LENGTH)) + ret.append(chr(self.TLV_INFO_LENGTH_VALUE)) + + total_len = 0 + for key in _t: + x = self.getTLV_BODY(key, _t[key]) + ret += x + total_len += len(x) + ret[10] = chr(total_len + 6) + + ret.append(chr(0xFE)) + ret.append(chr(0x04)) + s = self.oniecrc32(''.join(ret)) + for t in range(0, 4): + ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16))) + totallen = len(ret) + if (totallen < 256): + for left_t in range(0, 256 - totallen): + ret.append(chr(0x00)) + return (ret, True) + + def decode_tlv(self, e): + tlv_index = 0 + tlv_end = len(e) + ret = [] + while tlv_index < tlv_end and (tlv_index + 2 + ord(e[tlv_index + 1])) <= len(e): + rt = self.decoder(e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])]) + ret.append(rt) + if ord(e[tlv_index]) == self.TLV_CODE_CRC_32: + break + tlv_index += ord(e[tlv_index + 1]) + 2 + return ret + + + + def decode(self, e): + if e[0:8] != self.TLV_INFO_ID_STRING: + raise OnietlvException("ONIE tlv head info error,not onie tlv type", -1) + total_len = (ord(e[9]) << 8) | ord(e[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_len + if tlv_end > len(e): + raise OnietlvException("ONIE tlv length error", -2) + ret = [] + ret = self.decode_tlv(e[tlv_index:tlv_end]) + for item in ret: + if item['code'] == self.TLV_CODE_VENDOR_EXT: + if item["value"][0:4] == self.TLV_INFO_INIA_ID: + rt = self.decode_tlv(item["value"][4:]) + else: + rt = self.decode_tlv(item["value"][0:]) + ret.extend(rt) + return ret + + def decoder(self, t): + if ord(t[0]) == self.TLV_CODE_PRODUCT_NAME: + name = "Product Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._productname = value + elif ord(t[0]) == self.TLV_CODE_PART_NUMBER: + name = "Part Number" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._partnum = value + elif ord(t[0]) == self.TLV_CODE_SERIAL_NUMBER: + name = "Serial Number" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._serialnum = value + elif ord(t[0]) == self.TLV_CODE_MAC_BASE: + name = "Base MAC Address" + _len = ord(t[1]) + value = ":".join([binascii.b2a_hex(T) for T in t[2:8]]).upper() + self._macbase = value + elif ord(t[0]) == self.TLV_CODE_MANUF_DATE: + name = "Manufacture Date" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._manufdate = value + elif ord(t[0]) == self.TLV_CODE_DEVICE_VERSION: + name = "Device Version" + _len = ord(t[1]) + value = ord(t[2]) + self._deviceversion = value + elif ord(t[0]) == self.TLV_CODE_LABEL_REVISION: + name = "Label Revision" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._labelrevision = value + elif ord(t[0]) == self.TLV_CODE_PLATFORM_NAME: + name = "Platform Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._platformname = value + elif ord(t[0]) == self.TLV_CODE_ONIE_VERSION: + name = "ONIE Version" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._onieversion = value + elif ord(t[0]) == self.TLV_CODE_MAC_SIZE: + name = "MAC Addresses" + _len = ord(t[1]) + value = str((ord(t[2]) << 8) | ord(t[3])) + self._macsize = value + elif ord(t[0]) == self.TLV_CODE_MANUF_NAME: + name = "Manufacturer" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._manufname = value + elif ord(t[0]) == self.TLV_CODE_MANUF_COUNTRY: + name = "Manufacture Country" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._manufcountry = value + elif ord(t[0]) == self.TLV_CODE_VENDOR_NAME: + name = "Vendor Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._vendorname = value + elif ord(t[0]) == self.TLV_CODE_DIAG_VERSION: + name = "Diag Version" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._diagname = value + elif ord(t[0]) == self.TLV_CODE_SERVICE_TAG: + name = "Service Tag" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._servicetag = value + elif ord(t[0]) == self.TLV_CODE_VENDOR_EXT: + name = "Vendor Extension" + _len = ord(t[1]) + value = "" + if self._TLV_DISPLAY_VENDOR_EXT: + value = t[2:2 + ord(t[1])] + self._vendorext = value + elif ord(t[0]) == self.TLV_CODE_CRC_32 and len(t) == 6: + name = "CRC-32" + _len = ord(t[1]) + value = "0x%08X" % (((ord(t[2]) << 24) | ( + ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) + self._crc32 = value + elif ord(t[0]) == self.TLV_CODE_RJ_CARID: + name = "Card id" + _len = ord(t[1]) + value = "" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + self._cardid = value + elif ord(t[0]) == self.TLV_CODE_PRODUCT_ID: + name = "Product id" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._productid = value + elif ord(t[0]) == self.TLV_CODE_HW_VERSION: + name = "Hardware Version" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._hwversion = value + elif ord(t[0]) == self.TLV_CODE_MAIN_FILENAME: + name = "Main File Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._mainfilename = value + elif ord(t[0]) == self.TLV_CODE_DTS_FINENAME: + name = "DTS File Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._dtsfilename = value + elif ord(t[0]) == self.TLV_CODE_SY_SERIAL0: + name = "SY Serial 0" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._syserial0 = value + elif ord(t[0]) == self.TLV_CODE_SY_SERIAL1: + name = "SY Serial 1" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._syserial1 = value + elif ord(t[0]) == self.TLV_CODE_SY_SERIAL2: + name = "SY Serial 2" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._syserial2 = value + elif ord(t[0]) == self.TLV_CODE_SY_SERIAL3: + name = "SY Serial 3" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._syserial3 = value + elif ord(t[0]) == self.TLV_CODE_PROJECT_ID: + name = "Project id" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._projectid = value + elif ord(t[0]) == self.TLV_CODE_SETMAC_VERSION: + name = "Setmac Version" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._setmacversion = value + elif ord(t[0]) == self.TLV_CODE_EEPROM_TYPE: + name = "EEPROM Type" + _len = ord(t[1]) + value = "" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + self._eepromtype = value + else: + name = "Unknown" + _len = ord(t[1]) + value = "" + for c in t[2:2 + ord(t[1])]: + value += "0x%02X " % (ord(c),) + return {"name": name, "code": ord(t[0]), "value": value,"lens": _len} + + def __str__(self): + formatstr = "Card id : %s \n" \ + "Product Name : %s \n" \ + "Part Number : %s \n" \ + "Serial Number : %s \n" \ + "Base MAC Address : %s \n" \ + "Manufacture Date : %s \n" \ + "Device Version : %s \n" \ + "Label Revision : %s \n" \ + "Platform Name : %s \n" \ + "ONIE Version : %s \n" \ + "MAC Addresses : %s \n" \ + "Manufacturer : %s \n" \ + "Manufacture Country : %s \n" \ + "Vendor Name : %s \n" \ + "Diag Version : %s \n" \ + "Service Tag : %s \n" \ + "CRC-32 : %s \n" + return formatstr % (self._cardid, + self._productname, + self._partnum, + self._serialnum, + self._macbase, + self._manufdate, + self._deviceversion, + self._labelrevision, + self._platformname, + self._onieversion, + self._macsize, + self._manufname, + self._manufcountry, + self._vendorname, + self._diagname, + self._servicetag, + self._crc32) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/__init__.py new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/__init__.py @@ -0,0 +1 @@ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/baseutil.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/baseutil.py new file mode 100644 index 000000000000..ec8975e25b66 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/baseutil.py @@ -0,0 +1,84 @@ +####################################################### +# +# baseutil.py +# Python implementation of the Class baseutil +# Original author: support@ragilenetworks.com +# +####################################################### + +import json +import subprocess +import imp +import re +import os +import syslog +from osutil import osutil + +SYSLOG_IDENTIFIER = "BMC" + +def getonieplatform(): + if not os.path.isfile('/host/machine.conf'): + return "" + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars.get("onie_platform") + +configfile_path = "/usr/lib/python2.7/dist-packages/" +platform = (getonieplatform()).replace("-","_") + +devicefile = (configfile_path + platform + "_device.py") +monitorfile = (configfile_path + platform + "_monitor.py") + +class baseutil: + + CONFIG_NAME = 'devices' + MONITOR_CONFIG_NAME = 'monitor' + UBOOT_ENV_URL = '/etc/device/uboot_env' + + @staticmethod + def get_config(): + real_path = devicefile + devices = imp.load_source(baseutil.CONFIG_NAME, real_path) + return devices.devices + + @staticmethod + def get_monitor_config(): + real_path = monitorfile + monitor = imp.load_source(baseutil.MONITOR_CONFIG_NAME, real_path) + return monitor.monitor + + @staticmethod + def get_productname(): + ret, val = osutil.command("cat %s |grep productname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL) + tmp = val.lower().replace('-', '_') + if ret != 0 or len(val) <= 0: + raise Exception("get productname error") + else: + return tmp + + @staticmethod + def get_platform(): + ret, val = osutil.command("cat %s |grep conffitname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL) + if ret != 0 or len(val) <= 0: + raise Exception("get platform error") + else: + return val + + @staticmethod + def get_product_fullname(): + ret, val = osutil.command("cat %s |grep productname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL) + if ret != 0 or len(val) <= 0: + raise Exception("get productname error") + else: + return val + + @staticmethod + def logger_debug(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/card.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/card.py new file mode 100644 index 000000000000..f396744a40f1 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/card.py @@ -0,0 +1,27 @@ +####################################################### +# +# card.py +# Python implementation of the Class card +# Original author: support@ragilenetworks.com +# +####################################################### +from led import led +from temp import temp + +class card: + def __init__(self, conf=None): + pass + def getled(): + pass + + def getname(): + pass + + def getTemps(): + pass + + def setled(): + pass + + def setname(): + pass \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/chassisbase.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/chassisbase.py new file mode 100644 index 000000000000..34d2f20c8d4d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/chassisbase.py @@ -0,0 +1,260 @@ +####################################################### +# +# chassisbase.py +# Python implementation of the Class chassisbase +# Original author: support@ragilenetworks.com +# +####################################################### +from dcdc import dcdc +from psu import psu +from led import led +from temp import temp +from fan import fan +from card import card +from sensor import sensor +# from cpld import cpld +# from bios import bios +# from bmc import bmc +# from cpu import cpu +from baseutil import baseutil + + +class chassisbase: + __psu_list = [] + __led_list = [] + __temp_list = [] + __fan_list = [] + __card_list = [] + __sensor_list = [] + __dcdc_list = [] + __cpld_list = [] + __bios_list = [] + __bmc_list = [] + __cpu = None + + def __init__(self, conftype = 0, conf = None): + # type: (object, object, object) -> object + """ + init chassisbase as order + + type = 0 use default conf, maybe auto find by platform + type = 1 use given conf, conf is not None + + BITMAP + bit 16 + bit 0 PSU + bit 1 LED + bit 2 TEMP + bit 3 fan + bit 4 card + bit 5 sensor + """ + __confTemp = None + + if conftype == 0: + # user + __confTemp = baseutil.get_config() + elif conftype == 1: + __confTemp = conf + + + # psu + psutemp = [] + psuconfig = __confTemp.get('psus') + for i in range(len((psuconfig))): + psu1 = psu(psuconfig[i]) + psutemp.append(psu1) + self.psu_list = psutemp + + # led + ledtemp = [] + ledconfig = __confTemp.get('leds') + for i in range(len((ledconfig))): + led1 = led(ledconfig[i]) + ledtemp.append(led1) + self.led_list = ledtemp + # temp + temptemp = [] + tempconfig = __confTemp.get('temps') + for i in range(len((tempconfig))): + temp1 = temp(tempconfig[i]) + temptemp.append(temp1) + self.temp_list = temptemp + # fan + fantemp = [] + fanconfig = __confTemp.get('fans') + for i in range(len((fanconfig))): + fan1 = fan(fanconfig[i]) + fantemp.append(fan1) + self.fan_list = fantemp + # card + cardtemp = [] + cardconfig = __confTemp.get('cards') + for i in range(len((cardconfig))): + card1 = card(cardconfig[i]) + cardtemp.append(card1) + self.card_list = cardtemp + + ''' + #dcdc + dcdctemp = [] + dcdcconfig = __confTemp.get('dcdc') + for i in range(len((dcdcconfig))): + dcdc1 = dcdc(dcdcconfig[i]) + dcdctemp.append(dcdc1) + self.dcdc_list = dcdctemp + ''' + + # dcdc + @property + def dcdc_list(self): + return self.__dcdc_list + + @dcdc_list.setter + def dcdc_list(self, val): + self.__dcdc_list = val + + # sensor + @property + def sensor_list(self): + return self.__sensor_list + + @sensor_list.setter + def sensor_list(self, val): + self.__sensor_list = val + + def get_sensor_byname(self, name): + tmp = self.sensor_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + # psu + @property + def psu_list(self): + return self.__psu_list + + + @psu_list.setter + def psu_list(self, val): + self.__psu_list = val + + def get_psu_byname(self, name): + tmp = self.psu_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + # fan + @property + def fan_list(self): + return self.__fan_list + + @fan_list.setter + def fan_list(self, val): + self.__fan_list = val + + def get_fan_byname(self, name): + tmp = self.fan_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + + # led + @property + def led_list(self): + return self.__led_list + + @led_list.setter + def led_list(self, val): + self.__led_list = val + + def get_ledlist_config(self): + pass + + def get_led_byname(self, name): + tmp = self.led_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + # temp + @property + def temp_list(self): + return self.__temp_list + + @temp_list.setter + def temp_list(self, val): + self.__temp_list = val + + def get_temp_byname(self, name): + tmp = self.temp_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + # cpld + @property + def cpld_list(self): + return self.__cpld_list + + @cpld_list.setter + def cpld_list(self, val): + self.__cpld_list = val + + def get_cpld_byname(self, name): + tmp = self.cpld_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + # bios + @property + def bios_list(self): + return self.__bios_list + + @bios_list.setter + def bios_list(self, val): + self.__bios_list = val + + def get_bios_byname(self, name): + tmp = self.bios_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + # bmc + @property + def bmc_list(self): + return self.__bmc_list + + @bmc_list.setter + def bmc_list(self, val): + self.__bmc_list = val + + def get_bmc_byname(self, name): + tmp = self.bmc_list + for i in range(len(tmp)): + if name == tmp[i].name: + return tmp[i] + return None + + # cpu + @property + def cpu(self): + return self.__cpu + + @cpu.setter + def cpu(self, val): + self.__cpu = val + + def get_cpu_byname(self, name): + return self.cpu diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/dcdc.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/dcdc.py new file mode 100644 index 000000000000..2b90a6bad32f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/dcdc.py @@ -0,0 +1,37 @@ +from devicebase import devicebase +from eepromutil.fru import * +from sensor import sensor +import collections + +class dcdc(devicebase): + __attr = None + __dcdc_ordict = None + def __init__(self, conf = None): + self.dcdc_ordict = collections.OrderedDict() + if conf is not None: + self.name = conf.get('name', None) + self.attr = conf.get('attr', None) + tmp = {} + for key in self.attr: + tmpdict= sensor(self.attr[key]) + tmp[key] = tmpdict + tmp_list = sorted(tmp.items(), key=lambda item: item[0]) + for member in tmp_list: + self.dcdc_ordict[member[0]] = member[1] + + @property + def dcdc_ordict(self): + return self.__dcdc_ordict + + @dcdc_ordict.setter + def dcdc_ordict(self, val): + self.__dcdc_ordict = val + + @property + def attr(self): + return self.__attr + + @attr.setter + def attr (self, val): + self.__attr = val + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/devicebase.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/devicebase.py new file mode 100644 index 000000000000..1b9162b1ef9f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/devicebase.py @@ -0,0 +1,175 @@ +####################################################### +# +# devicebase.py +# Python implementation of the Class devicebase +# Original author: support@ragilenetworks.com +# +####################################################### +from osutil import osutil +from baseutil import baseutil + +class devicebase(object): + _name = None + __error_ret = -99999 + + @property + def name(self): + return self._name + + @name.setter + def name(self, val): + self._name = val + + def dumpValueByI2c(self, bus, loc): + str = "" + for i in range(256): + ret,val = self.get_i2c(bus, loc, i) + str += chr(val) + return str + + def get_eeprom_info(self, conf): + if conf.get('way') == 'sysfs': + ret, eeprom = self.get_value(conf) + if ret is False: + return None + else: + eeprom = self.dumpValueByI2c(conf.get('bus'), conf.get('addr')) + return eeprom + + def get_value(self, config): + ''' + get value by config way + way i2c/sysfs/lpc + ''' + way = config.get("way") + if way == 'sysfs': + return self.get_sysfs(config.get("loc")) + elif way == "i2c": + bus = config.get("bus") + addr = config.get("addr") + offset = config.get("offset") + return self.get_i2c(bus, addr, offset) + elif way == "i2cword": + bus = config.get("bus") + addr = config.get("addr") + offset = config.get("offset") + return self.get_i2cword(bus, addr, offset) + elif way == "devmem": + addr = config.get("addr") + digit = config.get("digit") + mask = config.get("mask", None) + return self.get_devmem(addr, digit, mask) + elif way == "sdk": + type = config.get("type") + if type == "bcm_temp": + return self.getbcmtemp() + elif type == "bcm_reg": + reg = config.get("reg") + return self.getbcmreg(reg) + else: + raise Exception("cannot found sdk type deal") + else: + raise Exception("cannot found way deal") + + def get_sysfs(self, loc): + return self.getsysfs(loc) + + def getsysfs(self, loc): + ret,val = osutil.readsysfs(loc) + return ret , val + + def get_devmem(self, addr, digit, mask): + return osutil.getdevmem(addr, digit, mask) + + def get_i2cword(self, bus, addr, offset): + return self.geti2cword(bus, addr, offset) + + def geti2cword(self,bus,addr, offset): + ret,val = osutil.geti2cword(bus, addr, offset) + return ret, val + + def get_i2c(self, bus, addr, offset): + return self.geti2c(bus, addr, offset) + + def geti2c(self, bus, addr, offset): + ret,val = osutil.rji2cget(bus, addr, offset) + return ret , val + + def set_value(self, config, val): + ''' + get value by config way + way i2c/sysfs/lpc + ''' + way = config.get("way") + if way == 'sysfs': + return self.set_sysfs(config.get("loc"), "0x%02x" % val) + elif way == "i2c": + bus = config.get("bus") + addr = config.get("addr") + offset = config.get("offset") + return self.set_i2c(bus, addr, offset, val) + elif way == "i2cpec": + bus = config.get("bus") + addr = config.get("addr") + offset = config.get("offset") + return self.seti2c_byte_pec(bus, addr, offset, val) + elif way =='i2cword': + bus = config.get("bus") + addr = config.get("addr") + offset = config.get("offset") + return self.set_i2cword(bus, addr, offset, val) + elif way == "i2cwordpec": + bus = config.get("bus") + addr = config.get("addr") + offset = config.get("offset") + return self.set_i2cwordpec(bus, addr, offset, val) + + def set_sysfs(self, loc, value): + return self.setsysfs(loc, value) + + def setsysfs(self, loc, value): + return osutil.writesysfs(loc, value) + + def set_i2cword(self, bus, addr, offset, byte): + return self.seti2cword(bus, addr, offset, byte) + + def seti2cword(self, bus, addr, offset, byte): + return osutil.seti2cword(bus, addr, offset, byte) + + def set_i2cwordpec(self, bus, addr, offset, val): + return osutil.seti2cwordpec(bus, addr, offset, val) + + def seti2c_byte_pec(self, bus, addr, offset, val): + return osutil.seti2c_byte_pec(bus, addr, offset, val) + + def set_i2c(self, bus, addr, offset, byte): + return self.seti2c(bus, addr, offset, byte) + + def seti2c(self, bus, addr, offset, byte): + ret, val = osutil.rji2cset(bus, addr, offset, byte) + return ret, val + + def getbcmtemp(self): + try: + sta, ret = osutil.getmactemp() + if sta == True: + mac_aver = float(ret.get("average", self.__error_ret)) + mac_max = float(ret.get("maximum", self.__error_ret)) + mac_aver = mac_aver * 1000 + mac_max = mac_max * 1000 + else: + return False, ret + except AttributeError as e: + return False, str(e) + return True, mac_aver + + def getbcmreg(self, reg): + ret, val = osutil.getsdkreg(reg) + return ret, val + + def logger_debug(self, msg): + baseutil.logger_debug(msg) + + def command(self, cmd): + ret, output = osutil.command(cmd) + return ret, output diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/fan.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/fan.py new file mode 100644 index 000000000000..c270c5ab6356 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/fan.py @@ -0,0 +1,317 @@ +####################################################### +# +# fan.py +# Python implementation of the Class fan +# Original author: support@ragilenetworks.com +# +####################################################### +from devicebase import devicebase +from eepromutil.fru import * +from sensor import sensor +from rotor import rotor + +class fan(devicebase): + __rotor_list = [] + __pn = None + __raweeprom = None + __sn = None + __present = None + __e2loc = None + __rotors = None + __AirFlow = None + __SpeedMin = None + __SpeedMax = None + __productName = None + __productSerialNumber =None + __productPartModelName = None + __WatchdogStatus = None + __led_attrs_config = None + __led_config =None + __WatchdogStatus_config = None + __AirFlowconifg = None + __EnableWatchdogConf = None + __Rotor_config = None + + def __init__(self, conf = None): + if conf is not None: + self.name = conf.get('name', None) + self.sn = conf.get('sn', None) + self.present = conf.get('present', None) + self.e2loc = conf.get('e2loc', None) + self.SpeedMin = conf.get('SpeedMin', None) + self.SpeedMax = conf.get('SpeedMax', None) + self.AirFlowconifg = conf.get("airflow", None) + self.AirFlowconfig = conf.get('airflow', None) + self.WatchdogStatus_config = conf.get('WatchdogStatus', None) + self.EnableWatchdogConf = conf.get('EnableWatchdogConf', None) + self.led_attrs_config = conf.get('led_attrs', None) + self.led_config = conf.get('led', None) + self.Rotor_config = conf.get('Rotor', None) + rotor_tmp = [] + for key,value in (self.Rotor_config).items(): + rotor_tmp.append(rotor(value)) + rotor_tmp.sort(key=lambda x: x.name, reverse=False) + self.rotor_list = rotor_tmp + self.rotors = len(self.rotor_list) + @property + def EnableWatchdogConf(self): + return self.__EnableWatchdogConf + + @EnableWatchdogConf.setter + def EnableWatchdogConf(self, val): + self.__EnableWatchdogConf = val + + @property + def rotor_list(self): + return self.__rotor_list + + @rotor_list.setter + def rotor_list(self, val): + self.__rotor_list = val + + @property + def Rotor_config(self): + return self.__Rotor_config + + @Rotor_config.setter + def Rotor_config(self, val): + self.__Rotor_config = val + + @property + def productName(self): + return self.__productName + + @productName.setter + def productName(self, val): + self.__productName = val + + @property + def productSerialNumber(self): + return self.__productSerialNumber + + @productSerialNumber.setter + def productSerialNumber(self, val): + self.__productSerialNumber = val + + @property + def productPartModelName(self): + return self.__productPartModelName + + @productPartModelName.setter + def productPartModelName(self, val): + self.__productPartModelName = val + + @property + def sn(self): + return self.__sn + + @sn.setter + def sn(self, val): + self.__sn = val + + @property + def pn(self): + return self.__pn + + @pn.setter + def pn(self, val): + self.__pn = val + + @property + def raweeprom(self): + return self.__raweeprom + + @raweeprom.setter + def raweeprom(self, val): + self.__raweeprom = val + + @property + def SpeedMax(self): + return self.__SpeedMax + + @SpeedMax.setter + def SpeedMax(self, val): + self.__SpeedMax = val + + @property + def SpeedMin(self): + return self.__SpeedMin + + @SpeedMin.setter + def SpeedMin(self, val): + self.__SpeedMin = val + + @property + def rotors(self): + return self.__rotors + + @property + def AirFlow(self): + return self.__AirFlow + + @AirFlow.setter + def AirFlow(self, val): + self.__AirFlow = val + + @rotors.setter + def rotors(self, val): + self.__rotors = val + + def getspeed(self, conf): + tmp = None + if conf == None: + return -1 + ret, val = self.get_value(conf) + if ret == True: + tmp = int(str(val), 10) + else: + val = None + if val is not None: + return int(15000000 / tmp) + return -1 + + def get_speed(self, rotor_index): + rotor = self.get_rotor_index(rotor_index) + return int(rotor.rotor_Speed.Value) + + def set_led(self, color, blink): + status = self.led_attrs_config.get(color, None) + if status == None: + return False + if blink == True: + blink_status = self.led_attrs_config.get('flash', None) + elif blink == False: + blink_status = self.led_attrs_config.get('light', None) + if blink_status == None: + return False + byte = status & blink_status + ret, val = self.set_value(self.led_config, byte) + return ret + + def set_speed(self, rotor_index, level): + if level > 255 or level < 0 : + return False + rotor = self.get_rotor_index(rotor_index) + if rotor is None: + return False + ret, val = self.set_value(rotor.Speedconfig, int(level)) + return ret + + def get_rotor_index(self, rotor_index): + if rotor_index > len(self.rotor_list): + raise Exception("%s: rotor_index value is wrong" % self.name) + rotor = self.rotor_list[rotor_index - 1] + return rotor + + def get_rotor_byname(self, rotor_index): + for rotor in self.rotor_list: + if rotor.name == rotor_index: + return rotor + return None + + def get_presence(self): + ret , val = self.get_value(self.present) + mask = self.present.get("mask") + if (ret == False) or (val is None): + return False + flag = val & mask + if flag == 0: + return True + else: + return False + + def get_speed_pwm(self, rotor_index): + rotor = self.get_rotor_index(rotor_index) + if rotor is None: + return False + if rotor.i2c_speed is None: + return False + val = round(rotor.i2c_speed * 100 / 255) + return val + + def feed_watchdog(self, pwm): + ret = False + for rotor in self.rotor_list: + ret, val= rotor.feed_watchdog() + if ret is False: + return ret + return ret + + def get_fru_info(self): + try: + if self.get_presence() is False: + raise Exception("%s: not present" % self.name) + eeprom = self.get_eeprom_info(self.e2loc) + if eeprom is None: + raise Exception("%s: value is none" % self.name) + fru = ipmifru() + fru.decodeBin(eeprom) + self.productName = fru.productInfoArea.productName.strip() + self.productSerialNumber = fru.productInfoArea.productSerialNumber.strip() #SN + self.productPartModelName = fru.productInfoArea.productPartModelName.strip() #PN + except Exception as e: + self.productName = None + self.productSerialNumber = None + self.productPartModelName = None + return False + return True + + def get_AirFlow(self): + if self.productPartModelName == None: + ret = self.get_fru_info() + if ret is False: + self.AirFlow = None + return False + if self.AirFlowconifg == None: + self.AirFlow = None + return False + else: + for i in self.AirFlowconifg: + if self.productPartModelName in self.AirFlowconifg[i]: + self.AirFlow = i + return True + self.AirFlow = None + return False + + def enable_watchdog(self, enable, timeout_sec): + if enable == True: + byte = self.EnableWatchdogConf.get("enable_byte", None) + ret, val = self.set_value(self.EnableWatchdogConf, byte) + elif enable == False: + byte = self.EnableWatchdogConf.get("disable_byte", None) + ret, val = self.set_value(self.EnableWatchdogConf, byte) + return ret + + def get_watchdog_status(self): + dic = {"support": None , "open": None, "work_full":None, "work_allow_set":None} + if self.WatchdogStatus_config == None: + return None + ret , val = self.get_value(self.WatchdogStatus_config) + if (ret == False) or (val is None): + return None + support_watchdog_off = self.WatchdogStatus_config.get("support_watchdog_off", None) + is_open_off = self.WatchdogStatus_config.get("is_open_off", None) + full_running_off = self.WatchdogStatus_config.get("full_running_off", None) + running_setting_off = self.WatchdogStatus_config.get("running_setting_off", None) + if support_watchdog_off is not None: + if support_watchdog_off & val == self.WatchdogStatus_config.get("support_watchdog_mask", None): + dic["support"] = True + else: + dic["support"] = False + return dic + if is_open_off is not None: + if is_open_off & val == self.WatchdogStatus_config.get("is_open_mask", None): + dic["open"] = True + else: + dic["open"] = False + if full_running_off is not None: + if full_running_off & val == self.WatchdogStatus_config.get("full_running_mask", None): + dic["work_full"] = True + else: + dic["work_full"] = False + if running_setting_off is not None: + if running_setting_off & val == self.WatchdogStatus_config.get("running_setting_mask", None): + dic["work_allow_set"] = True + else: + dic["work_allow_set"] = False + return dic \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/interface.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/interface.py new file mode 100644 index 000000000000..0dc8762a08e8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/interface.py @@ -0,0 +1,1021 @@ +####################################################### +# +# interface.py +# Python implementation of the Class interface +# Original author: support@ragilenetworks.com +# +####################################################### +from chassisbase import chassisbase +import collections +from baseutil import baseutil +from osutil import osutil + +def Singleton(cls): + _instance = {} + + def _singleton(*args, **kargs): + if cls not in _instance: + _instance[cls] = cls(*args, **kargs) + return _instance[cls] + + return _singleton + +@Singleton +class interface(object): + __chas = None + __error_ret = None + + def __init__(self): + self.chas = chassisbase() + self.__error_ret = -99999 + self.__na_ret = 'N/A' + + @property + def na_ret(self): + return self.__na_ret + + @na_ret.setter + def na_ret(self, val): + self.__na_ret = val + + @property + def error_ret(self): + return self.__error_ret + + @error_ret.setter + def error_ret(self, val): + self.__error_ret = val + + @property + def chas(self): + return self.__chas + + @chas.setter + def chas(self, val): + self.__chas = val + + # temp + def get_temp_total_number(self): + templist = self.chas.temp_list + return len(templist) + + def get_temp_location(self, temp_name): + temp = self.chas.get_temp_byname(temp_name) + return temp.get_location() + + def set_temp_location(self, temp_name, location): + temp = self.chas.get_temp_byname(temp_name) + return temp.set_location(location) + + def set_temp_name(self, temp_name, name): + temp = self.chas.get_temp_byname(temp_name) + return temp.set_name(name) + + def get_appoint_temp(self, temp_name): + temp = self.chas.get_led_byname(temp_name) + return temp.get_temp() + + def set_appoint_temp(self, temp_name, val): + temp = self.chas.get_temp_byname(temp_name) + return temp.set_temp(val) + + def get_temp_mintemp(self, temp_name): + temp = self.chas.get_temp_byname(temp_name) + return temp.get_mintemp() + + def set_temp_mintemp(self, temp_name, val): + temp = self.chas.get_temp_byname(temp_name) + return temp.set_mintemp(val) + + # led + def get_led_total_number(self): + ledlist = self.chas.led_list + return len(ledlist) + + def get_led_color(self, led_name): + led = self.chas.get_led_byname(led_name) + return led.get_color() + + def set_led_color(self, led_name, color, blink): + led = self.chas.get_led_byname(led_name) + return led.set_color(color, blink) + + # psu + def get_psu_total_number(self): + psulist = self.chas.psu_list + return len(psulist) + + def get_psus(self): + psulist = self.chas.psu_list + return psulist + + def get_psu_presence(self, psu_name): + psu = self.chas.get_psu_byname(psu_name) + return psu.present + + def get_psu_fru_info(self, psu_name): + ''' + { + "Name": "PSU1", + "SN": "serial_number_example", # 'N/A' + "PN": "part_number_example", # 'N/A' + "AirFlow": "B2F" # 'N/A' + } + ''' + psu = self.chas.get_psu_byname(psu_name) + psu.get_fru_info() + psu.get_AirFlow() + + dic = collections.OrderedDict() + dic["Name"] = psu.name + dic["SN"] = psu.productSerialNumber if (psu.productSerialNumber is not None) else self.na_ret + dic["PN"] = psu.productPartModelName if (psu.productPartModelName is not None) else self.na_ret + dic["AirFlow"] = psu.AirFlow if (psu.AirFlow is not None) else self.na_ret + return dic + + def get_psu_input_output_status(self, psu_name): + psu = self.chas.get_psu_byname(psu_name) + if (psu.InputStatus == True) and (psu.OutputStatus == True): + status = True + else: + status = False + return status + + def get_psu_status(self, psu_name): + """ + Get status of a specific PSU + @return dict of the specific PSU's status, None for failure + Example return value(all keys are mandatory) + { + "Name": "PSU1", + "InputType": "DC", # "AC" or 'N/A' + "InputStatus": True, # H/W status bit + "OutputStatus": True # H/W status bit + "FanSpeed": { + "Value": 4000, # -99999 + "Min": 2000, # -99999 + "Max": 10000 # -99999 + }, + "Temperature": { + "Value": 40.0, # -99999.0 + "Min": -30.0, # -99999.0 + "Max": 50.0 # -99999.0 + } + } + """ + psu = self.chas.get_psu_byname(psu_name) + + dic = collections.OrderedDict() + # psu.get_Temperature() + temp_dict = collections.OrderedDict() + temp_dict['Min'] = psu.Temperature.Min + temp_dict['Max'] = psu.Temperature.Max + temp_dict['Value'] = psu.Temperature.Value + dic["Temperature"] = temp_dict + + # psu.get_FanSpeed() + fan_speed_dict = collections.OrderedDict() + fan_speed_dict['Min'] = psu.FanSpeed.Min + fan_speed_dict['Max'] = psu.FanSpeed.Max + fan_speed_dict['Value'] = psu.FanSpeed.Value + dic["FanSpeed"] = fan_speed_dict + + dic["Name"] = psu.name + dic["InputType"] = psu.InputsType + dic["InputStatus"] = psu.InputStatus + dic["OutputStatus"] = psu.OutputStatus + return dic + + def get_psu_power_status(self, psu_name): + """ + Get power status of a specific PSU + @return dict of the specific PSU's power status, None for failure + Example return value + { + "Name": "PSU1", + "Inputs": { + "Status": True, # H/W status bit + "Type": "DC", # or "AC" or "N/A" + "Voltage": { + "Value": 220, # -1 + "LowAlarm": 200, # -1 + "HighAlarm": 240, # -1 + "Unit": "V" + }, + "Current": { + "Value": 6.0, # -99999.0 + "LowAlarm": 0.2, # -99999.0 + "HighAlarm": 7.0, # -99999.0 + "Unit": "A" + }, + "Power": { + "Value": 1000, # -99999 + "LowAlarm": -1, # -99999 + "HighAlarm": 1400, # -99999 + "Unit": "W" + } + }, + "Outputs": { + "Status": True, + "Voltage": { + "Value": 220, + "LowAlarm": 200, + "HighAlarm": 240, + "Unit": "V" + }, + "Current": { + "Value": 6.0, + "LowAlarm": 0.2, + "HighAlarm": 7.0, + "Unit": "A" + }, + "Power": { + "Value": 1000, + "LowAlarm": -1, # Don't care + "HighAlarm": 1400, + "Unit": "W" + } + } + } + """ + psu = self.chas.get_psu_byname(psu_name) + + dic = collections.OrderedDict() + inputdic =collections.OrderedDict() + Outputsdic = collections.OrderedDict() + dic["Name"] = psu.name + inputdic["Status"] = psu.InputStatus + inputdic["Type"] = psu.InputsType + + # psu.get_InputsVoltage() + inputdic_voltage = collections.OrderedDict() + + inputdic_voltage["Value"] = psu.InputsVoltage.Value + inputdic_voltage["LowAlarm"] = psu.InputsVoltage.Min + inputdic_voltage["HighAlarm"] = psu.InputsVoltage.Max + inputdic_voltage["Unit"] = psu.InputsVoltage.Unit + + + inputdic["Voltage"] = inputdic_voltage + inputdic_current = collections.OrderedDict() + inputdic_current["Value"] = psu.InputsCurrent.Value + inputdic_current["LowAlarm"] = psu.InputsCurrent.Min + inputdic_current["HighAlarm"] = psu.InputsCurrent.Max + inputdic_current["Unit"] = psu.InputsCurrent.Unit + inputdic["Current"] = inputdic_current + + inputdic_power = collections.OrderedDict() + inputdic_power["Value"] = psu.InputsPower.Value + inputdic_power["LowAlarm"] = psu.InputsPower.Min + inputdic_power["HighAlarm"] = psu.InputsPower.Max + inputdic_power["Unit"] = psu.InputsPower.Unit + inputdic["Power"] = inputdic_power + Outputsdic["Status"] = psu.InputStatus + + outputdic_voltage =collections.OrderedDict() + outputdic_current = collections.OrderedDict() + outputdic_power = collections.OrderedDict() + + outputdic_voltage["Value"] = psu.OutputsVoltage.Value + outputdic_voltage["LowAlarm"] = psu.OutputsVoltage.Min + outputdic_voltage["HighAlarm"] = psu.OutputsVoltage.Max + outputdic_voltage["Unit"] = psu.OutputsVoltage.Unit + + outputdic_current["Value"] = psu.OutputsCurrent.Value + outputdic_current["LowAlarm"] = psu.OutputsCurrent.Min + outputdic_current["HighAlarm"] = psu.OutputsCurrent.Max + outputdic_current["Unit"] = psu.OutputsCurrent.Unit + + outputdic_power["Value"] = psu.OutputsPower.Value + outputdic_power["LowAlarm"] = psu.OutputsPower.Min + outputdic_power["HighAlarm"] = psu.OutputsPower.Max + outputdic_power["Unit"] = psu.OutputsPower.Unit + + + + Outputsdic["Voltage"] = outputdic_voltage + Outputsdic["Current"] = outputdic_current + Outputsdic["Power"] = outputdic_power + + + dic["Inputs"] = inputdic + dic["Outputs"] = Outputsdic + + return dic + + def set_psu_fan_speed_pwm(self, psu_name, pwm): + psu = self.chas.get_psu_byname(psu_name) + return psu.set_fan_speed_pwm(pwm) + + def get_psu_fan_speed_pwm(self, psu_name): + psu = self.chas.get_psu_byname(psu_name) + return psu.get_fan_speed_pwm() + + def get_psu_info_all(self): + """ + { + "Number": 2, + "PSU1": { + "SN": "serial_number_example", # 'N/A' + "PN": "part_number_example", # 'N/A' + "AirFlow": "F2B", # 'N/A' + + "FanSpeed": { + "Value": 4000, + "Min": 2000, + "Max": 30000 + }, + "Temperature": { + "Value": 35.0, + "Min": -20.0, + "Max": 45.0 + }, + "Inputs": { + "Status": True, # H/W status bit + "Type": "DC", # or "AC" + "Voltage": { + "Value": 220, + "LowAlarm": 200, + "HighAlarm": 240, + "Unit": "V" + }, + "Current": { + "Value": 6.0, + "LowAlarm": 0.2, + "HighAlarm": 7.0, + "Unit": "A" + }, + "Power": { + "Value": 1000, + "LowAlarm": -1, + "HighAlarm": 1400, + "Unit": "W" + } + }, + "Outputs": { + "Status": True, + "Voltage": { + "Value": 220, + "LowAlarm": 200, + "HighAlarm": 240, + "Unit": "V" + }, + "Current": { + "Value": 6.0, + "LowAlarm": 0.2, + "HighAlarm": 7.0, + "Unit": "A" + }, + "Power": { + "Value": 1000, + "LowAlarm": -1, # Don't care + "HighAlarm": 1400, + "Unit": "W" + } + } + } + } + """ + + psus = self.get_psus() + dict = collections.OrderedDict() + dict['Number'] = len(psus) + for psu in psus: + dicttmp = self.get_psu_fru_info(psu.name) + dicttmp.update(self.get_psu_status(psu.name)) + dicttmp.update(self.get_psu_power_status(psu.name)) + if self.get_psu_presence(psu.name) is True: + dicttmp['Present'] = 'yes' + else: + dicttmp['Present'] = 'no' + dict[psu.name] = dicttmp + return dict + + def get_fans(self): + fanlist = self.chas.fan_list + return fanlist + + # fan + def get_fan_total_number(self): + fanlist = self.chas.fan_list + if fanlist is None: + return -1 + return len(fanlist) + + def get_fan_rotor_number(self, fan_name): + fan = self.chas.get_fan_byname(fan_name) + ret = fan.rotors + if ret is None: + return -1 + return ret + + def get_fan_speed(self, fan_name, rotor_index): + fan = self.chas.get_fan_byname(fan_name) + ret = fan.get_speed(rotor_index) + if ret is None: + return -1 + return ret + + def set_fan_speed(self, fan_name, rotor_index, speed): + return -1 + + def fan_speed_set_level(self, fan_name, rotor_index, level): + fan = self.chas.get_fan_byname(fan_name) + ret = fan.set_speed(rotor_index, level) + if ret is True: + return 0 + else: + return -1 + + def get_fan_speed_pwm(self, fan_name, rotor_index): + fan = self.chas.get_fan_byname(fan_name) + val = fan.get_speed_pwm(rotor_index) + if val is None: + return -1 + return val + + def set_fan_speed_pwm(self, fan_name, rotor_index, pwm): + fan = self.chas.get_fan_byname(fan_name) + if isinstance(pwm, str): + rate = float(pwm.strip('%s')) + speed = round(rate * 255 / 100) + elif isinstance(pwm, int): + speed = round(pwm * 255 / 100) + elif isinstance(pwm, float): + speed = round(pwm * 255 / 100) + else: + return -1 + ret = self.fan_speed_set_level(fan.name, rotor_index, speed) + if ret == 0: + return 0 + return -1 + + def get_fan_watchdog_status(self): + fan = self.chas.fan_list[0] + dic = fan.get_watchdog_status() + if dic is None or dic["support"] == False: + return "N/A" + elif dic["open"] is False or dic["work_allow_set"] is True: + return "Normal" + elif dic["work_full"] is True: + return "Abnormal" + else: + return "Abnormal" + + + def enable_fan_watchdog(self, enable=True, timeout_sec=10): + fan = self.chas.fan_list[0] + ret = fan.enable_watchdog(enable, timeout_sec) + if ret is True: + return 0 + else: + return -1 + + def feed_fan_watchdog(self, pwm): + fan_list = self.chas.fan_list + if fan_list is None: + return -1 + for fan in fan_list: + ret = fan.feed_watchdog(pwm) + if ret is False: + return -1 + return 0 + + def set_fan_led(self, fan_name, color, blink = False): + fan = self.chas.get_fan_byname(fan_name) + ret = fan.set_led(color, blink) + if ret is True: + return 0 + else: + return -1 + + def get_fan_presence(self, fan_name): + fan = self.chas.get_fan_byname(fan_name) + return fan.get_presence() + + def get_fan_fru_info(self, fan_name): + """ + Get specific fan's information + # Properties + "Name": "FAN1", + "SN": "serial_number_example", # 'N/A' + "PN": "part_number_exampple", # 'N/A' + "Rotors": 2, # -1 + "AirFlow": "F2B", # 'N/A' + "SpeedMin": 2000, # -1 + "SpeedMax": 30000 # -1 + """ + fan = self.chas.get_fan_byname(fan_name) + fan.get_fru_info() + fan.get_AirFlow() + dic = collections.OrderedDict() + dic["Name"] = fan.name + dic["SN"] = fan.productSerialNumber + if dic["SN"] is None: + dic["SN"] = "N/A" + dic["PN"] = fan.productPartModelName + if dic["PN"] is None: + dic["PN"] = "N/A" + dic["Rotors"] = fan.rotors + dic["AirFlow"] = fan.AirFlow + if dic["AirFlow"] is None: + dic["AirFlow"] = "N/A" + dic["SpeedMin"] = fan.SpeedMin + dic["SpeedMax"] = fan.SpeedMax + return dic + + def get_product_fullname(self): + return baseutil.get_product_fullname() + + def get_fan_status(self, fan_name): + fan = self.chas.get_fan_byname(fan_name) + if fan is None: + return -1 + rotorlist = fan.rotor_list + dir = collections.OrderedDict() + for rotor in rotorlist: + dir_val = collections.OrderedDict() + if rotor.rotor_Running == True: + dir_val['Running'] = 'yes' + else: + dir_val['Running'] = 'no' + if rotor.rotor_HwAlarm == True: + dir_val['HwAlarm'] = 'yes' + else: + dir_val['HwAlarm'] = 'no' + dir_val['Speed'] = int(rotor.rotor_Speed.Value) + dir[rotor.name] = dir_val + return dir + + def get_fan_rotor_status(self, fan_name, rotor_name): + fan = self.chas.get_fan_byname(fan_name) + if fan is None: + return -1 + rotorlist = fan.rotor_list + for i in range(len(rotorlist)): + if rotor_name == rotorlist[i].name: + rotor = rotorlist[i] + if rotor.rotor_Running == True: + return True + else: + return False + return -1 + + def get_fan_info_fru(self, fan_name): + fan = self.chas.get_fan_byname(fan_name) + fan.get_fru_info() + fan.get_AirFlow() + dic = collections.OrderedDict() + dic["Name"] = fan.name + dic["SN"] = fan.productSerialNumber + if dic["SN"] is None: + dic["SN"] = "N/A" + dic["PN"] = fan.productPartModelName + if dic["PN"] is None: + dic["PN"] = "N/A" + flag = self.get_fan_presence(fan_name) + if flag is True: + dic["Present"] = "yes" + elif flag is False: + dic["Present"] = "no" + else: + dic["Present"] = "N/A" + dic["Rotors"] = fan.rotors + dic["AirFlow"] = fan.AirFlow + if dic["AirFlow"] is None: + dic["AirFlow"] = "N/A" + return dic + + def get_fan_info_rotor(self, fan_name): + fan = self.chas.get_fan_byname(fan_name) + if fan is None: + return -1 + rotorlist = fan.rotor_list + dir = collections.OrderedDict() + for rotor in rotorlist: + dir_val = collections.OrderedDict() + if rotor.rotor_Running == True: + dir_val['Running'] = 'yes' + else: + dir_val['Running'] = 'no' + if rotor.rotor_HwAlarm == True: + dir_val['HwAlarm'] = 'yes' + else: + dir_val['HwAlarm'] = 'no' + speed_value = rotor.rotor_Speed.Value + if speed_value is None: + dir_val['Speed'] = self.error_ret + else: + dir_val['Speed'] = int(speed_value) + if rotor.SpeedMin is None: + dir_val['SpeedMin'] = self.error_ret + else: + dir_val['SpeedMin'] = rotor.SpeedMin + if rotor.SpeedMax is None: + dir_val['SpeedMax'] = self.error_ret + else: + dir_val['SpeedMax'] = rotor.SpeedMax + + dir[rotor.name] = dir_val + return dir + + def get_fan_info_all(self): + fanlist = self.chas.fan_list + dic = collections.OrderedDict() + dic['Number'] = len(fanlist) + dic['WatchdogStatus'] = self.get_fan_watchdog_status() + for fan in fanlist: + dic[fan.name] = self.get_fan_info_fru(fan.name) + dic[fan.name].update(self.get_fan_info_rotor(fan.name)) + return dic + + def temp_test(self): + templist = self.chas.temp_list + dicret = collections.OrderedDict() + + for temp in templist: + dic = collections.OrderedDict() + dic["Value"] = temp.Value if (temp.Value is not None) else self.error_ret + dic["LowAlarm"] = temp.Min + dic["HighAlarm"] = temp.Max + dicret[temp.name] = dic + return dicret + + # sensors + def get_dcdc_all_info(self): + val_list = collections.OrderedDict() + dcdclist = self.chas.dcdc_list + for dcdc in dcdclist: + for name,sensor in dcdc.dcdc_ordict.items(): + dicttmp = collections.OrderedDict() + sensorname = "%s%s" % (dcdc.name, name) + dicttmp['Min'] = sensor.Min + dicttmp['Max'] = sensor.Max + dicttmp['Value'] = sensor.Value if (sensor.Value is not None) else self.error_ret + dicttmp['Unit'] = sensor.Unit + val_list[sensorname] = dicttmp + return val_list + def get_monitor_temp(self, name): + templist = self.chas.temp_list + temptmp = None + for temp in templist: + if temp.name == name: + temptmp = temp + + dic = collections.OrderedDict() + if temptmp is None: + dic["Min"] = self.error_ret + dic["Max"] = self.error_ret + dic["Value"] = self.error_ret + dic["Unit"] = self.error_ret + else: + dic["Min"] = temptmp.Min + dic["Max"] = temptmp.Max + dic["Value"] = temptmp.Value if (temptmp.Value is not None) else self.error_ret + dic["Unit"] = temptmp.Unit + return dic + + def get_temp_info(self): + val_list = collections.OrderedDict() + # temp + templist = self.chas.temp_list + for temp in templist: + dic = collections.OrderedDict() + dic["Min"] = temp.Min + dic["Max"] = temp.Max + dic["Value"] = temp.Value if (temp.Value is not None) else self.error_ret + dic["Unit"] = temp.Unit + val_list[temp.name] = dic + return val_list + + def get_sensor_info(self): + val_list = collections.OrderedDict() + # temp + templist = self.chas.temp_list + for temp in templist: + dic = collections.OrderedDict() + dic["Min"] = temp.Min + dic["Max"] = temp.Max + dic["Value"] = temp.Value if (temp.Value is not None) else self.error_ret + dic["Unit"] = temp.Unit + val_list[temp.name] = dic + # fan + fanlist = self.chas.fan_list + for fan in fanlist: + for rotor in fan.rotor_list: + sensorname = "%s%s"%(fan.name, rotor.name) + speed = collections.OrderedDict() + speed['Min'] = rotor.rotor_Speed.Min + speed['Max'] = rotor.rotor_Speed.Max + speed['Value'] = rotor.rotor_Speed.Value if (rotor.rotor_Speed.Value is not None) else self.error_ret + speed['Unit'] = rotor.rotor_Speed.Unit + val_list[sensorname] = speed + + # dcdc + dcdclist = self.chas.dcdc_list + for dcdc in dcdclist: + for name,sensor in dcdc.dcdc_ordict.items(): + dicttmp = collections.OrderedDict() + sensorname = "%s%s" % (dcdc.name, name) + dicttmp['Min'] = sensor.Min + dicttmp['Max'] = sensor.Max + dicttmp['Value'] = sensor.Value if (sensor.Value is not None) else self.error_ret + dicttmp['Unit'] = sensor.Unit + val_list[sensorname] = dicttmp + + # psu + psulist = self.chas.psu_list + for psu in psulist: + inputdic_voltage = collections.OrderedDict() + inputdic_current = collections.OrderedDict() + inputdic_power = collections.OrderedDict() + outputdic_voltage =collections.OrderedDict() + outputdic_current = collections.OrderedDict() + outputdic_power = collections.OrderedDict() + temperature = collections.OrderedDict() + fanspeed = collections.OrderedDict() + + temperature["Value"] = psu.Temperature.Value if (psu.Temperature.Value is not None) else self.error_ret + temperature["Min"] = psu.Temperature.Min + temperature["Max"] = psu.Temperature.Max + temperature["Unit"] = psu.Temperature.Unit + + fanspeed["Value"] = psu.FanSpeed.Value + fanspeed["Min"] = psu.FanSpeed.Min + fanspeed["Max"] = psu.FanSpeed.Max + fanspeed["Unit"] = psu.FanSpeed.Unit + + inputdic_voltage["Value"] = psu.InputsVoltage.Value if (psu.InputsVoltage.Value is not None) else self.error_ret + inputdic_voltage["Min"] = psu.InputsVoltage.Min + inputdic_voltage["Max"] = psu.InputsVoltage.Max + inputdic_voltage["Unit"] = psu.InputsVoltage.Unit + + inputdic_current["Value"] = psu.InputsCurrent.Value if (psu.InputsCurrent.Value is not None) else self.error_ret + inputdic_current["Min"] = psu.InputsCurrent.Min + inputdic_current["Max"] = psu.InputsCurrent.Max + inputdic_current["Unit"] = psu.InputsCurrent.Unit + + inputdic_power["Value"] = psu.InputsPower.Value if (psu.InputsPower.Value is not None) else self.error_ret + inputdic_power["Min"] = psu.InputsPower.Min + inputdic_power["Max"] = psu.InputsPower.Max + inputdic_power["Unit"] = psu.InputsPower.Unit + + outputdic_voltage["Value"] = psu.OutputsVoltage.Value if (psu.OutputsVoltage.Value is not None) else self.error_ret + outputdic_voltage["Min"] = psu.OutputsVoltage.Min + outputdic_voltage["Max"] = psu.OutputsVoltage.Max + outputdic_voltage["Unit"] = psu.OutputsVoltage.Unit + + outputdic_current["Value"] = psu.OutputsCurrent.Value if (psu.OutputsCurrent.Value is not None) else self.error_ret + outputdic_current["Min"] = psu.OutputsCurrent.Min + outputdic_current["Max"] = psu.OutputsCurrent.Max + outputdic_current["Unit"] = psu.OutputsCurrent.Unit + + outputdic_power["Value"] = psu.OutputsPower.Value if (psu.OutputsPower.Value is not None) else self.error_ret + outputdic_power["Min"] = psu.OutputsPower.Min + outputdic_power["Max"] = psu.OutputsPower.Max + outputdic_power["Unit"] = psu.OutputsPower.Unit + + val_list["%s%s"%(psu.name,"Vol_I" )] = inputdic_voltage + val_list["%s%s"%(psu.name,"Curr_I" )] = inputdic_current + val_list["%s%s"%(psu.name,"Power_I" )] = inputdic_power + val_list["%s%s"%(psu.name,"Vol_O" )] = outputdic_voltage + val_list["%s%s"%(psu.name,"Curr_O" )] = outputdic_current + val_list["%s%s"%(psu.name,"Power_O" )] = outputdic_power + val_list["%s%s" % (psu.name, "Fan")] = fanspeed + val_list["%s%s" % (psu.name, "Temp")] = temperature + + return val_list + + # cpld + def get_cpld_user_reg(self): + cpld = self.chas.get_cpld_byname("BASE_CPLD") + if cpld == None : + return None + else: + return cpld.get_user_reg() + + def set_cpld_user_reg(self, value): + if (isinstance (value, int) == False) : + baseutil.logger_debug("value must int %s"%type(value)) + return -1 + if (int(value) < 0 or int(value) > 255) : + baseutil.logger_debug("value must [0 - 255]") + return -1 + cpld = self.chas.get_cpld_byname("BASE_CPLD") + if cpld == None : + baseutil.logger_debug("name BASE_CPLD not find") + return -1 + if cpld.set_user_reg(value) == True: + return 0 + else: + return -1 + + def set_cpld_console_owner(self, owner): + """ + Set console I/O owner + + @param owner I/O owner of the console, either "cpu" or "bmc" + + @return 0 for success, -1 for failure + """ + if (owner == None): + baseutil.logger_debug("owner is None") + return -1 + if (owner != "cpu" and owner != "bmc") : + baseutil.logger_debug("owner is %s, must cpu or bmc"%owner) + return -1 + cpld = self.chas.get_cpld_byname("BASE_CPLD") + if cpld == None : + baseutil.logger_debug("name BASE_CPLD not find") + return -1 + if cpld.set_console_owner(owner) == True: + return 0 + else: + return -1 + + def get_cpld_all_version(self): + """ + Get version of all CPLDs' that can be read from BMC + + @return dict of CPLDs' version or None for failure. + example outputs: + { + "BASE_CPLD": "0.1", # or "N/A" for read failure + "FAN_CPLD": "0.2" + } + """ + cpld_version = { + "BASE_CPLD": "N/A", + "FAN_CPLD": "N/A" + } + for cpld_name in cpld_version.keys(): + cpld = self.chas.get_cpld_byname(cpld_name) + if cpld == None : + baseutil.logger_debug("name %s not find"%cpld_name) + continue + cpld_version[cpld_name] = cpld.get_version() + return cpld_version + + def get_bmc_productname(self): + """ + Get product name + + @return product name string, e.g. AS13-32H-F-$(VENDOR_NAME), if error return "N/A" + """ + bmc = self.chas.get_bmc_byname("master") + if (bmc == None): + baseutil.logger_debug("name bmc(master) not find") + return "N/A" + return bmc.get_productname() + + def call_bmc_diagcmd(self, cmdstr): + """ + Call BMC diag comman func + + @return ret: 0 sucess , -1 fail + outmsg: if success is out msg, or fail is err msg + """ + if (cmdstr == None or cmdstr == ""): + outmsg = "cmdstr is empty" + baseutil.logger_debug(outmsg) + return -1, outmsg + bmc = self.chas.get_bmc_byname("master") + if (bmc == None): + outmsg = "name bmc(master) not find" + baseutil.logger_debug(outmsg) + return -1, outmsg + baseutil.logger_debug("call cmdstr %s"%cmdstr) + return bmc.call_diagcmd(cmdstr) + + def write_bios_version(self, flash, version): + bios = self.chas.get_bios_byname("master") + if bios == None : + baseutil.logger_debug("name bios(master) not find") + return -1 + return bios.set_bios_version(flash, version) + + def get_bios_version(self): + bios = self.chas.get_bios_byname("master") + if bios == None : + baseutil.logger_debug("name bios(master) not find") + return -1 + return bios.get_bios_version() + + def get_bios_status(self): + bios = self.chas.get_bios_byname("master") + if bios == None : + baseutil.logger_debug("name bios(master) not find") + return -1 + return bios.get_bios_boot_status() + + def monitor_cpu_host_watchdog(self, value): + cpu = self.chas.get_cpu_byname("cpu") + if cpu == None: + baseutil.logger_debug("name cpu not find") + return -1 + return cpu.set_cpu_host_watchdog(value) + + def get_bmc_mac_rov(self): + """ + Get BMC mac rov + + @return ret: 0 sucess , -1 fail + outmsg: if success is out msg, or fail is err msg + """ + bmc = self.chas.get_bmc_byname("master") + if bmc == None: + msg = "name master not find" + baseutil.logger_debug(msg) + return -1, msg + return bmc.get_mac_rov() + + def get_bmc_next_boot(self): + """ + Get next booting flash of BMC + + @return 'master'/'slave' on success, "N/A" for failure + """ + bmc = self.chas.get_bmc_byname("master") + if bmc == None: + baseutil.logger_debug("name master not find") + return "N/A" + return bmc.get_next_boot() + + def set_bmc_next_boot(self, flash): + """ + Set flash from which next BMC boot + + @param flash Booting flash of BMC, "master" or "slave" + + @return 0 on success, -1 for failure + """ + if flash == None or (flash != "master" and flash != "slave"): + baseutil.logger_debug("parameter flash illegal, should be [master|slave]") + return -1 + bmc = self.chas.get_bmc_byname("master") + if bmc == None: + baseutil.logger_debug("name master not find") + return -1 + return bmc.set_next_boot(flash) + + def reboot_bmc(self): + """ + Reboot running BMC + """ + bmc = self.chas.get_bmc_byname("master") + if bmc == None: + baseutil.logger_debug("name master not find") + return -1 + return bmc.reboot() + + def get_bmc_info(self): + """ + Get BMC info + + @return dict of BMC info or None for failure + "Version": "1.1.1", # "N/A" + "Flash": "master", # "N/A" + "Next": "master" # "N/A" + """ + bmc = self.chas.get_bmc_byname("master") + if bmc == None: + baseutil.logger_debug("name master not find") + return "N/A" + return bmc.get_info() + + def get_bmc_version_all(self): + """ + @return dict of BMCs + { + "MasterVersion": "1.1.1", # "N/A" + "SlaveVersion": "1.1.1" # "N/A" + } + """ + bmc = self.chas.get_bmc_byname("master") + if bmc == None: + baseutil.logger_debug("name master not find") + return "N/A" + return bmc.get_version_all() + + def bmc_execute_command(self, cmd_str): + ret, output = osutil.command(cmd_str) + if ret: + baseutil.logger_debug("execute %s command failed" %(cmd_str)) + return ret, output + + def get_cpu_status(self): + """ + Get CPU current status. + + @return 'S0', ..., 'S5', or 'N/A' for failure + """ + cpu = self.chas.get_cpu_byname("cpu") + if cpu == None: + baseutil.logger_debug("name cpu not find") + return 'N/A' + return cpu.get_state() + + + + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/led.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/led.py new file mode 100644 index 000000000000..f8115bc06608 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/led.py @@ -0,0 +1,59 @@ +####################################################### +# +# led.py +# Python implementation of the Class led +# Original author: support@ragilenetworks.com +# +####################################################### +from devicebase import devicebase + +class led(devicebase): + def __init__(self, conf = None): + if conf is not None: + self.name = conf.get('name', None) + self.led_attrs_config = conf.get('led_attrs', None) + self.led_config = conf.get('led', None) + + def set_color(self, color, blink): + status = self.led_attrs_config.get(color, None) + if status == None: + return False + if blink == True: + blink_status = self.led_attrs_config.get('flash', None) + elif blink == False: + blink_status = self.led_attrs_config.get('light', None) + if blink_status == None: + return False + + mask = self.led_attrs_config.get('mask', 0xff) + + if isinstance(self.led_config, list): + for led_config_index in self.led_config: + ret, value = self.get_value(led_config_index) + if (ret == False) or (value is None): + return False + setval = (int(value) & ~mask) | (status & blink_status) + ret, val = self.set_value(led_config_index, setval) + else: + ret, value = self.get_value(self.led_config) + if (ret == False) or (value is None): + return False + setval = (int(value) & ~mask) | (status & blink_status) + ret, val = self.set_value(self.led_config, setval) + return ret + + def get_color(): + pass + + def get_location(): + pass + + def get_name(): + pass + + + def set_location(): + pass + + def set_name(): + pass diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/osutil.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/osutil.py new file mode 100644 index 000000000000..0d0541251b89 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/osutil.py @@ -0,0 +1,261 @@ +####################################################### +# +# osutil.py +# Python implementation of the Class osutil +# Original author: support@ragilenetworks.com +# +####################################################### + +import os +import subprocess +import time +import glob +import re +# import chardet +from rjutil.smbus import SMBus +import time +import subprocess +from functools import wraps + + +def retry(maxretry =6, delay = 0.01): + ''' + maxretry: max retry times + delay : interval after last retry + ''' + def decorator(f): + @wraps(f) + def wrapper(*args, **kwargs): + time_retry = maxretry + time_delay = delay + result_msg = "" + while time_retry: + try: + val , result_msg = f(*args, **kwargs) + if val is False: + time_retry -=1 + time.sleep(time_delay) + continue + else: + return val, result_msg + except Exception as e: + time_retry -= 1 + result_msg = str(e) + time.sleep(time_delay) + return False, "max time retry last errmsg is {}".format(result_msg) + return wrapper + return decorator + +class osutil(object): + """ + osutil + """ + + @staticmethod + @retry(maxretry = 6) + def rji2cget_python(bus, addr, reg): + with SMBus(bus) as y: + val , ind = y.read_byte_data(addr, reg, True) + return val , ind + + + @staticmethod + @retry(maxretry = 6) + def rji2cset_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_byte_data(addr, reg, value, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2cgetword_python(bus, addr, reg): + with SMBus(bus) as y: + val , ind = y.read_word_data(addr, reg, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2csetword_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_word_data(addr, reg, value, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2csetwordpec_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_word_data_pec(addr, reg, value, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2cset_byte_pec_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_byte_data_pec(addr, reg, value, True) + return val , ind + + + @staticmethod + def command(cmdstr): + retcode, output = subprocess.getstatusoutput(cmdstr) + return retcode, output + + + @staticmethod + def geti2cword_i2ctool(bus, addr, offset): + command_line = "i2cget -f -y %d 0x%02x 0x%02x wp" % (bus, addr, offset) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, int(ret_t, 16) + time.sleep(0.1) + return False, ret_t + + + @staticmethod + def seti2cword_i2ctool(bus, addr, offset, val): + command_line = "i2cset -f -y %d 0x%02x 0x%0x 0x%04x wp" % (bus, addr, offset, val) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + + @staticmethod + def rji2cget_i2ctool(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, int(ret_t, 16) + time.sleep(0.1) + return False, ret_t + + @staticmethod + def rji2cset_i2ctool(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + @staticmethod + def geti2cword(bus, addr, offset): + return osutil.rji2cgetword_python(bus, addr, offset) + @staticmethod + def seti2cword(bus, addr, offset, val): + return osutil.rji2csetword_python(bus, addr, offset, val) + + @staticmethod + def seti2cwordpec(bus, addr, offset, val): + return osutil.rji2csetwordpec_python(bus, addr, offset, val) + + @staticmethod + def seti2c_byte_pec(bus, addr, offset, val): + return osutil.rji2cset_byte_pec_python(bus, addr, offset, val) + + @staticmethod + def rji2cget(bus, devno, address): + return osutil.rji2cget_python(bus, devno, address) + @staticmethod + def rji2cset(bus, devno, address, byte): + return osutil.rji2cset_python(bus, devno, address, byte) + + @staticmethod + def byteTostr(val): + strtmp = '' + for i in range(len(val)): + strtmp += chr(val[i]) + return strtmp + + @staticmethod + def readsysfs(location): + try: + locations = glob.glob(location) + with open(locations[0], 'rb') as fd1: + retval = fd1.read() + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + except Exception as e: + return False, (str(e)+" location[%s]" % location) + return True, retval + + @staticmethod + def writesysfs(location, value): + try: + if not os.path.isfile(location): + print(location, 'not found !') + return False, ("location[%s] not found !" % location) + with open(location, 'w') as fd1: + fd1.write(value) + except Exception as e: + return False, (str(e)+" location[%s]" % location) + return True, ("set location[%s] %s success !" % (location, value)) + + @staticmethod + def getdevmem(addr, digit, mask): + command_line = "devmem 0x%02x %d" %(addr, digit) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + if mask != None: + ret_t = str(int(ret_t, 16) & mask) + return True, ret_t + return False, ret_t + + @staticmethod + def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + + @staticmethod + def getsdkreg(reg): + try: + cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg + ret, result = osutil.rj_os_system(cmd) + result_t = result.strip().replace("\r", "").replace("\n", "") + if ret != 0 or "Error:" in result_t: + return False, result + patt = r"%s.(.*):(.*)>drivshell" % reg + rt = re.findall(patt, result_t, re.S) + test = re.findall("=(.*)", rt[0][0])[0] + except Exception as e: + return False, 'get sdk register error' + return True, test + + @staticmethod + def getmactemp(): + try: + result = {} + # waitForDocker() + # need to exec twice + ret, log = osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + ret, log = osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + if ret: + return False, result + else: + logs = log.splitlines() + for line in logs: + if "average" in line: + b = re.findall(r'\d+.\d+', line) + result["average"] = b[0] + elif "maximum" in line: + b = re.findall(r'\d+.\d+', line) + result["maximum"] = b[0] + except Exception as e: + return False, str(e) + return True, result + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/psu.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/psu.py new file mode 100644 index 000000000000..285bbc339a52 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/psu.py @@ -0,0 +1,428 @@ +####################################################### +# +# psu.py +# Python implementation of the Class psu +# Original author: support@ragilenetworks.com +# +####################################################### +from devicebase import devicebase +from eepromutil.fru import * +from sensor import sensor + +class psu(devicebase): + __pmbus = None + __e2loc = None + __present = None + __productManufacturer = None # ARTESYN + __productName = None # CRPS550W + __productPartModelName= None # CSU550AP-3-300 + __productVersion = None # AB + __productSerialNumber = None # M623UZ00JYABL + __AirFlow = None # 'N/A' + __AirFlowconifg = None + __InputStatus_config = None + __OutputStatus_config = None + __FanSpeed_config = None + __Temperature_config = None + __InputStatus = None + __OutputStatus = None + __FanSpeed = None + __Temperature = None + __FanSpeedMin = None + __FanSpeedMax = None + __InputsVoltage_config = None + __InputsCurrent_config = None + __InputsPower_config = None + __OutputsVoltage_config = None + __OutputsCurrent_config = None + __OutputsPower_config = None + __InputsVoltage = {} + __InputsCurrent = None + __InputsPower = None + __OutputsVoltage = None + __OutputsCurrent = None + __OutputsPower = None + __InputsType_config = None + __InputsType = None + + def __init__(self, conf = None): + self.pmbus = conf.get("pmbusloc", None) + self.e2loc = conf.get("e2loc", None) + self.__presentconfig = conf.get("present", None) + self.name = conf.get("name", None) + self.AirFlowconifg = conf.get("airflow", None) + self.Temperature_config = conf.get("Temperature", None) + self.Temperature = sensor(self.Temperature_config) + + self.FanSpeed_config = conf.get("FanSpeed", None) + self.FanSpeed = sensor(self.FanSpeed_config) + + self.__InputsVoltage_config = conf.get("InputsVoltage",None) + self.generate_psu_input_vol(self.__InputsVoltage_config) + self.__InputsCurrent_config = conf.get("InputsCurrent",None) + self.InputsCurrent = sensor(self.__InputsCurrent_config) + self.__InputsPower_config = conf.get("InputsPower",None) + self.InputsPower = sensor(self.__InputsPower_config) + self.__OutputsVoltage_config = conf.get("OutputsVoltage",None) + self.OutputsVoltage = sensor(self.__OutputsVoltage_config) + self.__OutputsCurrent_config = conf.get("OutputsCurrent",None) + self.OutputsCurrent = sensor(self.__OutputsCurrent_config) + self.__OutputsPower_config = conf.get("OutputsPower",None) + self.OutputsPower = sensor(self.__OutputsPower_config) + + self.__InputStatus_config = conf.get("InputsStatus", None) + self.__OutputStatus_config = conf.get("OutputsStatus", None) + self.__InputsType_config = conf.get('InputsType', None) + + def generate_psu_input_vol(self, config): + tmp = {} + for (key, item) in config.items(): + tmp.setdefault(key, sensor(item)) + self.__InputsVoltage = tmp + + def get_psu_sensor_by_name(self, psutype): + return self.__InputsVoltage.get(psutype) or self.__InputsVoltage.get('other') + + @property + def InputsVoltage(self): + psutype = self.InputsType + input_sensor = self.get_psu_sensor_by_name(psutype) + if input_sensor is None: + return None + else: + return input_sensor + + @InputsVoltage.setter + def InputsVoltage(self, val): + self.__InputsVoltage = val + + @property + def InputsCurrent(self): + return self.__InputsCurrent + + @InputsCurrent.setter + def InputsCurrent(self, val): + self.__InputsCurrent = val + + @property + def InputsPower(self): + return self.__InputsPower + + @InputsPower.setter + def InputsPower(self, val): + self.__InputsPower = val + + @property + def OutputsVoltage(self): + return self.__OutputsVoltage + + @OutputsVoltage.setter + def OutputsVoltage(self, val): + self.__OutputsVoltage = val + + @property + def OutputsCurrent(self): + return self.__OutputsCurrent + + @OutputsCurrent.setter + def OutputsCurrent(self, val): + self.__OutputsCurrent = val + + @property + def OutputsPower(self): + return self.__OutputsPower + + @OutputsPower.setter + def OutputsPower(self, val): + self.__OutputsPower = val + + @property + def InputStatus(self): + if self.present == False: + self.__InputStatus = False + else: + ret, val = self.get_value(self.__InputStatus_config) + mask = self.__InputStatus_config.get("mask") + if ret == True: + ttt = val & mask + if ttt == 0: + self.__InputStatus = True + else: + self.__InputStatus = False + else: + self.__InputStatus = False + return self.__InputStatus + + @InputStatus.setter + def InputStatus(self, val): + self.__InputStatus = val + + + @property + def InputsType(self): + psutypedecode = self.__InputsType_config.get('psutypedecode', None) + if self.present == False: + self.__InputsType = psutypedecode.get(0x00) + else: + ret, val = self.get_value(self.__InputsType_config) + self.__InputsType = self.__InputsType_config.get(val,None) + if self.__InputsType is not None: + return self.__InputsType + if ret == True and val in psutypedecode: + self.__InputsType = psutypedecode.get(val) + else: + self.__InputsType = psutypedecode.get(0x00) + return self.__InputsType + + @InputsType.setter + def InputsType(self, val): + self.__InputsType = val + + @property + def FanSpeedMin(self): + return self.__FanSpeedMin + + @FanSpeedMin.setter + def FanSpeedMin(self, val): + self.__FanSpeedMin = val + + @property + def FanSpeedMax(self): + return self.__FanSpeedMax + + @FanSpeedMax.setter + def FanSpeedMax(self, val): + self.__FanSpeedMax = val + + @property + def OutputStatus(self): + if self.present == False: + self.__OutputStatus = False + else: + ret, val = self.get_value(self.__OutputStatus_config) + mask = self.__OutputStatus_config.get("mask") + if ret == True: + ttt = val & mask + if ttt == 0: + self.__OutputStatus = True + else: + self.__OutputStatus = False + else: + self.__OutputStatus = False + return self.__OutputStatus + + @OutputStatus.setter + def OutputStatus(self, val): + self.__OutputStatus = val + + @property + def FanSpeed(self): + return self.__FanSpeed + + @FanSpeed.setter + def FanSpeed(self, val): + self.__FanSpeed = val + + @property + def Temperature(self): + return self.__Temperature + + @Temperature.setter + def Temperature(self, val): + self.__Temperature = val + + @property + def Temperature_config(self): + return self.__Temperature_config + + @Temperature_config.setter + def Temperature_config(self, val): + self.__Temperature_config = val + + @property + def AirFlowconifg(self): + return self.__AirFlowconifg + + @AirFlowconifg.setter + def AirFlowconifg(self, val): + self.__AirFlowconifg = val + + @property + def pmbus(self): + return self.__pmbus + + @pmbus.setter + def pmbus(self, val): + self.__pmbus = val + + @property + def e2loc(self): + return self.__e2loc + + @e2loc.setter + def e2loc(self, val): + self.__e2loc = val + + @property + def AirFlow(self): + return self.__AirFlow + + @AirFlow.setter + def AirFlow(self, val): + self.__AirFlow = val + + @property + def present(self): + ret , val = self.get_value(self.__presentconfig) + if (ret == False) or (val is None): + return False + mask = self.__presentconfig.get("mask") + ttt = (int(val, 16)) & mask + if ttt == 0: + return True + else: + return False + + @present.setter + def present(self, val): + self.__present = val + + @property + def productManufacturer(self): + return self.__productManufacturer + + @productManufacturer.setter + def productManufacturer(self, val): + self.__productManufacturer = val + + @property + def productName(self): + return self.__productName + + @productName.setter + def productName(self, val): + self.__productName = val + + @property + def productPartModelName(self): + return self.__productPartModelName + + @productPartModelName.setter + def productPartModelName(self, val): + self.__productPartModelName = val + + @property + def productVersion(self): + return self.__productVersion + + @productVersion.setter + def productVersion(self, val): + self.__productVersion = val + + @property + def productSerialNumber(self): + return self.__productSerialNumber + + @productSerialNumber.setter + def productSerialNumber(self, val): + self.__productSerialNumber = val + + def __str__(self): + formatstr = \ + "name : %s \n" \ + "productManufacturer : %s \n" \ + "productName : %s \n" \ + "productPartModelName: %s \n" \ + "productVersion : %s \n" \ + "productSerialNumber : %s \n" \ + "AirFlow : %s \n" \ + + tmpstr = formatstr % (self.name, self.productManufacturer, + self.productName, self.productPartModelName, + self.productVersion, self.productSerialNumber, self.AirFlow) + return tmpstr + + def get_fan_speed_pwm(self): + if self.present == False: + return None + selfconfig = {} + selfconfig['bus'] = self.pmbus['bus'] + selfconfig['addr'] = self.pmbus['addr'] + selfconfig['way'] = 'i2cword' + selfconfig['offset'] = 0x3b + ret, val = self.get_value(selfconfig) + if ret == True: + return val + else: + return None + + def set_fan_speed_pwm(self, pwm): + ''' + pmbus + if duty: + i2cset -f -y 0x3b 0x0064 wp + ''' + if self.present == False: + return None + if 0 <= pwm <= 100: + '''enable duty first ''' + selfconfig = {} + + selfconfig['bus'] = self.pmbus['bus'] + selfconfig['addr'] = self.pmbus['addr'] + selfconfig['way'] = 'i2cpec' + selfconfig['offset'] = 0x3a + ret , val = self.set_value(selfconfig, 0x80) + + selfconfig['way'] = 'i2cwordpec' + selfconfig['offset'] = 0x3b + bytetmp = pwm + ret , val = self.set_value(selfconfig, int(bytetmp)) + if ret == True: + return True + else: + return None + else: + raise Exception("pwm not in range [0,100]") + + def get_fru_info(self): + try: + if self.present == False: + raise Exception("%s: not present" % self.name) + eeprom = self.get_eeprom_info(self.e2loc) + if eeprom is None: + raise Exception("%s:value is none" % self.name) + fru = ipmifru() + fru.decodeBin(eeprom) + if fru.productInfoArea is not None: + self.productManufacturer = fru.productInfoArea.productManufacturer.strip() + self.productName = fru.productInfoArea.productName.strip() + self.productPartModelName= fru.productInfoArea.productPartModelName.strip() + self.productVersion = fru.productInfoArea.productVersion.strip() + self.productSerialNumber = fru.productInfoArea.productSerialNumber.strip().replace(chr(0),"") + except Exception as e: + self.productManufacturer = None + self.productName = None + self.productPartModelName= None + self.productVersion = None + self.productSerialNumber = None + return False + return True + + def get_AirFlow(self): + if self.productPartModelName == None: + ret = self.get_fru_info() + if ret is False: + self.AirFlow = None + return False + if self.AirFlowconifg == None: + self.AirFlow = None + return False + else: + for i in self.AirFlowconifg: + if self.productPartModelName in self.AirFlowconifg[i]: + self.AirFlow = i + return True + self.AirFlow = None + return False + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/rotor.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/rotor.py new file mode 100644 index 000000000000..1b4f3843ceb3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/rotor.py @@ -0,0 +1,137 @@ +####################################################### +# +# rotor.py +# Python implementation of the Class rotor +# Original author: support@ragilenetworks.com +# +####################################################### +from devicebase import devicebase +from sensor import sensor + +class rotor(devicebase): + __rotor_Running = None + __rotor_HwAlarm_conf = None + __rotor_Speed = None + __rotor_run_conf = None + __Speedconfig = None + __i2c_speed = None + __SpeedMin = None + __SpeedMax = None + + def __init__(self, conf = None): + self.name = conf.get('name', None) + self.rotor_HwAlarm_conf = conf.get('HwAlarm', None) + self.rotor_run_conf = conf.get('Running', None) + self.SpeedMin = conf.get('SpeedMin', None) + self.SpeedMax = conf.get('SpeedMax', None) + self.rotor_Speed = sensor(conf.get('Speed', None)) + self.Speedconfig = conf.get('Set_speed', None) + + def getRunning(self): + ret, val = self.get_value(self.rotor_run_conf) + if (ret == False) or (val is None): + return False + mask = self.rotor_run_conf.get("mask") + is_runing_value = self.rotor_run_conf.get("is_runing") + flag = val & mask + if flag == is_runing_value: + return True + else: + return False + + @property + def SpeedMin(self): + return self.__SpeedMin + + @SpeedMin.setter + def SpeedMin(self, val): + self.__SpeedMin = val + + @property + def SpeedMax(self): + return self.__SpeedMax + + @SpeedMax.setter + def SpeedMax(self, val): + self.__SpeedMax = val + + @property + def i2c_speed(self): + ret, val = self.get_value(self.Speedconfig) + if ret == False: + return None + if val is not None: + self.__i2c_speed = val + return self.__i2c_speed + + def feed_watchdog(self): + ret, val = self.get_value(self.Speedconfig) + if ret == False: + return False, None + if val is not None: + ret, val = self.set_value(self.Speedconfig, val) + return ret, val + return False, None + + @i2c_speed.setter + def i2c_speed(self, val): + self.__i2c_speed = val + + @property + def Speedconfig(self): + return self.__Speedconfig + + @Speedconfig.setter + def Speedconfig(self, val): + self.__Speedconfig = val + + @property + def rotor_run_conf(self): + return self.__rotor_run_conf + + @rotor_run_conf.setter + def rotor_run_conf(self, val): + self.__rotor_run_conf = val + + @property + def rotor_Speed(self): + return self.__rotor_Speed + + @rotor_Speed.setter + def rotor_Speed(self, val): + self.__rotor_Speed = val + + @property + def rotor_HwAlarm(self): + ret, val = self.get_value(self.rotor_HwAlarm_conf) + mask = self.rotor_HwAlarm_conf.get("mask") + no_alarm_value = self.rotor_HwAlarm_conf.get("no_alarm") + if (ret == False) or (val is None): + return False + flag = val & mask + if flag == no_alarm_value: + return False + else: + return True + return self.__rotor_HwAlarm + + @rotor_HwAlarm.setter + def rotor_HwAlarm(self, val): + self.__rotor_HwAlarm = val + + @property + def rotor_HwAlarm_conf(self): + return self.__rotor_HwAlarm_conf + + @rotor_HwAlarm_conf.setter + def rotor_HwAlarm_conf(self, val): + self.__rotor_HwAlarm_conf = val + + @property + def rotor_Running(self): + self.__rotor_Running = self.getRunning() + return self.__rotor_Running + + @rotor_Running.setter + def rotor_Running(self, val): + self.__rotor_Running = val diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/sensor.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/sensor.py new file mode 100644 index 000000000000..16d22244f0da --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/sensor.py @@ -0,0 +1,142 @@ +####################################################### +# +# sensor.py +# Python implementation of the Class sensor +# Original author: support@ragilenetworks.com +# +####################################################### +from devicebase import devicebase + +class sensor(devicebase): + + __Value = None + __Min = None + __Max = None + __ValueConfig = None + __Flag = None + __Unit = None + __format = None + + __Min_config = None + __Max_config = None + + + + @property + def Min_config(self): + return self.__Min_config + + @Min_config.setter + def Min_config(self, val): + self.__Min_config = val + + @property + def Max_config(self): + return self.__Max_config + + @Max_config.setter + def Max_config(self, val): + self.__Max_config = val + + @property + def Unit(self): + return self.__Unit + + @Unit.setter + def Unit(self, val): + self.__Unit = val + + @property + def format(self): + return self.__format + + @format.setter + def format(self, val): + self.__format = val + + + @property + def ValueConfig(self): + return self.__ValueConfig + + @ValueConfig.setter + def ValueConfig(self, val): + self.__ValueConfig = val + + @property + def Flag(self): + return self.__Flag + + @Flag.setter + def Flag(self, val): + self.__Flag = val + + @property + def Value(self): + try: + ret, val = self.get_value(self.ValueConfig) + if (ret == False) or (val is None): + return None + if self.format is None: + self.__Value = int(val) + else: + self.__Value = eval(self.format % val) + except: + return None + return self.__Value + + @Value.setter + def Value(self, val): + self.__Value = val + + @property + def Min(self): + try: + if self.format is None: + self.__Min = self.Min_config + else: + self.__Min = eval(self.format % self.Min_config) + except: + return None + return self.__Min + + @Min.setter + def Min(self, val): + self.__Min = val + + @property + def Max(self): + try: + if self.format is None: + self.__Max = self.Max_config + else: + self.__Max = eval(self.format % self.Max_config) + except: + return None + return self.__Max + + @Max.setter + def Max(self, val): + self.__Max = val + + def __init__(self, conf=None): + self.ValueConfig = conf.get("value", None) + self.Flag = conf.get("flag", None) + self.Min_config = conf.get("Min", None) + self.Max_config = conf.get("Max", None) + self.Unit = conf.get('Unit', None) + self.format = conf.get('format', None) + + def __str__(self): + formatstr = \ + "ValueConfig: : %s \n" \ + "Min : %s \n" \ + "Max : %s \n" \ + "Unit : %s \n" \ + "format: : %s \n" + + tmpstr = formatstr % (self.ValueConfig, self.Min, + self.Max, self.Unit, + self.format) + return tmpstr + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/temp.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/temp.py new file mode 100644 index 000000000000..5bbd7bbe176f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/plat_hal/temp.py @@ -0,0 +1,77 @@ +####################################################### +# +# temp.py +# Python implementation of the Class temp +# Original author: support@ragilenetworks.com +# +####################################################### +from devicebase import devicebase +from sensor import sensor + +class temp(sensor): + def __init__(self, conf = None): + super(temp, self).__init__(conf.get('Temperature', None)) + self.name = conf.get("name", None) + + def __str__(self): + super(temp, self).__str__() + + def get_max_value(self, conf): + try: + ret, val = self.get_value(conf) + if ret == True: + return val + else: + return None + except: + return None + + def check_flag(self): + try: + okbit = self.Flag.get('okbit') + okval = self.Flag.get('okval') + ret, val = self.get_value(self.Flag) + if (ret == False) or (val is None): + return False + val_t = (int(val) & (1<< okbit)) >> okbit + if val_t != okval: + return False + except Exception as e: + return False + return True + + @property + def Value(self): + try: + if self.Flag != None: + if self.check_flag() == False: + return None + if isinstance(self.ValueConfig, list): + max = None + for i in self.ValueConfig: + tmp = self.get_max_value(i) + if tmp is None: + continue + if max is None or max < tmp: + max = tmp + if max is None: + return None + if self.format is None: + self.__Value = int(max) + else: + self.__Value = eval(self.format % max) + else: + ret, val = self.get_value(self.ValueConfig) + if (ret == False) or (val is None): + return None + if self.format is None: + self.__Value = int(val) + else: + self.__Value = eval(self.format % val) + except: + return None + return self.__Value + + @Value.setter + def Value(self, val): + self.__Value = val diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/baseutil.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/baseutil.py new file mode 100644 index 000000000000..0dc94761a317 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/baseutil.py @@ -0,0 +1,22 @@ +# -*- coding: UTF-8 -*- +import os + +def get_machine_info(): + if not os.path.isfile('/host/machine.conf'): + return None + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + +def get_platform_info(machine_info): + if machine_info != None: + if machine_info.__contains__('onie_platform'): + return machine_info['onie_platform'] + elif machine_info.__contains__('aboot_platform'): + return machine_info['aboot_platform'] + return None \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/smbus.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/smbus.py new file mode 100644 index 000000000000..0a147c92ae66 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/lib/rjutil/smbus.py @@ -0,0 +1,774 @@ +"""smbus2 - A drop-in replacement for smbus-cffi/smbus-python""" +# The MIT License (MIT) +# Copyright (c) 2017 Karl-Petter Lindegaard +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +import sys +from fcntl import ioctl +from ctypes import c_uint32, c_uint8, c_uint16, c_char, POINTER, Structure, Array, Union, create_string_buffer, string_at + + +# Commands from uapi/linux/i2c-dev.h +I2C_SLAVE = 0x0703 # Use this slave address +I2C_SLAVE_FORCE = 0x0706 # Use this slave address, even if it is already in use by a driver! +I2C_FUNCS = 0x0705 # Get the adapter functionality mask +I2C_RDWR = 0x0707 # Combined R/W transfer (one STOP only) +I2C_SMBUS = 0x0720 # SMBus transfer. Takes pointer to i2c_smbus_ioctl_data +I2C_PEC = 0x0708 + +# SMBus transfer read or write markers from uapi/linux/i2c.h +I2C_SMBUS_WRITE = 0 +I2C_SMBUS_READ = 1 + +# Size identifiers uapi/linux/i2c.h +I2C_SMBUS_QUICK = 0 +I2C_SMBUS_BYTE = 1 +I2C_SMBUS_BYTE_DATA = 2 +I2C_SMBUS_WORD_DATA = 3 +I2C_SMBUS_PROC_CALL = 4 +I2C_SMBUS_BLOCK_DATA = 5 # This isn't supported by Pure-I2C drivers with SMBUS emulation, like those in RaspberryPi, OrangePi, etc :( +I2C_SMBUS_BLOCK_PROC_CALL = 7 # Like I2C_SMBUS_BLOCK_DATA, it isn't supported by Pure-I2C drivers either. +I2C_SMBUS_I2C_BLOCK_DATA = 8 +I2C_SMBUS_BLOCK_MAX = 32 + +# To determine what functionality is present (uapi/linux/i2c.h) +try: + from enum import IntFlag +except: + IntFlag = int + + +class I2cFunc(IntFlag): + """ + These flags identify the operations supported by an I2C/SMBus device. + + You can test these flags on your `smbus.funcs` + + On newer python versions, I2cFunc is an IntFlag enum, but it + falls back to class with a bunch of int constants on older releases. + """ + I2C = 0x00000001 + ADDR_10BIT = 0x00000002 + PROTOCOL_MANGLING = 0x00000004 # I2C_M_IGNORE_NAK etc. + SMBUS_PEC = 0x00000008 + NOSTART = 0x00000010 # I2C_M_NOSTART + SLAVE = 0x00000020 + SMBUS_BLOCK_PROC_CALL = 0x00008000 # SMBus 2.0 + SMBUS_QUICK = 0x00010000 + SMBUS_READ_BYTE = 0x00020000 + SMBUS_WRITE_BYTE = 0x00040000 + SMBUS_READ_BYTE_DATA = 0x00080000 + SMBUS_WRITE_BYTE_DATA = 0x00100000 + SMBUS_READ_WORD_DATA = 0x00200000 + SMBUS_WRITE_WORD_DATA = 0x00400000 + SMBUS_PROC_CALL = 0x00800000 + SMBUS_READ_BLOCK_DATA = 0x01000000 + SMBUS_WRITE_BLOCK_DATA = 0x02000000 + SMBUS_READ_I2C_BLOCK = 0x04000000 # I2C-like block xfer + SMBUS_WRITE_I2C_BLOCK = 0x08000000 # w/ 1-byte reg. addr. + SMBUS_HOST_NOTIFY = 0x10000000 + + SMBUS_BYTE = 0x00060000 + SMBUS_BYTE_DATA = 0x00180000 + SMBUS_WORD_DATA = 0x00600000 + SMBUS_BLOCK_DATA = 0x03000000 + SMBUS_I2C_BLOCK = 0x0c000000 + SMBUS_EMUL = 0x0eff0008 + + +# i2c_msg flags from uapi/linux/i2c.h +I2C_M_RD = 0x0001 + +# Pointer definitions +LP_c_uint8 = POINTER(c_uint8) +LP_c_uint16 = POINTER(c_uint16) +LP_c_uint32 = POINTER(c_uint32) + + +############################################################# +# Type definitions as in i2c.h + + +class i2c_smbus_data(Array): + """ + Adaptation of the i2c_smbus_data union in ``i2c.h``. + + Data for SMBus messages. + """ + _length_ = I2C_SMBUS_BLOCK_MAX + 2 + _type_ = c_uint8 + + +class union_i2c_smbus_data(Union): + _fields_ = [ + ("byte", c_uint8), + ("word", c_uint16), + ("block", i2c_smbus_data) + ] + + +union_pointer_type = POINTER(union_i2c_smbus_data) + + +class i2c_smbus_ioctl_data(Structure): + """ + As defined in ``i2c-dev.h``. + """ + _fields_ = [ + ('read_write', c_uint8), + ('command', c_uint8), + ('size', c_uint32), + ('data', union_pointer_type)] + __slots__ = [name for name, type in _fields_] + + @staticmethod + def create(read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE_DATA): + u = union_i2c_smbus_data() + return i2c_smbus_ioctl_data( + read_write=read_write, command=command, size=size, + data=union_pointer_type(u)) + + +############################################################# +# Type definitions for i2c_rdwr combined transactions + + +class i2c_msg(Structure): + """ + As defined in ``i2c.h``. + """ + _fields_ = [ + ('addr', c_uint16), + ('flags', c_uint16), + ('len', c_uint16), + ('buf', POINTER(c_char))] + + def __iter__(self): + """ Iterator / Generator + + :return: iterates over :py:attr:`buf` + :rtype: :py:class:`generator` which returns int values + """ + idx = 0 + while idx < self.len: + yield ord(self.buf[idx]) + idx += 1 + + def __len__(self): + return self.len + + def __bytes__(self): + return string_at(self.buf, self.len) + + def __repr__(self): + return 'i2c_msg(%d,%d,%r)' % (self.addr, self.flags, self.__bytes__()) + + def __str__(self): + s = self.__bytes__() + if sys.version_info.major >= 3: + s = ''.join(map(chr, s)) + return s + + @staticmethod + def read(address, length): + """ + Prepares an i2c read transaction. + + :param address: Slave address. + :type: address: int + :param length: Number of bytes to read. + :type: length: int + :return: New :py:class:`i2c_msg` instance for read operation. + :rtype: :py:class:`i2c_msg` + """ + arr = create_string_buffer(length) + return i2c_msg( + addr=address, flags=I2C_M_RD, len=length, + buf=arr) + + @staticmethod + def write(address, buf): + """ + Prepares an i2c write transaction. + + :param address: Slave address. + :type address: int + :param buf: Bytes to write. Either list of values or str. + :type buf: list + :return: New :py:class:`i2c_msg` instance for write operation. + :rtype: :py:class:`i2c_msg` + """ + if sys.version_info.major >= 3: + if type(buf) is str: + buf = bytes(map(ord, buf)) + else: + buf = bytes(buf) + else: + if type(buf) is not str: + buf = ''.join([chr(x) for x in buf]) + arr = create_string_buffer(buf, len(buf)) + return i2c_msg( + addr=address, flags=0, len=len(arr), + buf=arr) + + +class i2c_rdwr_ioctl_data(Structure): + """ + As defined in ``i2c-dev.h``. + """ + _fields_ = [ + ('msgs', POINTER(i2c_msg)), + ('nmsgs', c_uint32) + ] + __slots__ = [name for name, type in _fields_] + + @staticmethod + def create(*i2c_msg_instances): + """ + Factory method for creating a i2c_rdwr_ioctl_data struct that can + be called with ``ioctl(fd, I2C_RDWR, data)``. + + :param i2c_msg_instances: Up to 42 i2c_msg instances + :rtype: i2c_rdwr_ioctl_data + """ + n_msg = len(i2c_msg_instances) + msg_array = (i2c_msg * n_msg)(*i2c_msg_instances) + return i2c_rdwr_ioctl_data( + msgs=msg_array, + nmsgs=n_msg + ) + + +############################################################# + + +class SMBus(object): + + def __init__(self, bus=None, force=False): + """ + Initialize and (optionally) open an i2c bus connection. + + :param bus: i2c bus number (e.g. 0 or 1) + or an absolute file path (e.g. `/dev/i2c-42`). + If not given, a subsequent call to ``open()`` is required. + :type bus: int or str + :param force: force using the slave address even when driver is + already using it. + :type force: boolean + """ + self.fd = None + self.funcs = I2cFunc(0) + if bus is not None: + self.open(bus) + self.address = None + self.force = force + self._force_last = None + + def __enter__(self): + """Enter handler.""" + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Exit handler.""" + self.close() + + def open(self, bus): + """ + Open a given i2c bus. + + :param bus: i2c bus number (e.g. 0 or 1) + or an absolute file path (e.g. '/dev/i2c-42'). + :type bus: int or str + :raise TypeError: if type(bus) is not in (int, str) + """ + if isinstance(bus, int): + filepath = "/dev/i2c-{}".format(bus) + elif isinstance(bus, str): + filepath = bus + else: + raise TypeError("Unexpected type(bus)={}".format(type(bus))) + + self.fd = os.open(filepath, os.O_RDWR) + self.funcs = self._get_funcs() + + def close(self): + """ + Close the i2c connection. + """ + if self.fd: + os.close(self.fd) + self.fd = None + + def _set_address(self, address, force=None): + """ + Set i2c slave address to use for subsequent calls. + + :param address: + :type address: int + :param force: + :type force: Boolean + """ + force = force if force is not None else self.force + if self.address != address or self._force_last != force: + if force is True: + ioctl(self.fd, I2C_SLAVE_FORCE, address) + else: + ioctl(self.fd, I2C_SLAVE, address) + self.address = address + self._force_last = force + + def _get_funcs(self): + """ + Returns a 32-bit value stating supported I2C functions. + + :rtype: int + """ + f = c_uint32() + ioctl(self.fd, I2C_FUNCS, f) + return f.value + + def write_quick(self, i2c_addr, force=None): + """ + Perform quick transaction. Throws IOError if unsuccessful. + :param i2c_addr: i2c address + :type i2c_addr: int + :param force: + :type force: Boolean + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=0, size=I2C_SMBUS_QUICK) + ioctl(self.fd, I2C_SMBUS, msg) + + def read_byte(self, i2c_addr, force=None): + """ + Read a single byte from a device. + + :rtype: int + :param i2c_addr: i2c address + :type i2c_addr: int + :param force: + :type force: Boolean + :return: Read byte value + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE + ) + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.byte + + def write_byte(self, i2c_addr, value, force=None): + """ + Write a single byte to a device. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param value: value to write + :type value: int + :param force: + :type force: Boolean + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=value, size=I2C_SMBUS_BYTE + ) + ioctl(self.fd, I2C_SMBUS, msg) + + def read_byte_data(self, i2c_addr, register, force=None): + """ + Read a single byte from a designated register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read + :type register: int + :param force: + :type force: Boolean + :return: Read byte value + :rtype: int + """ + val_t = -1 + returnmsg="" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BYTE_DATA + ) + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + self.close() + returnmsg = str(e) + if val_t < 0: + return False, returnmsg + else: + return True, msg.data.contents.byte + + def write_byte_data(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Byte value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA + ) + msg.data.contents.byte = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def write_byte_data_pec(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Byte value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + val_t = ioctl(self.fd, I2C_PEC, 1) + if val_t < 0: + raise Exception("set pec mod error") + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA + ) + msg.data.contents.byte = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def read_word_data(self, i2c_addr, register, force=None): + """ + Read a single word (2 bytes) from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read + :type register: int + :param force: + :type force: Boolean + :return: 2-byte word + :rtype: int + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_WORD_DATA + ) + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, msg.data.contents.word + + def write_word_data_pec(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Word value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + val_t = ioctl(self.fd, I2C_PEC, 1) + if val_t < 0: + raise Exception("set pec mod error") + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA + ) + msg.data.contents.word = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def write_word_data(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Word value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA + ) + msg.data.contents.word = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def process_call(self, i2c_addr, register, value, force=None): + """ + Executes a SMBus Process Call, sending a 16-bit value and receiving a 16-bit response + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read/write to + :type register: int + :param value: Word value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: int + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_PROC_CALL + ) + msg.data.contents.word = value + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.word + + def read_block_data(self, i2c_addr, register, force=None): + """ + Read a block of up to 32-bytes from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BLOCK_DATA + ) + ioctl(self.fd, I2C_SMBUS, msg) + length = msg.data.contents.block[0] + return msg.data.contents.block[1:length + 1] + + def write_block_data(self, i2c_addr, register, data, force=None): + """ + Write a block of byte data to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :rtype: None + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_DATA + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + + def block_process_call(self, i2c_addr, register, data, force=None): + """ + Executes a SMBus Block Process Call, sending a variable-size data + block and receiving another variable-size response + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read/write to + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_PROC_CALL + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + length = msg.data.contents.block[0] + return msg.data.contents.block[1:length + 1] + + def read_i2c_block_data(self, i2c_addr, register, length, force=None): + """ + Read a block of byte data from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param length: Desired block length + :type length: int + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Desired block length over %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA + ) + msg.data.contents.byte = length + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.block[1:length + 1] + + def write_i2c_block_data(self, i2c_addr, register, data, force=None): + """ + Write a block of byte data to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :rtype: None + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + + def i2c_rdwr(self, *i2c_msgs): + """ + Combine a series of i2c read and write operations in a single + transaction (with repeated start bits but no stop bits in between). + + This method takes i2c_msg instances as input, which must be created + first with :py:meth:`i2c_msg.read` or :py:meth:`i2c_msg.write`. + + :param i2c_msgs: One or more i2c_msg class instances. + :type i2c_msgs: i2c_msg + :rtype: None + """ + ioctl_data = i2c_rdwr_ioctl_data.create(*i2c_msgs) + ioctl(self.fd, I2C_RDWR, ioctl_data) + + +class SMBusWrapper: + """ + Wrapper class around the SMBus. + Deprecated as of version 0.3.0. Please replace with :py:class:`SMBus`. + + Enables the user to wrap access to the :py:class:`SMBus` class in a + "with" statement. If auto_cleanup is True (default), the + :py:class:`SMBus` handle will be automatically closed + upon exit of the ``with`` block. + """ + def __init__(self, bus_number=0, auto_cleanup=True, force=False): + """ + :param auto_cleanup: Close bus when leaving scope. + :type auto_cleanup: Boolean + :param force: Force using the slave address even when driver is already using it. + :type force: Boolean + """ + self.bus_number = bus_number + self.auto_cleanup = auto_cleanup + self.force = force + + def __enter__(self): + self.bus = SMBus(bus=self.bus_number, force=self.force) + return self.bus + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.auto_cleanup: + self.bus.close() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/Makefile new file mode 100644 index 000000000000..995ff0a3ce83 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/Makefile @@ -0,0 +1,33 @@ +PWD = $(shell pwd) +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +KVERSION ?= $(shell uname -r) +KERNEL_SRC ?= /lib/modules/$(KVERSION) + +module_out_put_dir := $(PWD)/build +export module_out_put_dir + + +ragile_common-objs := ragile_common_module.o dfd_tlveeprom.o +obj-m += ragile_platform.o +obj-m += i2c-mux-pca9641.o +obj-m += i2c-mux-pca954x.o +obj-m += ragile_common.o +obj-m += rtc-pcf85063.o +#obj-m += tpm_tis_core.o +#obj-m += rg_spi_gpio.o +#obj-m += spi-gpio.o +#obj-m += tpm_tis_spi.o +obj-m += optoe.o + + +all : + $(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules + @if [ ! -d $(module_out_put_dir) ]; then mkdir -p $(module_out_put_dir) ;fi + cp -p $(PWD)/*.ko $(module_out_put_dir) + +clean : + rm -rf $(module_out_put_dir) + rm -f ${PWD}/*.o ${PWD}/*.ko ${PWD}/*.mod.c ${PWD}/.*.cmd ${PWD}/.*.o.d + rm -f ${PWD}/Module.markers ${PWD}/Module.symvers ${PWD}/modules.order + rm -rf ${PWD}/.tmp_versions diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.c new file mode 100644 index 000000000000..de6fe863eead --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.c @@ -0,0 +1,522 @@ +/* + * Copyright (C) 2003-2014 FreeIPMI Core Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +/*****************************************************************************\ + * Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Albert Chu + * UCRL-CODE-232183 + * + * This file is part of Ipmi-fru, a tool used for retrieving + * motherboard field replaceable unit (FRU) information. For details, + * see http://www.llnl.gov/linux/. + * + * Ipmi-fru is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * Ipmi-fru is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with Ipmi-fru. If not, see . +\*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ragile.h" +#include "dfd_tlveeprom.h" + +/* using in is_valid_tlvinfo_header */ +static u_int32_t eeprom_size; + +/* + * List of TLV codes and names. + */ +static const struct tlv_code_desc tlv_code_list[] = { + { TLV_CODE_PRODUCT_NAME , "Product Name"}, + { TLV_CODE_PART_NUMBER , "Part Number"}, + { TLV_CODE_SERIAL_NUMBER , "Serial Number"}, + { TLV_CODE_MAC_BASE , "Base MAC Address"}, + { TLV_CODE_MANUF_DATE , "Manufacture Date"}, + { TLV_CODE_DEVICE_VERSION , "Device Version"}, + { TLV_CODE_LABEL_REVISION , "Label Revision"}, + { TLV_CODE_PLATFORM_NAME , "Platform Name"}, + { TLV_CODE_ONIE_VERSION , "ONIE Version"}, + { TLV_CODE_MAC_SIZE , "MAC Addresses"}, + { TLV_CODE_MANUF_NAME , "Manufacturer"}, + { TLV_CODE_MANUF_COUNTRY , "Country Code"}, + { TLV_CODE_VENDOR_NAME , "Vendor Name"}, + { TLV_CODE_DIAG_VERSION , "Diag Version"}, + { TLV_CODE_SERVICE_TAG , "Service Tag"}, + { TLV_CODE_VENDOR_EXT , "Vendor Extension"}, + { TLV_CODE_CRC_32 , "CRC-32"}, +}; + +#if 0 +#define OPENBMC_VPD_KEY_INVAIL_VAL 0 + +static const tlv_code_map_t tlv_code_map[] = { + { TLV_CODE_PRODUCT_NAME , OPENBMC_VPD_KEY_PRODUCT_NAME}, + { TLV_CODE_PART_NUMBER , OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM}, + { TLV_CODE_SERIAL_NUMBER , OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM}, + { TLV_CODE_MAC_BASE , OPENBMC_VPD_KEY_INVAIL_VAL}, + { TLV_CODE_MANUF_DATE , OPENBMC_VPD_KEY_BOARD_MFG_DATE}, + { TLV_CODE_DEVICE_VERSION , OPENBMC_VPD_KEY_PRODUCT_VER}, + { TLV_CODE_LABEL_REVISION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM7}, + { TLV_CODE_PLATFORM_NAME , OPENBMC_VPD_KEY_PRODUCT_CUSTOM1}, + { TLV_CODE_ONIE_VERSION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM2}, + { TLV_CODE_MAC_SIZE , OPENBMC_VPD_KEY_INVAIL_VAL}, + { TLV_CODE_MANUF_NAME , OPENBMC_VPD_KEY_PRODUCT_MFR}, + { TLV_CODE_MANUF_COUNTRY , OPENBMC_VPD_KEY_PRODUCT_CUSTOM3}, + { TLV_CODE_VENDOR_NAME , OPENBMC_VPD_KEY_PRODUCT_CUSTOM4}, + { TLV_CODE_DIAG_VERSION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM8}, + { TLV_CODE_SERVICE_TAG , OPENBMC_VPD_KEY_PRODUCT_CUSTOM5}, + { TLV_CODE_VENDOR_EXT , OPENBMC_VPD_KEY_PRODUCT_CUSTOM6}, + { TLV_CODE_CRC_32 , OPENBMC_VPD_KEY_INVAIL_VAL}, +}; +#endif + +#define TLV_CODE_NUM (sizeof(tlv_code_list) / sizeof(tlv_code_list[0])) + +#if 0 +#define TLV_CODE_MAP_NUM (sizeof(tlv_code_map) / sizeof(tlv_code_map[0])) +#endif + +const unsigned long crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +static unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned len) +{ + unsigned i; + if (len < 1) + return 0xffffffff; + + for (i = 0; i != len; ++i) + { + crc = crc_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); + } + + crc = crc ^ 0xffffffff; + + return crc; +} + +/* + * is_valid_tlv + * + * Perform basic sanity checks on a TLV field. The TLV is pointed to + * by the parameter provided. + * 1. The type code is not reserved (0x00 or 0xFF) + */ +static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) +{ + return ((tlv->type != 0x00) && (tlv->type != 0xFF)); +} + +/* + * is_valid_tlvinfo_header + * + * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM + * data pointed to by the parameter: + * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo" + * 2. Version byte is 1 + * 3. Total length bytes contain value which is less than or equal + * to the allowed maximum (2048-11) + * + */ +static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) +{ + int max_size = eeprom_size; + return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && + (hdr->version == TLV_INFO_VERSION) && + (be16_to_cpu(hdr->totallen) <= max_size) ); +} + +/* + * decode_tlv_value + * + * Decode a single TLV value into a string. + + * The validity of EEPROM contents and the TLV field have been verified + * prior to calling this function. + */ +static void decode_tlv_value(tlvinfo_tlv_t *tlv, tlv_decode_value_t *decode_value) +{ + int i; + char *value; + u_int32_t length; + + value = (char *)decode_value->value; + + switch (tlv->type) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_MANUF_DATE: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + case TLV_CODE_VENDOR_EXT: + memcpy(value, tlv->value, tlv->length); + value[tlv->length] = 0; + length = tlv->length; + break; + case TLV_CODE_MAC_BASE: + length = sprintf(value, "%02X:%02X:%02X:%02X:%02X:%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3], tlv->value[4], tlv->value[5]); + break; + case TLV_CODE_DEVICE_VERSION: + length = sprintf(value, "%u", tlv->value[0]); + break; + case TLV_CODE_MAC_SIZE: + length = sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]); + break; + #if 0 + case TLV_CODE_VENDOR_EXT: + value[0] = 0; + length = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) { + length += sprintf(value, "%s 0x%02X", value, tlv->value[i]); + } + break; + #endif + case TLV_CODE_CRC_32: + length = sprintf(value, "0x%02X%02X%02X%02X", tlv->value[0], + tlv->value[1], tlv->value[2], tlv->value[3]); + break; + default: + value[0] = 0; + length = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) { + length += sprintf(value, "%s 0x%02X", value, tlv->value[i]); + } + break; + } + + decode_value->length = length; +} + +/* + * is_checksum_valid + * + * Validate the checksum in the provided TlvInfo EEPROM data. First, + * verify that the TlvInfo header is valid, then make sure the last + * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data + * and compare it to the value stored in the EEPROM CRC-32 TLV. + */ +static bool is_checksum_valid(u_int8_t *eeprom) +{ + tlvinfo_header_t *eeprom_hdr; + tlvinfo_tlv_t *eeprom_crc; + unsigned int calc_crc; + unsigned int stored_crc; + + eeprom_hdr = (tlvinfo_header_t *) eeprom; + + /* Is the eeprom header valid? */ + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return false; + } + + /* Is the last TLV a CRC? */ + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - (sizeof(tlvinfo_tlv_t) + 4)]; + if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { + return false; + } + + /* Calculate the checksum */ + calc_crc = crc32(0xffffffffL, (const unsigned char *)eeprom, sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | + (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]); + + return (calc_crc == stored_crc); +} + +/* + * tlvinfo_find_tlv + * + * This function finds the TLV with the supplied code in the EERPOM. + * An offset from the beginning of the EEPROM is returned in the + * eeprom_index parameter if the TLV is found. + */ +static bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index) +{ + tlvinfo_header_t *eeprom_hdr; + tlvinfo_tlv_t *eeprom_tlv; + int eeprom_end; + + eeprom_hdr = (tlvinfo_header_t *) eeprom; + + /* Search through the TLVs, looking for the first one which matches the + supplied type code. */ + *eeprom_index = sizeof(tlvinfo_header_t); + eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + while (*eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; + if (!is_valid_tlv(eeprom_tlv)) { + return false; + } + + if (eeprom_tlv->type == tcode) { + return true; + } + + *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + + return false; +} + +/* + * tlvinfo_decode_tlv + * + * This function finds the TLV with the supplied code in the EERPOM + * and decodes the value into the buffer provided. + */ +static bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, tlv_decode_value_t *decode_value) +{ + int eeprom_index; + tlvinfo_tlv_t *eeprom_tlv; + + /* Find the TLV and then decode it */ + if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + decode_tlv_value(eeprom_tlv, decode_value); + return true; + } + + return false; +} + +/* + * parse_tlv_eeprom + * + * parse the EEPROM into memory, if it hasn't already been read. + */ +int parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size) +{ + unsigned int i; + bool ret; + tlvinfo_header_t *eeprom_hdr; + //tlv_info_vec_t tlv_info; + tlv_decode_value_t decode_value; + int j; + + eeprom_hdr = (tlvinfo_header_t *) eeprom; + eeprom_size = size; /* eeprom real size */ + + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + DBG_ERROR("Failed to check tlv header.\n"); + return -1; + } + + if (!is_checksum_valid(eeprom)) { + DBG_ERROR("Failed to check tlv crc.\n"); + return -1; + } + + for (i = 0; i < TLV_CODE_NUM; i++) { + memset((void *)&decode_value, 0, sizeof(tlv_decode_value_t)); + ret = tlvinfo_decode_tlv(eeprom, tlv_code_list[i].m_code, &decode_value); + if (!ret) { + DBG_ERROR("No found type: %s\n", tlv_code_list[i].m_name); + continue; + } + + DBG_DEBUG("i: %d,Found type: %s tlv[%d]:%s\n", i, tlv_code_list[i].m_name, tlv_code_list[i].m_code, + decode_value.value); + for (j = 0; j < decode_value.length; j++) { + if ((j % 16) == 0) { + DBG_DEBUG("\n"); + } + DBG_DEBUG("%02x ", decode_value.value[j]); + } + DBG_DEBUG("\n\n"); + } + return 0; +} +static int dfd_parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size, u_int8_t main_type, tlv_decode_value_t *decode_value) +{ + bool ret; + tlvinfo_header_t *eeprom_hdr; + /* tlv_info_vec_t tlv_info; */ + int j; + + eeprom_hdr = (tlvinfo_header_t *) eeprom; + eeprom_size = size; /* eeprom real size */ + + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + DBG_ERROR("Failed to check tlv header.\n"); + return -1; + } + + if (!is_checksum_valid(eeprom)) { + DBG_ERROR("Failed to check tlv crc.\n"); + return -1; + } + + ret = tlvinfo_decode_tlv(eeprom, main_type, decode_value); + if (!ret) { + DBG_ERROR("No found type: %d\n", main_type); + return -1; + } + + DBG_DEBUG("Found type: %d, value: %s\n", main_type,decode_value->value); + for (j = 0; j < decode_value->length; j++) { + if ((j % 16) == 0) { + DBG_DEBUG("\n"); + } + DBG_DEBUG("%02x ", decode_value->value[j]); + } + DBG_DEBUG("\n\n"); + + return 0; +} + +/* analyze the extended custom TLV format */ +static int tlvinfo_find_rg_ext_tlv(tlv_decode_value_t *ext_tlv_value, u_int8_t ext_type, + u_int8_t *buf, u_int8_t *buf_len) +{ + tlvinfo_tlv_t *eeprom_tlv; + int eeprom_end, eeprom_index; + + /* Search through the TLVs, looking for the first one which matches the + supplied type code. */ + DBG_DEBUG("ext_tlv_value->length: %d.\n", ext_tlv_value->length); + for (eeprom_index = 0; eeprom_index < ext_tlv_value->length; eeprom_index++) { + if ((eeprom_index % 16) == 0) { + DBG_DEBUG("\n"); + } + DBG_DEBUG("%02x ", ext_tlv_value->value[eeprom_index]); + } + + DBG_DEBUG("\n"); + + eeprom_index = 0; + eeprom_end = ext_tlv_value->length; + while (eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &(ext_tlv_value->value[eeprom_index]); + if (!is_valid_tlv(eeprom_tlv)) { + DBG_ERROR("tlv is not valid, eeprom_tlv->type 0x%x.\n", eeprom_tlv->type); + return -1; + } + + DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length); + if (eeprom_tlv->type == ext_type) { + if (*buf_len >= eeprom_tlv->length) { + memcpy(buf, eeprom_tlv->value, eeprom_tlv->length); + DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length); + *buf_len = eeprom_tlv->length; + return 0; + } + DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, eeprom_tlv->length); + return -1; + } + + eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + + DBG_ERROR("ext_type %d: tlv is not found.\n", ext_type); + return -1; +} + +/* get EEPROM information */ +int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len) +{ + tlv_decode_value_t decode_value; + int ret; + + if (eeprom == NULL || tlv_type == NULL || buf == NULL) { + DBG_ERROR("Input para invalid.\n"); + return -1; + } + + memset((void *)&decode_value, 0, sizeof(tlv_decode_value_t)); + ret = dfd_parse_tlv_eeprom(eeprom, size, tlv_type->main_type, &decode_value); + if (ret) { + DBG_ERROR("dfd_parse_tlv_eeprom failed ret %d.\n", ret); + return ret; + } + + /* For non-extended types, return data directly */ + if (tlv_type->main_type != TLV_CODE_VENDOR_EXT) { + if (*buf_len >= decode_value.length) { + memcpy(buf, decode_value.value, decode_value.length); + *buf_len = decode_value.length; + return 0; + } + DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, decode_value.length); + return -1; + } + DBG_DEBUG("info_len %d.\n", decode_value.length); + + /* For the extended type, continue with the secondary TLV analysis to obtain + the data corresponding to the sub-TLV type */ + return tlvinfo_find_rg_ext_tlv(&decode_value, tlv_type->ext_type, buf, buf_len); +} + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.h new file mode 100644 index 000000000000..fe5959d9028d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/dfd_tlveeprom.h @@ -0,0 +1,122 @@ +#ifndef DFD_OPENBMC_TLVEEPROM_H +#define DFD_OPENBMC_TLVEEPROM_H + +#ifndef u_int8_t +#define u_int8_t unsigned char +#endif + +#ifndef u_int16_t +#define u_int16_t unsigned short +#endif + +#ifndef u_int32_t +#define u_int32_t unsigned int +#endif + +#ifndef be16_to_cpu +#define be16_to_cpu(x) ntohs(x) +#endif + +#ifndef cpu_to_be16 +#define cpu_to_be16(x) htons(x) +#endif + +/** + * The TLV Types. + * + * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + +#define TLV_CODE_NAME_LEN 64 +/* + * Struct for displaying the TLV codes and names. + */ +struct tlv_code_desc { + u_int8_t m_code; + char m_name[TLV_CODE_NAME_LEN]; +}; +/* ONIE TLV Type and Extended TLV Type Definition */ +typedef struct dfd_tlv_type_s { + u_int8_t main_type;/* ONIE standard TLV TYPE type */ + u_int8_t ext_type; /* Extended TLV TYPE type */ +} dfd_tlv_type_t; + +/* Header Field Constants */ +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +/*#define TLV_TOTAL_LEN_MAX (XXXXXXXX - sizeof(tlvinfo_header_t))*/ + +struct __attribute__ ((__packed__)) tlvinfo_header_s { + char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ + u_int8_t version; /* 0x08 Structure version */ + u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */ +}; +typedef struct tlvinfo_header_s tlvinfo_header_t; + +/* + * TlvInfo TLV: Layout of a TLV field + */ +struct __attribute__ ((__packed__)) tlvinfo_tlv_s { + u_int8_t type; + u_int8_t length; + u_int8_t value[0]; +}; +typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; + +#define TLV_VALUE_MAX_LEN 255 +/* + * The max decode value is currently for the 'raw' type or the 'vendor + * extension' type, both of which have the same decode format. The + * max decode string size is computed as follows: + * + * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 + * + */ +#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1) + +typedef struct tlv_decode_value_s { + u_int8_t value[TLV_DECODE_VALUE_MAX_LEN]; + u_int32_t length; +} tlv_decode_value_t; + +typedef enum dfd_tlvinfo_ext_tlv_type_e { + DFD_TLVINFO_EXT_TLV_TYPE_DEV_TYPE = 1, +} dfd_tlvinfo_ext_tlv_type_t; + +#if 0 +#define TLV_TIME_LEN 64 + +int ipmi_tlv_validate_fru_area(const uint8_t fruid, const char *fru_file_name, + sd_bus *bus_type, const bool bmc_fru); + +extern const char *get_vpd_key_names(int key_id); +extern std::string getService(sdbusplus::bus::bus& bus, + const std::string& intf, + const std::string& path); +extern std::string getFRUValue(const std::string& section, + const std::string& key, + const std::string& delimiter, + IPMIFruInfo& fruData); +#endif + +int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len); + +#endif /* endif DFD_OPENBMC_TLVEEPROM_H */ + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca954x.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca954x.c new file mode 100644 index 000000000000..11c1b4fa80f2 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca954x.c @@ -0,0 +1,3825 @@ +/* + * I2C multiplexer + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This module supports the PCA954x series of I2C multiplexer/switch chips + * made by Philips Semiconductors. + * This includes the: + * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 + * and PCA9548. + * + * These chips are all controlled via the I2C bus itself, and all have a + * single 8-bit register. The upstream "parent" bus fans out to two, + * four, or eight downstream busses or channels; which of these + * are selected is determined by the chip type and register contents. A + * mux can select only one sub-bus at a time; a switch can select any + * combination simultaneously. + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * 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 + +#if LINUX_VERSION_CODE > KERNEL_VERSION(4,0,36) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCA954X_MAX_NCHANS 8 + +#define PCA954X_IRQ_OFFSET 4 + +extern int pca9641_setmuxflag(int nr, int flag); + +int force_create_bus = 0; +module_param(force_create_bus, int, S_IRUGO | S_IWUSR); + +enum pca_type { + pca_9540, + pca_9542, + pca_9543, + pca_9544, + pca_9545, + pca_9546, + pca_9547, + pca_9548, +}; + +struct chip_desc { + u8 nchans; + u8 enable; /* used for muxes only */ + u8 has_irq; + enum muxtype { + pca954x_ismux = 0, + pca954x_isswi + } muxtype; +}; + + + + +struct pca954x { + const struct chip_desc *chip; + + u8 last_chan; /* last register value */ + s32 idle_state; + u8 deselect; + struct i2c_client *client; + + struct irq_domain *irq; + unsigned int irq_mask; + raw_spinlock_t lock; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [pca_9540] = { + .nchans = 2, + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [pca_9542] = { + .nchans = 2, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + }, + [pca_9543] = { + .nchans = 2, + .has_irq = 1, + .muxtype = pca954x_isswi, + }, + [pca_9544] = { + .nchans = 4, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + }, + [pca_9545] = { + .nchans = 4, + .has_irq = 1, + .muxtype = pca954x_isswi, + }, + [pca_9546] = { + .nchans = 4, + .muxtype = pca954x_isswi, + }, + [pca_9547] = { + .nchans = 8, + .enable = 0x8, + .muxtype = pca954x_ismux, + }, + [pca_9548] = { + .nchans = 8, + .muxtype = pca954x_isswi, + }, +}; + +static const struct i2c_device_id pca954x_id[] = { + { "pca9540", pca_9540 }, + { "pca9542", pca_9542 }, + { "pca9543", pca_9543 }, + { "pca9544", pca_9544 }, + { "pca9545", pca_9545 }, + { "pca9546", pca_9546 }, + { "pca9547", pca_9547 }, + { "pca9548", pca_9548 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pca954x_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca954x_of_match[] = { + { .compatible = "nxp,pca9540", .data = &chips[pca_9540] }, + { .compatible = "nxp,pca9542", .data = &chips[pca_9542] }, + { .compatible = "nxp,pca9543", .data = &chips[pca_9543] }, + { .compatible = "nxp,pca9544", .data = &chips[pca_9544] }, + { .compatible = "nxp,pca9545", .data = &chips[pca_9545] }, + { .compatible = "nxp,pca9546", .data = &chips[pca_9546] }, + { .compatible = "nxp,pca9547", .data = &chips[pca_9547] }, + { .compatible = "nxp,pca9548", .data = &chips[pca_9548] }, + {} +}; +MODULE_DEVICE_TABLE(of, pca954x_of_match); +#endif + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int pca954x_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + int ret = -ENODEV; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[1]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + buf[0] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + + if (ret >= 0 && ret != 1) + ret = -EREMOTEIO; + } else { + union i2c_smbus_data data; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + val, I2C_SMBUS_BYTE, &data); + } + + return ret; +} + +static u8 pca954x_regval(struct pca954x *data, u8 chan) +{ + /* We make switches look like muxes, not sure how to be smarter. */ + if (data->chip->muxtype == pca954x_ismux) + return chan | data->chip->enable; + else + return 1 << chan; +} + static int pca954x_setmuxflag(struct i2c_client *client, int flag) + { + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + pca9641_setmuxflag(adap->nr, flag); + return 0; + } + +static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + const struct chip_desc *chip = data->chip; + u8 regval; + int ret = 0; + regval = pca954x_regval(data, chan); + + /* we make switches look like muxes, not sure how to be smarter */ + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + pca954x_setmuxflag(client, 0); + ret = pca954x_reg_write(muxc->parent, client, regval); + data->last_chan = ret < 0 ? 0 : regval; + } + + return ret; +} + + +typedef void (*pca954x_hw_do_reset_func_t)(int busid, int addr); +pca954x_hw_do_reset_func_t g_notify_to_do_reset = NULL; + +void pca954x_hw_do_reset_func_register(void* func) +{ + if (func == NULL) { + return ; + } + g_notify_to_do_reset = func; + return; +} +EXPORT_SYMBOL(pca954x_hw_do_reset_func_register); + +static int pca954x_hw_do_reset(int busid, int addr) +{ + if (g_notify_to_do_reset != NULL) { + (*g_notify_to_do_reset)(busid, addr); + return 0; + } + + return 0; +} +/***************************************9548 reset*****************************************/ +#define DEV_TYPE 0x4040 /* BT2575 */ +#define PCA9548_MAX_CPLD_NUM (32) /* PCA9548 max number */ +#define PCA9548_MAX_CPLD_LAYER (8) /* PCA9548 max layer */ +#define DFD_PID_BUF_LEN (32) +#define DFD_PRODUCT_ID_LENGTH (8) +#define CPLD_PCA9548_RESET 0x023500b0 /* bus:2, addr:0x35, offset:0xb0 */ +#define B6510_32CQ_CPLD_PCA9548_RESET 0x060d0060 /* bus:6, addr:0x0d, offset:0x60 */ + +#define DFD_PUB_CARDTYPE_FILE "/sys/module/ragile_common/parameters/dfd_my_type" +#define DFD_MAX_PRODUCT_NUM (32) + + +#define I2C_RETRY_TIMES 5 +#define I2C_RETRY_WAIT_TIMES 10 /*delay 10ms*/ + +#define PCA9548_I2C_GET_BUS(addr) (((addr) >> 24) & 0x00ff) +#define PCA9548_I2C_GET_CLIENT(addr) (((addr) >> 16) & 0x00ff) +#define PCA9548_I2C_GET_OFFSET(addr) (addr & 0xffff) + +typedef enum pca9548_reset_type { + PCA9548_RESET_FUNC = 0, + PCA9548_RESET_GPIO = 1, +} pca9548_reset_type_t; + +typedef void (*pca954x_hw_do_reset_func_t_new)(int io_port, u8 value); +typedef u8 (*pca954x_get_umask_func_t)(int io_port); + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value); +u8 pca954x_get_umask_by_i2c(int addr); +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value); +u8 pca954x_get_umask_by_lpc(int io_port); + + +typedef struct func_attr_s { + int cfg_offset[PCA9548_MAX_CPLD_LAYER]; + int umask[PCA9548_MAX_CPLD_LAYER]; + pca954x_hw_do_reset_func_t_new reset_func; /* 9548 reset function */ + pca954x_get_umask_func_t get_umask_func; /* get reset mask */ +} func_attr_t; + +typedef struct gpio_attr_s { + int gpio; + int gpio_init; + u8 reset_on; + u8 reset_off; +} gpio_attr_t; + +typedef struct pca9548_cfg_info_s { + int pca9548_reset_type; + int pca9548_bus; + int pca9548_addr; + int rst_delay_b; /* delay time before reset(us) */ + int rst_delay; /* reset time(us) */ + int rst_delay_a; /* delay time after reset(us) */ + union { + func_attr_t func_attr; + gpio_attr_t gpio_attr; + } attr; +} pca9548_cfg_info_t; + +typedef struct fpga_pcie_card_info_s { + int dev_type[DFD_MAX_PRODUCT_NUM]; /* dev type */ + pca9548_cfg_info_t pca9548_cfg_info[PCA9548_MAX_CPLD_NUM]; +} pca9548_card_info_t; + +static pca9548_card_info_t g_pca9548_card_info[] = { + { + .dev_type = {0x4040,0x4061,0x4071}, /*B6510,BT2575,TCS81*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4041}, /*B6520*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + /* sff8 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4044,0x4072,0x4048}, /*B6920,TCS83,BS100R0*/ + .pca9548_cfg_info = { + /* 9548 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x936, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* base board */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 8, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 9, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 12, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 11, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 7, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* fanA */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 14, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* fanB */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 13, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4058,0x4073}, /* B6510-32CQ, TCS82 */ + .pca9548_cfg_info = { + /* psu */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* fan */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4065}, /* AS61-48E4T */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, + { + .dev_type = {0x4066}, /* AS61-48X4T */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP1 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 7, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP2 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 7, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP3 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 7, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP4 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP5 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP6 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, + { + .dev_type = {0x4087}, /* AS61-48E4T-LC */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, + { + .dev_type = {0x4088}, /* AS61-48E4T-LD */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, +}; +int g_pca954x_debug = 0; +module_param(g_pca954x_debug, int, S_IRUGO | S_IWUSR); + +#define PCA954X_DEBUG(fmt, args...) do { \ + if (g_pca954x_debug) { \ + printk(KERN_ERR "[PCA95x][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +/* x86 device get type method */ +static int dfd_get_my_dev_type_by_file(void) +{ + struct file *fp; + /* mm_segment_t fs;*/ + loff_t pos; + static int card_type; + char buf[DFD_PID_BUF_LEN]; + + if (card_type != 0) { + return card_type; + } + + fp= filp_open(DFD_PUB_CARDTYPE_FILE, O_RDONLY, 0); + if (IS_ERR(fp)) { + PCA954X_DEBUG("open file fail!\r\n"); + return -1; + } + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + memset(buf, 0, DFD_PID_BUF_LEN); + pos = 0; + kernel_read(fp, buf, DFD_PRODUCT_ID_LENGTH + 1, &pos); + if (pos < 0) { + PCA954X_DEBUG("read file fail!\r\n"); + goto exit; + } + + card_type = simple_strtoul(buf, NULL, 10); + PCA954X_DEBUG("card_type 0x%x.\n", card_type); + +exit: + /* set_fs(fs); */ + filp_close(fp, NULL); + return card_type; +} + +static int drv_get_my_dev_type(void) +{ + static int type = -1; + + if (type > 0) { + return type; + } + type = dfd_get_my_dev_type_by_file(); + PCA954X_DEBUG("ko board type %d\r\n", type); + + return type; +} + +pca9548_card_info_t* pca9548_get_card_info(int dev_type) +{ + int i, j; + int size; + + size = ARRAY_SIZE(g_pca9548_card_info); + + PCA954X_DEBUG("Enter dev_type 0x%x size %d.\n", dev_type, size); + for (i = 0; i < size; i++) { + for(j = 0; j < DFD_MAX_PRODUCT_NUM; j++) { + if (g_pca9548_card_info[i].dev_type[j] == dev_type) { + PCA954X_DEBUG("match dev_type 0x%x.\n", dev_type); + return &g_pca9548_card_info[i]; + } + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x.\n", dev_type); + return NULL; +} + +pca9548_cfg_info_t* get_pca9548_cfg_info(int bus, int addr) +{ + int dev_type; + pca9548_card_info_t *info; + pca9548_cfg_info_t *pca9548_cfg_info; + int i; + int size; + + dev_type = drv_get_my_dev_type(); + if (dev_type < 0) { + PCA954X_DEBUG("drv_get_my_dev_type failed ret %d.\n", dev_type); + return NULL; + } + + info = pca9548_get_card_info(dev_type); + if (info == NULL) { + PCA954X_DEBUG("fpga_pcie_get_card_info dev_type %d failed.\n", dev_type); + return NULL; + } + + size = PCA9548_MAX_CPLD_NUM; + for (i = 0; i < size; i++) { + pca9548_cfg_info = &(info->pca9548_cfg_info[i]); + if ((pca9548_cfg_info->pca9548_bus == bus) && (pca9548_cfg_info->pca9548_addr == addr)) { + PCA954X_DEBUG("match dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return pca9548_cfg_info; + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return NULL; +} + +static void pca9548_gpio_init(gpio_attr_t *gpio_attr) +{ + if (gpio_attr->gpio_init == 0) { + PCA954X_DEBUG("gpio%d init.\n", gpio_attr->gpio); + gpio_request(gpio_attr->gpio, "pca9548_reset"); + gpio_direction_output(gpio_attr->gpio, gpio_attr->reset_off); + gpio_attr->gpio_init = 1; + } +} + +static void pca9548_gpio_free(gpio_attr_t *gpio_attr) +{ + if (gpio_attr == NULL) { + PCA954X_DEBUG("pca9548_gpio_free,params error\n"); + return ; + } + if (gpio_attr->gpio_init == 1) { + PCA954X_DEBUG("gpio%d release.\n", gpio_attr->gpio); + gpio_free(gpio_attr->gpio); + gpio_attr->gpio_init = 0; + } +} + +static int pca954x_do_gpio_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int ret = -1; + gpio_attr_t *tmp_gpio_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + tmp_gpio_attr = &(cfg_info->attr.gpio_attr); + timeout = cfg_info->rst_delay_a; + + pca9548_gpio_init(tmp_gpio_attr); + udelay(cfg_info->rst_delay_b); + /* reset on */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + udelay(cfg_info->rst_delay); + /* reset off */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + + while (timeout > 0) { + udelay(1); + val = __gpio_get_value(tmp_gpio_attr->gpio); + if (val == tmp_gpio_attr->reset_off) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_gpio_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_gpio_reset failed.\n"); + } + pca9548_gpio_free(&(cfg_info->attr.gpio_attr)); + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_gpio_reset failed.\n"); + } + + return ret; +} + +static int pca954x_do_func_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int ret = -1; + func_attr_t *tmp_func_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + int i; + u8 old_value; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + tmp_func_attr = &(cfg_info->attr.func_attr); + timeout = cfg_info->rst_delay_a; + + if ((tmp_func_attr->reset_func == NULL) || (tmp_func_attr->get_umask_func == NULL)) { + PCA954X_DEBUG("pca954x hw do reset func or get umask func is null.\n"); + return ret; + } + + for(i = 0; (i < PCA9548_MAX_CPLD_LAYER) && (tmp_func_attr->cfg_offset[i] != -1) + && (tmp_func_attr->umask[i] != -1); i++) { + old_value = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i]); + PCA954X_DEBUG("cfg info: offset:0x%x umask:0x%x, old_value:0x%x\n", + tmp_func_attr->cfg_offset[i], tmp_func_attr->umask[i],old_value); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value & ~tmp_func_attr->umask[i]); + udelay(cfg_info->rst_delay); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value | tmp_func_attr->umask[i]); + } + + while (timeout > 0) { + udelay(1); + val = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i - 1]); + val &= (tmp_func_attr->umask[i - 1]); + if (val == tmp_func_attr->umask[i - 1]) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_func_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_func_reset failed.\n"); + } + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_func_reset failed.\n"); + } + + return ret; +} + +static int pca9548_reset_ctrl(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + int ret = -1; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + ret = pca954x_do_func_reset(cfg_info, adap, client, chan); + } else if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + ret = pca954x_do_gpio_reset(cfg_info, adap, client, chan); + } + + if (ret < 0) { + PCA954X_DEBUG("pca9548_reset_ctrl failed.\n"); + } + return ret; +} + +static int pca954x_reset_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset_addr, + unsigned char *buf, uint32_t size) +{ + struct file *fp; + /* mm_segment_t fs; */ + struct i2c_client client; + char i2c_path[32]; + int i ,j ; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = addr; + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + for (j = 0 ;j < size ;j++){ + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_read_byte_data(&client, (offset_addr + j)); + if (rv < 0) { + PCA954X_DEBUG("i2c read failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + *(buf + j) = (unsigned char)rv; + break; + } + } +out: + filp_close(fp, NULL); + /* set_fs(fs); */ + return rv; +} + +static int pca954x_reset_i2c_write(uint32_t bus, uint32_t dev_addr, uint32_t offset_addr, + uint8_t write_buf) +{ + struct file *fp; + /* mm_segment_t fs; */ + struct i2c_client client; + char i2c_path[32]; + int i; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = dev_addr; + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_write_byte_data(&client, offset_addr, write_buf); + if (rv < 0) { + PCA954X_DEBUG("i2c write failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + break; + } +out: + filp_close(fp, NULL); + /* set_fs(fs); */ + return rv; +} + +int pca954x_reset_reg_i2c_read_byte(int addr, u8 *value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_read(bus, client_addr, offset, value, 1); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x read fail\r\n", addr); + goto end; + } +end: + return ret; +} + +int pca954x_reset_reg_i2c_write_byte(int addr, u8 value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_write(bus, client_addr, offset, value); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x write fail\r\n", addr); + goto end; + } +end: + return ret; +} + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value) +{ + int ret; + + PCA954X_DEBUG("write i2c cpld[0x%x], value[%d]\n", addr, value); + ret = pca954x_reset_reg_i2c_write_byte(addr, value); + if (ret < 0) { + PCA954X_DEBUG("write cpld pca9548 reset reg failed, ret = %d \n", ret); + } +} + +u8 pca954x_get_umask_by_i2c(int addr) +{ + u8 value = 0xFF; + int ret; + + ret = pca954x_reset_reg_i2c_read_byte(addr, &value); + PCA954X_DEBUG("read i2c cpld[0x%x], value[%d], ret = %d\n", addr, value, ret); + + return value; +} + +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value) +{ + PCA954X_DEBUG("write lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + outb(value, (u16)io_port); +} + +u8 pca954x_get_umask_by_lpc(int io_port) +{ + u8 value; + + value = inb(io_port); + PCA954X_DEBUG("read lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + + return value; +} + +int pca954x_hw_do_reset_new(struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + pca9548_cfg_info_t *cfg_info; + int ret = -1; + + cfg_info = get_pca9548_cfg_info(adap->nr, client->addr); + if (cfg_info == NULL && g_notify_to_do_reset == NULL) { + PCA954X_DEBUG("fpga_do_pca954x_reset_func do nothing.\n"); + return ret; + } + if(cfg_info != NULL) { + ret = pca9548_reset_ctrl(cfg_info, adap, client, chan); + } else { + ret = pca954x_hw_do_reset(adap->nr, client->addr); + } + if (ret < 0) { + PCA954X_DEBUG("pca954x_hw_do_reset failed.\n"); + } + return ret; +} +/******************************end 9548 reset***********************************/ + +static int pca954x_do_reset(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct i2c_client *new_client; + int ret = -1; + + PCA954X_DEBUG("do pca954x reset x86\n"); + new_client =(struct i2c_client *) client; + ret = pca954x_hw_do_reset_new(adap, new_client, chan); + if (ret < 0) { + PCA954X_DEBUG("pca954x_do_reset failed.\n"); + return ret; + } + + PCA954X_DEBUG("pca954x_do_reset success.\n"); + ret = 0; + return ret; +} +static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + s32 idle_state; + int ret, rv; + struct i2c_client * new_client; + + idle_state = READ_ONCE(data->idle_state); + if (idle_state >= 0) + /* Set the mux back to a predetermined channel */ + return pca954x_select_chan(muxc, idle_state); + + if (idle_state == MUX_IDLE_DISCONNECT) { + /* Deselect active channel */ + data->last_chan = 0; + ret = pca954x_reg_write(muxc->parent, client, + data->last_chan); + if (ret < 0) { + new_client =(struct i2c_client *) client; + dev_warn(&new_client->dev, "pca954x close chn failed, do reset.\n"); + rv = pca954x_do_reset(client->adapter, client, chan); + if (rv == 0) { + ret = 0; + } + } + return ret; + } + + /* otherwise leave as-is */ + + return 0; +} + +static ssize_t idle_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + + return sprintf(buf, "%d\n", READ_ONCE(data->idle_state)); +} + +static ssize_t idle_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int val; + int ret; + + ret = kstrtoint(buf, 0, &val); + if (ret < 0) + return ret; + + if (val != MUX_IDLE_AS_IS && val != MUX_IDLE_DISCONNECT && + (val < 0 || val >= data->chip->nchans)) + return -EINVAL; + + i2c_lock_bus(muxc->parent, I2C_LOCK_SEGMENT); + + WRITE_ONCE(data->idle_state, val); + /* + * Set the mux into a state consistent with the new + * idle_state. + */ + if (data->last_chan || val != MUX_IDLE_DISCONNECT) + ret = pca954x_deselect_mux(muxc, 0); + + i2c_unlock_bus(muxc->parent, I2C_LOCK_SEGMENT); + + return ret < 0 ? ret : count; +} + +static DEVICE_ATTR_RW(idle_state); + +static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) +{ + struct pca954x *data = dev_id; + unsigned long pending; + int ret, i; + + ret = i2c_smbus_read_byte(data->client); + if (ret < 0) + return IRQ_NONE; + + pending = (ret >> PCA954X_IRQ_OFFSET) & (BIT(data->chip->nchans) - 1); + for_each_set_bit(i, &pending, data->chip->nchans) + handle_nested_irq(irq_linear_revmap(data->irq, i)); + + return IRQ_RETVAL(pending); +} + +static int pca954x_init(struct i2c_client *client, struct pca954x *data) +{ + int ret; + + if (data->idle_state >= 0) + data->last_chan = pca954x_regval(data, data->idle_state); + else + data->last_chan = 0; /* Disconnect multiplexer */ + + ret = i2c_smbus_write_byte(client, data->last_chan); + if (ret < 0) + data->last_chan = 0; + return ret; +} + +static void pca954x_irq_mask(struct irq_data *idata) +{ + struct pca954x *data = irq_data_get_irq_chip_data(idata); + unsigned int pos = idata->hwirq; + unsigned long flags; + + raw_spin_lock_irqsave(&data->lock, flags); + + data->irq_mask &= ~BIT(pos); + if (!data->irq_mask) + disable_irq(data->client->irq); + + raw_spin_unlock_irqrestore(&data->lock, flags); +} + +static void pca954x_irq_unmask(struct irq_data *idata) +{ + struct pca954x *data = irq_data_get_irq_chip_data(idata); + unsigned int pos = idata->hwirq; + unsigned long flags; + + raw_spin_lock_irqsave(&data->lock, flags); + + if (!data->irq_mask) + enable_irq(data->client->irq); + data->irq_mask |= BIT(pos); + + raw_spin_unlock_irqrestore(&data->lock, flags); +} + +static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) +{ + if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW) + return -EINVAL; + return 0; +} + +static struct irq_chip pca954x_irq_chip = { + .name = "i2c-mux-pca954x", + .irq_mask = pca954x_irq_mask, + .irq_unmask = pca954x_irq_unmask, + .irq_set_type = pca954x_irq_set_type, +}; + +static int pca954x_irq_setup(struct i2c_mux_core *muxc) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int c, err, irq; + + if (!data->chip->has_irq || client->irq <= 0) + return 0; + + raw_spin_lock_init(&data->lock); + + data->irq = irq_domain_add_linear(client->dev.of_node, + data->chip->nchans, + &irq_domain_simple_ops, data); + if (!data->irq) + return -ENODEV; + + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_create_mapping(data->irq, c); + irq_set_chip_data(irq, data); + irq_set_chip_and_handler(irq, &pca954x_irq_chip, + handle_simple_irq); + } + + err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL, + pca954x_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, + "pca954x", data); + if (err) + goto err_req_irq; + + disable_irq(data->client->irq); + + return 0; +err_req_irq: + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_find_mapping(data->irq, c); + irq_dispose_mapping(irq); + } + irq_domain_remove(data->irq); + + return err; +} + +/* + * I2C init/probing/exit functions + */ +static int pca954x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct device_node *of_node = client->dev.of_node; + bool idle_disconnect_dt; + struct gpio_desc *gpio; + int num, force, class; + struct i2c_mux_core *muxc; + struct pca954x *data; + const struct of_device_id *match; + int ret; + + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + PCA954X_MAX_NCHANS, sizeof(*data), 0, + pca954x_select_chan, pca954x_deselect_mux); + if (!muxc) + return -ENOMEM; + data = i2c_mux_priv(muxc); + + i2c_set_clientdata(client, muxc); + data->client = client; + + /* Get the mux out of reset if a reset GPIO is specified. */ + gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + data->idle_state = MUX_IDLE_AS_IS; + if (device_property_read_u32(&client->dev, "idle-state", &data->idle_state)) { + if (device_property_read_bool(&client->dev, "i2c-mux-idle-disconnect")) + data->idle_state = MUX_IDLE_DISCONNECT; + } + + /* + * Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to a channel + * or disconnected state. + */ + ret = pca954x_init(client, data); + if (ret < 0) { + dev_warn(&client->dev, "probe failed\n"); + return -ENODEV; + } + + match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); + if (match) + data->chip = of_device_get_match_data(&client->dev); + else + data->chip = &chips[id->driver_data]; + + data->last_chan = 0; /* force the first selection */ + + idle_disconnect_dt = of_node && + of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); + + ret = pca954x_irq_setup(muxc); + if (ret) + goto fail_del_adapters; + + /* Now create an adapter for each channel */ + for (num = 0; num < data->chip->nchans; num++) { + ret = i2c_mux_add_adapter(muxc, 0, num, 0); + if (ret) + goto fail_del_adapters; + } + + device_create_file(&client->dev, &dev_attr_idle_state); + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s %s\n", + num, data->chip->muxtype == pca954x_ismux + ? "mux" : "switch", client->name); + + return 0; + +fail_del_adapters: + i2c_mux_del_adapters(muxc); + return ret; +} + +static int pca954x_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int c, irq; + + if (data->irq) { + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_find_mapping(data->irq, c); + irq_dispose_mapping(irq); + } + irq_domain_remove(data->irq); + } + device_remove_file(&client->dev, &dev_attr_idle_state); + + i2c_mux_del_adapters(muxc); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int pca954x_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int ret; + + ret = pca954x_init(client, data); + if (ret < 0) + dev_err(&client->dev, "failed to verify mux presence\n"); + + return ret; +} +#endif + +static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume); + +static struct i2c_driver pca954x_driver = { + .driver = { + .name = "pca954x", + .pm = &pca954x_pm, + .of_match_table = of_match_ptr(pca954x_of_match), + }, + .probe = pca954x_probe, + .remove = pca954x_remove, + .id_table = pca954x_id, +}; + +module_i2c_driver(pca954x_driver); + + +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int pca9641_setmuxflag(int nr, int flag); + +int force_create_bus = 0; +module_param(force_create_bus, int, S_IRUGO | S_IWUSR); + +#define PCA954X_MAX_NCHANS 8 + +enum pca_type { + pca_9540, + pca_9542, + pca_9543, + pca_9544, + pca_9545, + pca_9546, + pca_9547, + pca_9548, +}; + +struct pca954x { + enum pca_type type; + struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; + + u8 last_chan; /* last register value */ +}; + +struct chip_desc { + u8 nchans; + u8 enable; /* used for muxes only */ + enum muxtype { + pca954x_ismux = 0, + pca954x_isswi + } muxtype; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [pca_9540] = { + .nchans = 2, + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [pca_9543] = { + .nchans = 2, + .muxtype = pca954x_isswi, + }, + [pca_9544] = { + .nchans = 4, + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [pca_9545] = { + .nchans = 4, + .muxtype = pca954x_isswi, + }, + [pca_9547] = { + .nchans = 8, + .enable = 0x8, + .muxtype = pca954x_ismux, + }, + [pca_9548] = { + .nchans = 8, + .muxtype = pca954x_isswi, + }, +}; + +static const struct i2c_device_id pca954x_id[] = { + { "pca9540", pca_9540 }, + { "pca9542", pca_9540 }, + { "pca9543", pca_9543 }, + { "pca9544", pca_9544 }, + { "pca9545", pca_9545 }, + { "pca9546", pca_9545 }, + { "pca9547", pca_9547 }, + { "pca9548", pca_9548 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pca954x_id); + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int pca954x_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + int ret = -ENODEV; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[1]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + buf[0] = val; + msg.buf = buf; + ret = adap->algo->master_xfer(adap, &msg, 1); + + if (ret >= 0 && ret != 1) + ret = -EREMOTEIO; + } else { + union i2c_smbus_data data; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + val, I2C_SMBUS_BYTE, &data); + } + + return ret; +} + +static int pca954x_setmuxflag(struct i2c_adapter *adap, int flag) +{ + pca9641_setmuxflag(adap->nr, flag); + return 0; +} + +static int pca954x_select_chan(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + const struct chip_desc *chip = &chips[data->type]; + u8 regval; + int ret = 0; + + /* we make switches look like muxes, not sure how to be smarter */ + if (chip->muxtype == pca954x_ismux) + regval = chan | chip->enable; + else + regval = 1 << chan; + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + pca954x_setmuxflag(adap, 0); + ret = pca954x_reg_write(adap, client, regval); + data->last_chan = ret < 0 ? 0 : regval; + } + + return ret; +} + +typedef void (*pca954x_hw_do_reset_func_t)(int busid, int addr); +pca954x_hw_do_reset_func_t g_notify_to_do_reset = NULL; + +void pca954x_hw_do_reset_func_register(void* func) +{ + if (func == NULL) { + return ; + } + g_notify_to_do_reset = func; + return; +} +EXPORT_SYMBOL(pca954x_hw_do_reset_func_register); + +static int pca954x_hw_do_reset(int busid, int addr) +{ + if (g_notify_to_do_reset != NULL) { + (*g_notify_to_do_reset)(busid, addr); + return 0; + } + return 0; +} +/***************************************9548 reset*****************************************/ +#define DEV_TYPE 0x4040 /* BT2575 */ +#define PCA9548_MAX_CPLD_NUM (32) /* PCA9548 max number */ +#define PCA9548_MAX_CPLD_LAYER (8) /* PCA9548 max layer */ +#define DFD_PID_BUF_LEN (32) +#define DFD_PRODUCT_ID_LENGTH (8) +#define CPLD_PCA9548_RESET 0x023500b0 /* bus:2, addr:0x35, offset:0xb0 */ +#define B6510_32CQ_CPLD_PCA9548_RESET 0x060d0060 /* bus:6, addr:0x0d, offset:0x60 */ +#define DFD_PUB_CARDTYPE_FILE "/sys/module/ragile_common/parameters/dfd_my_type" +#define DFD_MAX_PRODUCT_NUM (32) + +#define I2C_RETRY_TIMES 5 +#define I2C_RETRY_WAIT_TIMES 10 /*delay 10ms*/ + +#define PCA9548_I2C_GET_BUS(addr) (((addr) >> 24) & 0x00ff) +#define PCA9548_I2C_GET_CLIENT(addr) (((addr) >> 16) & 0x00ff) +#define PCA9548_I2C_GET_OFFSET(addr) (addr & 0xffff) + +typedef enum pca9548_reset_type { + PCA9548_RESET_FUNC = 0, + PCA9548_RESET_GPIO = 1, +} pca9548_reset_type_t; + +typedef void (*pca954x_hw_do_reset_func_t_new)(int io_port, u8 value); +typedef u8 (*pca954x_get_umask_func_t)(int io_port); + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value); +u8 pca954x_get_umask_by_i2c(int addr); +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value); +u8 pca954x_get_umask_by_lpc(int io_port); + +typedef struct func_attr_s { + int cfg_offset[PCA9548_MAX_CPLD_LAYER]; + int umask[PCA9548_MAX_CPLD_LAYER]; + pca954x_hw_do_reset_func_t_new reset_func; /* 9548 reset function */ + pca954x_get_umask_func_t get_umask_func; /* get reset mask */ +} func_attr_t; + +typedef struct gpio_attr_s { + int gpio; + int gpio_init; + u8 reset_on; + u8 reset_off; +} gpio_attr_t; + +typedef struct pca9548_cfg_info_s { + int pca9548_reset_type; + int pca9548_bus; + int pca9548_addr; + int rst_delay_b; /* delay time before reset(us) */ + int rst_delay; /* reset time(us) */ + int rst_delay_a; /* delay time after reset(us) */ + union { + func_attr_t func_attr; + gpio_attr_t gpio_attr; + } attr; +} pca9548_cfg_info_t; + +typedef struct fpga_pcie_card_info_s { + int dev_type[DFD_MAX_PRODUCT_NUM]; /* dev type */ + pca9548_cfg_info_t pca9548_cfg_info[PCA9548_MAX_CPLD_NUM]; +} pca9548_card_info_t; + +static pca9548_card_info_t g_pca9548_card_info[] = { + { + .dev_type = {0x4040,0x4061,0x4071}, /*B6510,BT2575,TCS81*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4041}, /*B6520*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + /* sff8 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4044,0x4072,0x4048}, /*B6920,TCS83,BS100R0*/ + .pca9548_cfg_info = { + /* 9548 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x936, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* base board */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 8, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 9, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 12, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 11, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 7, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* fanA */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 14, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* fanB */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 13, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4058,0x4073}, /* B6510-32CQ, TCS82 */ + .pca9548_cfg_info = { + /* psu */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* fan */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4065}, /* AS61-48E4T */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, + { + .dev_type = {0x4066}, /* AS61-48X4T */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP1 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 7, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP2 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 7, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP3 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 7, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP4 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP5 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP6 */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, + { + .dev_type = {0x4087}, /* AS61-48E4T-LC */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, + { + .dev_type = {0x4088}, /* AS61-48E4T-LD */ + .pca9548_cfg_info = { + /* SOC */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 0, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + /* SFP+ */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 8, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 509, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 0, + .gpio_attr.reset_off = 1, + }, + }, + }, + }, +}; + +int g_pca954x_debug = 0; +module_param(g_pca954x_debug, int, S_IRUGO | S_IWUSR); + +#define PCA954X_DEBUG(fmt, args...) do { \ + if (g_pca954x_debug) { \ + printk(KERN_ERR "[PCA95x][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +/* x86 device get card method */ +static int dfd_get_my_dev_type_by_file(void) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos; + static int card_type; + char buf[DFD_PID_BUF_LEN]; + + if (card_type != 0) { + return card_type; + } + + fp= filp_open(DFD_PUB_CARDTYPE_FILE, O_RDONLY, 0); + if (IS_ERR(fp)) { + PCA954X_DEBUG("open file fail!\r\n"); + return -1; + } + fs = get_fs(); + set_fs(KERNEL_DS); + memset(buf, 0, DFD_PID_BUF_LEN); + pos = 0; + vfs_read(fp, buf, DFD_PRODUCT_ID_LENGTH + 1, &pos); + if (pos < 0) { + PCA954X_DEBUG("read file fail!\r\n"); + goto exit; + } + + card_type = simple_strtoul(buf, NULL, 10); + PCA954X_DEBUG("card_type 0x%x.\n", card_type); + +exit: + set_fs(fs); + filp_close(fp, NULL); + return card_type; +} + +static int drv_get_my_dev_type(void) +{ + static int type = -1; + + if (type > 0) { + return type; + } + type = dfd_get_my_dev_type_by_file(); + PCA954X_DEBUG("ko board type %d\r\n", type); + + return type; +} + +pca9548_card_info_t* pca9548_get_card_info(int dev_type) +{ + int i, j; + int size; + + size = ARRAY_SIZE(g_pca9548_card_info); + + PCA954X_DEBUG("Enter dev_type 0x%x size %d.\n", dev_type, size); + for (i = 0; i < size; i++) { + for(j = 0; j < DFD_MAX_PRODUCT_NUM; j++) { + if (g_pca9548_card_info[i].dev_type[j] == dev_type) { + PCA954X_DEBUG("match dev_type 0x%x.\n", dev_type); + return &g_pca9548_card_info[i]; + } + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x.\n", dev_type); + return NULL; +} + +pca9548_cfg_info_t* get_pca9548_cfg_info(int bus, int addr) +{ + int dev_type; + pca9548_card_info_t *info; + pca9548_cfg_info_t *pca9548_cfg_info; + int i; + int size; + + dev_type = drv_get_my_dev_type(); + if (dev_type < 0) { + PCA954X_DEBUG("drv_get_my_dev_type failed ret %d.\n", dev_type); + return NULL; + } + + info = pca9548_get_card_info(dev_type); + if (info == NULL) { + PCA954X_DEBUG("fpga_pcie_get_card_info dev_type %d failed.\n", dev_type); + return NULL; + } + + size = PCA9548_MAX_CPLD_NUM; + for (i = 0; i < size; i++) { + pca9548_cfg_info = &(info->pca9548_cfg_info[i]); + if ((pca9548_cfg_info->pca9548_bus == bus) && (pca9548_cfg_info->pca9548_addr == addr)) { + PCA954X_DEBUG("match dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return pca9548_cfg_info; + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return NULL; +} + +static void pca9548_gpio_init(gpio_attr_t *gpio_attr) +{ + if (gpio_attr->gpio_init == 0) { + PCA954X_DEBUG("gpio%d init.\n", gpio_attr->gpio); + gpio_request(gpio_attr->gpio, "pca9548_reset"); + gpio_direction_output(gpio_attr->gpio, gpio_attr->reset_off); + gpio_attr->gpio_init = 1; + } +} + +static void pca9548_gpio_free(gpio_attr_t *gpio_attr) +{ + if (gpio_attr == NULL) { + PCA954X_DEBUG("pca9548_gpio_free,params error\n"); + return ; + } + if (gpio_attr->gpio_init == 1) { + PCA954X_DEBUG("gpio%d release.\n", gpio_attr->gpio); + gpio_free(gpio_attr->gpio); + gpio_attr->gpio_init = 0; + } +} + +static int pca954x_do_gpio_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + int ret = -1; + gpio_attr_t *tmp_gpio_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + tmp_gpio_attr = &(cfg_info->attr.gpio_attr); + timeout = cfg_info->rst_delay_a; + + pca9548_gpio_init(tmp_gpio_attr); + udelay(cfg_info->rst_delay_b); + /* reset on */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + udelay(cfg_info->rst_delay); + /* reset off */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + + while (timeout > 0) { + udelay(1); + val = __gpio_get_value(tmp_gpio_attr->gpio); + if (val == tmp_gpio_attr->reset_off) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_gpio_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_gpio_reset failed.\n"); + } + pca9548_gpio_free(&(cfg_info->attr.gpio_attr)); + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_gpio_reset failed.\n"); + } + + return ret; +} + +static int pca954x_do_func_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + int ret = -1; + func_attr_t *tmp_func_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + int i; + u8 old_value; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + tmp_func_attr = &(cfg_info->attr.func_attr); + timeout = cfg_info->rst_delay_a; + + if ((tmp_func_attr->reset_func == NULL) || (tmp_func_attr->get_umask_func == NULL)) { + PCA954X_DEBUG("pca954x hw do reset func or get umask func is null.\n"); + return ret; + } + + for(i = 0; (i < PCA9548_MAX_CPLD_LAYER) && (tmp_func_attr->cfg_offset[i] != -1) + && (tmp_func_attr->umask[i] != -1); i++) { + old_value = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i]); + PCA954X_DEBUG("cfg info: offset:0x%x umask:0x%x, old_value:0x%x\n", + tmp_func_attr->cfg_offset[i], tmp_func_attr->umask[i],old_value); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value & ~tmp_func_attr->umask[i]); + udelay(cfg_info->rst_delay); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value | tmp_func_attr->umask[i]); + } + + while (timeout > 0) { + udelay(1); + val = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i - 1]); + val &= (tmp_func_attr->umask[i - 1]); + if (val == tmp_func_attr->umask[i - 1]) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_func_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_func_reset failed.\n"); + } + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_func_reset failed.\n"); + } + + return ret; +} + +static int pca9548_reset_ctrl(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + int ret = -1; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + ret = pca954x_do_func_reset(cfg_info, adap, client, chan); + } else if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + ret = pca954x_do_gpio_reset(cfg_info, adap, client, chan); + } + + if (ret < 0) { + PCA954X_DEBUG("pca9548_reset_ctrl failed.\n"); + } + return ret; +} + +static int pca954x_reset_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset_addr, + unsigned char *buf, uint32_t size) +{ + struct file *fp; + mm_segment_t fs; + struct i2c_client client; + char i2c_path[32]; + int i ,j ; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = addr; + fs = get_fs(); + set_fs(KERNEL_DS); + for (j = 0 ;j < size ;j++){ + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_read_byte_data(&client, (offset_addr + j)); + if (rv < 0) { + PCA954X_DEBUG("i2c read failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + *(buf + j) = (unsigned char)rv; + break; + } + } +out: + filp_close(fp, NULL); + set_fs(fs); + return rv; +} + +static int pca954x_reset_i2c_write(uint32_t bus, uint32_t dev_addr, uint32_t offset_addr, + uint8_t write_buf) +{ + struct file *fp; + mm_segment_t fs; + struct i2c_client client; + char i2c_path[32]; + int i; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = dev_addr; + fs = get_fs(); + set_fs(KERNEL_DS); + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_write_byte_data(&client, offset_addr, write_buf); + if (rv < 0) { + PCA954X_DEBUG("i2c write failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + break; + } +out: + filp_close(fp, NULL); + set_fs(fs); + return rv; +} + +int pca954x_reset_reg_i2c_read_byte(int addr, u8 *value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_read(bus, client_addr, offset, value, 1); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x read fail\r\n", addr); + goto end; + } +end: + return ret; +} + +int pca954x_reset_reg_i2c_write_byte(int addr, u8 value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_write(bus, client_addr, offset, value); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x write fail\r\n", addr); + goto end; + } +end: + return ret; +} + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value) +{ + int ret; + + PCA954X_DEBUG("write i2c cpld[0x%x], value[%d]\n", addr, value); + ret = pca954x_reset_reg_i2c_write_byte(addr, value); + if (ret < 0) { + PCA954X_DEBUG("write cpld pca9548 reset reg failed, ret = %d \n", ret); + } +} + +u8 pca954x_get_umask_by_i2c(int addr) +{ + u8 value = 0xFF; + int ret; + + ret = pca954x_reset_reg_i2c_read_byte(addr, &value); + PCA954X_DEBUG("read i2c cpld[0x%x], value[%d], ret = %d\n", addr, value, ret); + + return value; +} + +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value) +{ + PCA954X_DEBUG("write lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + outb(value, (u16)io_port); +} + +u8 pca954x_get_umask_by_lpc(int io_port) +{ + u8 value; + + value = inb(io_port); + PCA954X_DEBUG("read lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + + return value; +} + +int pca954x_hw_do_reset_new(struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + pca9548_cfg_info_t *cfg_info; + int ret = -1; + + cfg_info = get_pca9548_cfg_info(adap->nr, client->addr); + if (cfg_info == NULL && g_notify_to_do_reset == NULL) { + PCA954X_DEBUG("fpga_do_pca954x_reset_func do nothing.\n"); + return ret; + } + if (cfg_info != NULL) { + ret = pca9548_reset_ctrl(cfg_info, adap, client, chan); + } else { + ret = pca954x_hw_do_reset(adap->nr, client->addr); + } + + if (ret < 0) { + PCA954X_DEBUG("pca954x_hw_do_reset failed.\n"); + } + return ret; +} +/******************************end 9548 reset***********************************/ + +static int pca954x_do_reset(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct i2c_client *new_client; + int ret = -1; + + PCA954X_DEBUG("do pca954x reset x86\n"); + new_client =(struct i2c_client *) client; + ret = pca954x_hw_do_reset_new(adap, new_client, chan); + if (ret < 0) { + PCA954X_DEBUG("pca954x_do_reset failed.\n"); + return ret; + } + + PCA954X_DEBUG("pca954x_do_reset success.\n"); + ret = 0; + return ret; +} + +static int pca954x_deselect_mux(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + int ret, rv; + struct i2c_client * new_client; + + /* Deselect active channel */ + data->last_chan = 0; + + ret = pca954x_reg_write(adap, client, data->last_chan); + + if (ret < 0) { + new_client =(struct i2c_client *) client; + dev_warn(&new_client->dev, "pca954x close chn failed, do reset.\n"); + rv = pca954x_do_reset(adap, client, chan); + if (rv == 0) { + ret = 0; + } + + } + + pca954x_setmuxflag(adap, 1); + (void)pca954x_reg_write(adap, client, data->last_chan); + + return ret; +} + +/* + * I2C init/probing/exit functions + */ +static int pca954x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct gpio_desc *gpio; + int num, force, class; + struct pca954x *data; + int ret; + + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + + /* Get the mux out of reset if a reset GPIO is specified. */ + gpio = devm_gpiod_get(&client->dev, "reset"); + if (!IS_ERR(gpio)) + gpiod_direction_output(gpio, 0); + + /* Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to disconnected state. + */ + if ((i2c_smbus_write_byte(client, 0) < 0) && (force_create_bus == 0)) { + dev_warn(&client->dev, "probe failed\n"); + return -ENODEV; + } + + data->type = id->driver_data; + data->last_chan = 0; /* force the first selection */ + + /* Now create an adapter for each channel */ + for (num = 0; num < chips[data->type].nchans; num++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + if (pdata) { + if (num < pdata->num_modes) { + /* force static number */ + force = pdata->modes[num].adap_id; + class = pdata->modes[num].class; + } else + /* discard unconfigured channels */ + break; + } + + data->virt_adaps[num] = + i2c_add_mux_adapter(adap, &client->dev, client, + force, num, class, pca954x_select_chan, pca954x_deselect_mux); + + if (data->virt_adaps[num] == NULL) { + ret = -ENODEV; + dev_err(&client->dev, + "failed to register multiplexed adapter" + " %d as bus %d\n", num, force); + goto virt_reg_failed; + } + } + + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s %s\n", + num, chips[data->type].muxtype == pca954x_ismux + ? "mux" : "switch", client->name); + + return 0; + +virt_reg_failed: + for (num--; num >= 0; num--) + i2c_del_mux_adapter(data->virt_adaps[num]); + return ret; +} + +static int pca954x_remove(struct i2c_client *client) +{ + struct pca954x *data = i2c_get_clientdata(client); + const struct chip_desc *chip = &chips[data->type]; + int i; + + for (i = 0; i < chip->nchans; ++i) + if (data->virt_adaps[i]) { + i2c_del_mux_adapter(data->virt_adaps[i]); + data->virt_adaps[i] = NULL; + } + + return 0; +} + +static struct i2c_driver pca954x_driver = { + .driver = { + .name = "pca954x", + .owner = THIS_MODULE, + }, + .probe = pca954x_probe, + .remove = pca954x_remove, + .id_table = pca954x_id, +}; + +module_i2c_driver(pca954x_driver); +#endif + +MODULE_AUTHOR("Rodolfo Giometti "); +MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca9641.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca9641.c new file mode 100644 index 000000000000..aecd8350a6fa --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/i2c-mux-pca9641.c @@ -0,0 +1,648 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * + * Author: Guenter Roeck + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * 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 +#include +#include +#include +#include + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) +#define PCA9641_ID 0x00 +#define PCA9641_ID_MAGIC 0x38 +#define PCA9641_CONTROL 0x01 +#define PCA9641_STATUS 0x02 +#define PCA9641_TIME 0x03 +#define PCA9641_CTL_LOCK_REQ BIT(0) +#define PCA9641_CTL_LOCK_GRANT BIT(1) +#define PCA9641_CTL_BUS_CONNECT BIT(2) +#define PCA9641_CTL_BUS_INIT BIT(3) +#define PCA9641_CTL_SMBUS_SWRST BIT(4) +#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5) +#define PCA9641_CTL_SMBUS_DIS BIT(6) +#define PCA9641_CTL_PRIORITY BIT(7) +#define PCA9641_STS_OTHER_LOCK BIT(0) +#define PCA9641_STS_BUS_INIT_FAIL BIT(1) +#define PCA9641_STS_BUS_HUNG BIT(2) +#define PCA9641_STS_MBOX_EMPTY BIT(3) +#define PCA9641_STS_MBOX_FULL BIT(4) +#define PCA9641_STS_TEST_INT BIT(5) +#define PCA9641_STS_SCL_IO BIT(6) +#define PCA9641_STS_SDA_IO BIT(7) +#define PCA9641_RES_TIME 0x03 +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) +#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \ + !((y) & PCA9641_STS_OTHER_LOCK)) +#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK) +#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT) + +#define PCA9641_RETRY_TIME 8 + +typedef struct i2c_muxs_struct_flag +{ + int nr; + char name[48]; + struct mutex update_lock; + int flag; +}i2c_mux_flag; + +i2c_mux_flag pca_flag = { + .flag = -1, +}; + +int pca9641_setmuxflag(int nr, int flag) +{ + if (pca_flag.nr == nr) { + pca_flag.flag = flag; + } + return 0; +} +EXPORT_SYMBOL(pca9641_setmuxflag); + +int g_debug = 0; +module_param(g_debug, int, S_IRUGO | S_IWUSR); + +#define PCA_DEBUG(fmt, args...) do { \ + if (g_debug) { \ + printk(KERN_ERR "[pca9641][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_client *client; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {"pca9641", 1}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca9541_of_match[] = { + { .compatible = "nxp,pca9541" }, + { .compatible = "nxp,pca9641" }, + {} +}; +MODULE_DEVICE_TABLE(of, pca9541_of_match); +#endif + + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = command; + buf[1] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + + data.byte = val; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + command, + I2C_SMBUS_BYTE_DATA, &data); + } + + return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + u8 val; + + if (adap->algo->master_xfer) { + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + ret = __i2c_transfer(adap, msg, 2); + if (ret == 2) + ret = val; + else if (ret >= 0) + ret = -EIO; + } else { + union i2c_smbus_data data; + + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_READ, + command, + I2C_SMBUS_BYTE_DATA, &data); + if (!ret) + ret = data.byte; + } + return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + pca9541_release_bus(client); + return 0; +} + +/* +* Arbitration management functions +*/ +static void pca9641_release_bus(struct i2c_client *client) +{ + pca9541_reg_write(client, PCA9641_CONTROL, 0x80); /* master 0x80 */ +} + +/* +* Channel arbitration +* +* Return values: +* <0: error +* 0 : bus not acquired +* 1 : bus acquired +*/ +static int pca9641_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg_ctl, reg_sts; + + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + if (reg_ctl < 0) + return reg_ctl; + reg_sts = pca9541_reg_read(client, PCA9641_STATUS); + + if (BUSOFF(reg_ctl, reg_sts)) { + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + + if (lock_grant(reg_ctl)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT + | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + data->select_timeout = SELECT_DELAY_SHORT; + + return 1; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (lock_grant(reg_ctl)) { + /* + * Bus is on, and we own it. We are done with acquisition. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + + return 1; + } else if (other_lock(reg_sts)) { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + } + return 0; +} + + +int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + int result; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + for (result = 0 ; result < PCA9641_RETRY_TIME ; result ++) { + do { + ret = pca9641_arbitrate(client); + if (ret == 1) { + return 0; + } + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + timeout = jiffies + ARB2_TIMEOUT; + } + return -ETIMEDOUT; +} +EXPORT_SYMBOL(pca9641_select_chan); + +static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + if (pca_flag.flag) { + pca9641_release_bus(client); + } + return 0; +} + +static int pca9641_detect_id(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9641_ID); + if (reg == PCA9641_ID_MAGIC) + return 1; + else + return 0; +} + +/** + ** Limited: 20180827 supports one PCA9641 + **/ +static int pca9641_recordflag(struct i2c_adapter *adap) { + if (pca_flag.flag != -1) { + pr_err(" %s %d has init already!!!", __func__, __LINE__); + return -1 ; + } + pca_flag.nr = adap->nr; + PCA_DEBUG(" adap->nr:%d\n", adap->nr); + snprintf(pca_flag.name, sizeof(pca_flag.name),adap->name); + return 0; +} + +static void i2c_lock_adapter(struct i2c_adapter *adapter){ + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + if (parent) + i2c_lock_adapter(parent); + else + rt_mutex_lock(&adapter->bus_lock); +} + +void i2c_unlock_adapter(struct i2c_adapter *adapter) +{ + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + i2c_unlock_adapter(parent); + else + rt_mutex_unlock(&adapter->bus_lock); +} +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct i2c_mux_core *muxc; + struct pca9541 *data; + int force; + int ret = -ENODEV; + int detect_id; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + detect_id = pca9641_detect_id(client); + + /* + * I2C accesses are unprotected here. + * We have to lock the adapter before releasing the bus. + */ + #if 0 + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + #endif + if (detect_id == 0) { + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + } else { + i2c_lock_adapter(adap); + pca9641_release_bus(client); + i2c_unlock_adapter(adap); + } + + /* Create mux adapter */ + + if (detect_id == 0) { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9541_select_chan, pca9541_release_chan); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + ret = i2c_mux_add_adapter(muxc, 0, 0, 0); + + if (ret) + return ret; + } else { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9641_select_chan, pca9641_release_chan); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) + return ret; + } + pca9641_recordflag(muxc->adapter[0]); + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; + +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + + i2c_mux_del_adapters(muxc); + return 0; +} + +static struct i2c_driver pca9641_driver = { + .driver = { + .name = "pca9641", + .of_match_table = of_match_ptr(pca9541_of_match), + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +module_i2c_driver(pca9641_driver); + +MODULE_AUTHOR("Guenter Roeck "); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/optoe.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/optoe.c new file mode 100644 index 000000000000..d7f327c3e7b3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/optoe.c @@ -0,0 +1,1198 @@ +/* + * optoe.c - A driver to read and write the EEPROM on optical transceivers + * (SFP, QSFP and similar I2C based devices) + * + * Copyright (C) 2014 Cumulus networks Inc. + * Copyright (C) 2017 Finisar Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Freeoftware Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/* + * Description: + * a) Optical transceiver EEPROM read/write transactions are just like + * the at24 eeproms managed by the at24.c i2c driver + * b) The register/memory layout is up to 256 128 byte pages defined by + * a "pages valid" register and switched via a "page select" + * register as explained in below diagram. + * c) 256 bytes are mapped at a time. 'Lower page 00h' is the first 128 + * bytes of address space, and always references the same + * location, independent of the page select register. + * All mapped pages are mapped into the upper 128 bytes + * (offset 128-255) of the i2c address. + * d) Devices with one I2C address (eg QSFP) use I2C address 0x50 + * (A0h in the spec), and map all pages in the upper 128 bytes + * of that address. + * e) Devices with two I2C addresses (eg SFP) have 256 bytes of data + * at I2C address 0x50, and 256 bytes of data at I2C address + * 0x51 (A2h in the spec). Page selection and paged access + * only apply to this second I2C address (0x51). + * e) The address space is presented, by the driver, as a linear + * address space. For devices with one I2C client at address + * 0x50 (eg QSFP), offset 0-127 are in the lower + * half of address 50/A0h/client[0]. Offset 128-255 are in + * page 0, 256-383 are page 1, etc. More generally, offset + * 'n' resides in page (n/128)-1. ('page -1' is the lower + * half, offset 0-127). + * f) For devices with two I2C clients at address 0x50 and 0x51 (eg SFP), + * the address space places offset 0-127 in the lower + * half of 50/A0/client[0], offset 128-255 in the upper + * half. Offset 256-383 is in the lower half of 51/A2/client[1]. + * Offset 384-511 is in page 0, in the upper half of 51/A2/... + * Offset 512-639 is in page 1, in the upper half of 51/A2/... + * Offset 'n' is in page (n/128)-3 (for n > 383) + * + * One I2c addressed (eg QSFP) Memory Map + * + * 2-Wire Serial Address: 1010000x + * + * Lower Page 00h (128 bytes) + * ===================== + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * |Page Select Byte(127)| + * ===================== + * | + * | + * | + * | + * V + * ------------------------------------------------------------ + * | | | | + * | | | | + * | | | | + * | | | | + * | | | | + * | | | | + * | | | | + * | | | | + * | | | | + * V V V V + * ------------ -------------- --------------- -------------- + * | | | | | | | | + * | Upper | | Upper | | Upper | | Upper | + * | Page 00h | | Page 01h | | Page 02h | | Page 03h | + * | | | (Optional) | | (Optional) | | (Optional | + * | | | | | | | for Cable | + * | | | | | | | Assemblies) | + * | ID | | AST | | User | | | + * | Fields | | Table | | EEPROM Data | | | + * | | | | | | | | + * | | | | | | | | + * | | | | | | | | + * ------------ -------------- --------------- -------------- + * + * The SFF 8436 (QSFP) spec only defines the 4 pages described above. + * In anticipation of future applications and devices, this driver + * supports access to the full architected range, 256 pages. + * + * The CMIS (Common Management Interface Specification) defines use of + * considerably more pages (at least to page 0xAF), which this driver + * supports. + * + * NOTE: This version of the driver ONLY SUPPORTS BANK 0 PAGES on CMIS + * devices. + * + **/ + +/* #define DEBUG 1 */ + +#undef EEPROM_CLASS +#ifdef CONFIG_EEPROM_CLASS +#define EEPROM_CLASS +#endif +#ifdef CONFIG_EEPROM_CLASS_MODULE +#define EEPROM_CLASS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef EEPROM_CLASS +#include +#endif + +#include + +/* The maximum length of a port name */ +#define MAX_PORT_NAME_LEN 20 + +struct optoe_platform_data { + u32 byte_len; /* size (sum of all addr) */ + u16 page_size; /* for writes */ + u8 flags; + void *dummy1; /* backward compatibility */ + void *dummy2; /* backward compatibility */ + +#ifdef EEPROM_CLASS + struct eeprom_platform_data *eeprom_data; +#endif + char port_name[MAX_PORT_NAME_LEN]; +}; + +/* fundamental unit of addressing for EEPROM */ +#define OPTOE_PAGE_SIZE 128 +/* + * Single address devices (eg QSFP) have 256 pages, plus the unpaged + * low 128 bytes. If the device does not support paging, it is + * only 2 'pages' long. + */ +#define OPTOE_ARCH_PAGES 256 +#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) +#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) +/* + * Dual address devices (eg SFP) have 256 pages, plus the unpaged + * low 128 bytes, plus 256 bytes at 0x50. If the device does not + * support paging, it is 4 'pages' long. + */ +#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) +#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) +#define TWO_ADDR_NO_0X51_SIZE (2 * OPTOE_PAGE_SIZE) + +/* a few constants to find our way around the EEPROM */ +#define OPTOE_PAGE_SELECT_REG 0x7F +#define ONE_ADDR_PAGEABLE_REG 0x02 +#define QSFP_NOT_PAGEABLE (1<<2) +#define CMIS_NOT_PAGEABLE (1<<7) +#define TWO_ADDR_PAGEABLE_REG 0x40 +#define TWO_ADDR_PAGEABLE (1<<4) +#define TWO_ADDR_0X51_REG 92 +#define TWO_ADDR_0X51_SUPP (1<<6) +#define OPTOE_ID_REG 0 +#define OPTOE_READ_OP 0 +#define OPTOE_WRITE_OP 1 +#define OPTOE_EOF 0 /* used for access beyond end of device */ + +struct optoe_data { + struct optoe_platform_data chip; + int use_smbus; + char port_name[MAX_PORT_NAME_LEN]; + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + struct bin_attribute bin; + struct attribute_group attr_group; + + u8 *writebuf; + unsigned int write_max; + + unsigned int num_addresses; + +#ifdef EEPROM_CLASS + struct eeprom_device *eeprom_dev; +#endif + + /* dev_class: ONE_ADDR (QSFP) or TWO_ADDR (SFP) */ + int dev_class; + + struct i2c_client *client[]; +}; + + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned int io_limit = OPTOE_PAGE_SIZE; + +/* + * specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned int write_timeout = 25; + +/* + * flags to distinguish one-address (QSFP family) from two-address (SFP family) + * If the family is not known, figure it out when the device is accessed + */ +#define ONE_ADDR 1 +#define TWO_ADDR 2 +#define CMIS_ADDR 3 + +static const struct i2c_device_id optoe_ids[] = { + { "optoe1", ONE_ADDR }, + { "optoe2", TWO_ADDR }, + { "optoe3", CMIS_ADDR }, + { "sff8436", ONE_ADDR }, + { "24c04", TWO_ADDR }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, optoe_ids); + +/*-------------------------------------------------------------------------*/ +/* + * This routine computes the addressing information to be used for + * a given r/w request. + * + * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), + * the page, and the offset. + * + * Handles both single address (eg QSFP) and two address (eg SFP). + * For SFP, offset 0-255 are on client[0], >255 is on client[1] + * Offset 256-383 are on the lower half of client[1] + * Pages are accessible on the upper half of client[1]. + * Offset >383 are in 128 byte pages mapped into the upper half + * + * For QSFP, all offsets are on client[0] + * offset 0-127 are on the lower half of client[0] (no paging) + * Pages are accessible on the upper half of client[1]. + * Offset >127 are in 128 byte pages mapped into the upper half + * + * Callers must not read/write beyond the end of a client or a page + * without recomputing the client/page. Hence offset (within page) + * plus length must be less than or equal to 128. (Note that this + * routine does not have access to the length of the call, hence + * cannot do the validity check.) + * + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ + +static uint8_t optoe_translate_offset(struct optoe_data *optoe, + loff_t *offset, struct i2c_client **client) +{ + unsigned int page = 0; + + *client = optoe->client[0]; + + /* if SFP style, offset > 255, shift to i2c addr 0x51 */ + if (optoe->dev_class == TWO_ADDR) { + if (*offset > 255) { + /* like QSFP, but shifted to client[1] */ + *client = optoe->client[1]; + *offset -= 256; + } + } + + /* + * if offset is in the range 0-128... + * page doesn't matter (using lower half), return 0. + * offset is already correct (don't add 128 to get to paged area) + */ + if (*offset < OPTOE_PAGE_SIZE) + return page; + + /* note, page will always be positive since *offset >= 128 */ + page = (*offset >> 7)-1; + /* 0x80 places the offset in the top half, offset is last 7 bits */ + *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); + + return page; /* note also returning client and offset */ +} + +static ssize_t optoe_eeprom_read(struct optoe_data *optoe, + struct i2c_client *client, + char *buf, unsigned int offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + unsigned long timeout, read_time; + int status, i; + + memset(msg, 0, sizeof(msg)); + + switch (optoe->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* + * When we have a better choice than SMBus calls, use a + * combined I2C message. Write address; then read up to + * io_limit data bytes. msgbuf is u8 and will cast to our + * needs. + */ + i = 0; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + switch (optoe->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + + dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) /* happy path */ + return count; + + if (status == -ENXIO) /* no module present */ + return status; + + /* REVISIT: at HZ=100, this is sloooow */ + usleep_range(1000, 2000); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t optoe_eeprom_write(struct optoe_data *optoe, + struct i2c_client *client, + const char *buf, + unsigned int offset, size_t count) +{ + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned int next_page_start; + int i = 0; + + /* write max is at most a page + * (In this driver, write_max is actually one byte!) + */ + if (count > optoe->write_max) + count = optoe->write_max; + + /* shorten count if necessary to avoid crossing page boundary */ + next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE); + if (offset + count > next_page_start) + count = next_page_start - offset; + + switch (optoe->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = optoe->writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + break; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + switch (optoe->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + break; + case I2C_SMBUS_WORD_DATA: + if (count == 2) { + status = i2c_smbus_write_word_data(client, + offset, (u16)((buf[0])|(buf[1] << 8))); + } else { + /* count = 1 */ + status = i2c_smbus_write_byte_data(client, + offset, buf[0]); + } + if (status == 0) + status = count; + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_write_byte_data(client, offset, + buf[0]); + if (status == 0) + status = count; + break; + default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + break; + } + + dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", + count, offset, (long int) status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + usleep_range(1000, 2000); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + + +static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, + char *buf, loff_t off, + size_t count, int opcode) +{ + struct i2c_client *client; + ssize_t retval = 0; + uint8_t page = 0; + loff_t phy_offset = off; + int ret = 0; + + page = optoe_translate_offset(optoe, &phy_offset, &client); + dev_dbg(&client->dev, + "%s off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", + __func__, off, page, phy_offset, (long int) count, opcode); + if (page > 0) { + ret = optoe_eeprom_write(optoe, client, &page, + OPTOE_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_dbg(&client->dev, + "Write page register for page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + + while (count) { + ssize_t status; + + if (opcode == OPTOE_READ_OP) { + status = optoe_eeprom_read(optoe, client, + buf, phy_offset, count); + } else { + status = optoe_eeprom_write(optoe, client, + buf, phy_offset, count); + } + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + phy_offset += status; + count -= status; + retval += status; + } + + + if (page > 0) { + /* return the page register to page 0 (why?) */ + page = 0; + ret = optoe_eeprom_write(optoe, client, &page, + OPTOE_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_err(&client->dev, + "Restore page register to 0 failed:%d!\n", ret); + /* error only if nothing has been transferred */ + if (retval == 0) + retval = ret; + } + } + return retval; +} + +/* + * Figure out if this access is within the range of supported pages. + * Note this is called on every access because we don't know if the + * module has been replaced since the last call. + * If/when modules support more pages, this is the routine to update + * to validate and allow access to additional pages. + * + * Returns updated len for this access: + * - entire access is legal, original len is returned. + * - access begins legal but is too long, len is truncated to fit. + * - initial offset exceeds supported pages, return OPTOE_EOF (zero) + */ +static ssize_t optoe_page_legal(struct optoe_data *optoe, + loff_t off, size_t len) +{ + struct i2c_client *client = optoe->client[0]; + u8 regval; + int not_pageable; + int status; + size_t maxlen; + + if (off < 0) + return -EINVAL; + if (optoe->dev_class == TWO_ADDR) { + /* SFP case */ + /* if only using addr 0x50 (first 256 bytes) we're good */ + if ((off + len) <= TWO_ADDR_NO_0X51_SIZE) + return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= TWO_ADDR_EEPROM_SIZE) + return OPTOE_EOF; + /* in between, are pages supported? */ + status = optoe_eeprom_read(optoe, client, ®val, + TWO_ADDR_PAGEABLE_REG, 1); + if (status < 0) + return status; /* error out (no module?) */ + if (regval & TWO_ADDR_PAGEABLE) { + /* Pages supported, trim len to the end of pages */ + maxlen = TWO_ADDR_EEPROM_SIZE - off; + } else { + /* pages not supported, trim len to unpaged size */ + if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE) + return OPTOE_EOF; + + /* will be accessing addr 0x51, is that supported? */ + /* byte 92, bit 6 implies DDM support, 0x51 support */ + status = optoe_eeprom_read(optoe, client, ®val, + TWO_ADDR_0X51_REG, 1); + if (status < 0) + return status; + if (regval & TWO_ADDR_0X51_SUPP) { + /* addr 0x51 is OK */ + maxlen = TWO_ADDR_EEPROM_UNPAGED_SIZE - off; + } else { + /* addr 0x51 NOT supported, trim to 256 max */ + if (off >= TWO_ADDR_NO_0X51_SIZE) + return OPTOE_EOF; + maxlen = TWO_ADDR_NO_0X51_SIZE - off; + } + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, SFP, off %lld len %ld\n", + off, (long int) len); + } else { + /* QSFP case, CMIS case */ + /* if no pages needed, we're good */ + if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) + return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= ONE_ADDR_EEPROM_SIZE) + return OPTOE_EOF; + /* in between, are pages supported? */ + status = optoe_eeprom_read(optoe, client, ®val, + ONE_ADDR_PAGEABLE_REG, 1); + if (status < 0) + return status; /* error out (no module?) */ + + if (optoe->dev_class == ONE_ADDR) { + not_pageable = QSFP_NOT_PAGEABLE; + } else { + not_pageable = CMIS_NOT_PAGEABLE; + } + dev_dbg(&client->dev, + "Paging Register: 0x%x; not_pageable mask: 0x%x\n", + regval, not_pageable); + + if (regval & not_pageable) { + /* pages not supported, trim len to unpaged size */ + if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) + return OPTOE_EOF; + maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; + } else { + /* Pages supported, trim len to the end of pages */ + maxlen = ONE_ADDR_EEPROM_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, QSFP, off %lld len %ld\n", + off, (long int) len); + } + return len; +} + +static ssize_t optoe_read_write(struct optoe_data *optoe, + char *buf, loff_t off, size_t len, int opcode) +{ + struct i2c_client *client = optoe->client[0]; + int chunk; + int status = 0; + ssize_t retval; + size_t pending_len = 0, chunk_len = 0; + loff_t chunk_offset = 0, chunk_start_offset = 0; + loff_t chunk_end_offset = 0; + + dev_dbg(&client->dev, + "%s: off %lld len:%ld, opcode:%s\n", + __func__, off, (long int) len, + (opcode == OPTOE_READ_OP) ? "r" : "w"); + if (unlikely(!len)) + return len; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&optoe->lock); + + /* + * Confirm this access fits within the device suppored addr range + */ + status = optoe_page_legal(optoe, off, len); + if ((status == OPTOE_EOF) || (status < 0)) { + mutex_unlock(&optoe->lock); + return status; + } + len = status; + + /* + * For each (128 byte) chunk involved in this request, issue a + * separate call to sff_eeprom_update_client(), to + * ensure that each access recalculates the client/page + * and writes the page register as needed. + * Note that chunk to page mapping is confusing, is different for + * QSFP and SFP, and never needs to be done. Don't try! + */ + pending_len = len; /* amount remaining to transfer */ + retval = 0; /* amount transferred */ + for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { + + /* + * Compute the offset and number of bytes to be read/write + * + * 1. start at an offset not equal to 0 (within the chunk) + * and read/write less than the rest of the chunk + * 2. start at an offset not equal to 0 and read/write the rest + * of the chunk + * 3. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 4. start at offset 0 (within the chunk), and read/write + * the entire chunk + */ + chunk_start_offset = chunk * OPTOE_PAGE_SIZE; + chunk_end_offset = chunk_start_offset + OPTOE_PAGE_SIZE; + + if (chunk_start_offset < off) { + chunk_offset = off; + if ((off + pending_len) < chunk_end_offset) + chunk_len = pending_len; + else + chunk_len = chunk_end_offset - off; + } else { + chunk_offset = chunk_start_offset; + if (pending_len < OPTOE_PAGE_SIZE) + chunk_len = pending_len; + else + chunk_len = OPTOE_PAGE_SIZE; + } + + dev_dbg(&client->dev, + "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", + off, (long int) len, chunk_start_offset, chunk_offset, + (long int) chunk_len, (long int) pending_len); + + /* + * note: chunk_offset is from the start of the EEPROM, + * not the start of the chunk + */ + status = optoe_eeprom_update_client(optoe, buf, + chunk_offset, chunk_len, opcode); + if (status != chunk_len) { + /* This is another 'no device present' path */ + dev_dbg(&client->dev, + "o_u_c: chunk %d c_offset %lld c_len %ld failed %d!\n", + chunk, chunk_offset, (long int) chunk_len, status); + if (status > 0) + retval += status; + if (retval == 0) + retval = status; + break; + } + buf += status; + pending_len -= status; + retval += status; + } + mutex_unlock(&optoe->lock); + + return retval; +} + +static ssize_t optoe_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, + struct device, kobj)); + struct optoe_data *optoe = i2c_get_clientdata(client); + + return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP); +} + + +static ssize_t optoe_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, + struct device, kobj)); + struct optoe_data *optoe = i2c_get_clientdata(client); + + return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP); +} + +static int optoe_remove(struct i2c_client *client) +{ + struct optoe_data *optoe; + int i; + + optoe = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); + sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); + + for (i = 1; i < optoe->num_addresses; i++) + i2c_unregister_device(optoe->client[i]); + +#ifdef EEPROM_CLASS + eeprom_device_unregister(optoe->eeprom_dev); +#endif + + kfree(optoe->writebuf); + kfree(optoe); + return 0; +} + +static ssize_t show_dev_class(struct device *dev, + struct device_attribute *dattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct optoe_data *optoe = i2c_get_clientdata(client); + ssize_t count; + + mutex_lock(&optoe->lock); + count = sprintf(buf, "%d\n", optoe->dev_class); + mutex_unlock(&optoe->lock); + + return count; +} + +static ssize_t set_dev_class(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct optoe_data *optoe = i2c_get_clientdata(client); + int dev_class; + + /* + * dev_class is actually the number of i2c addresses used, thus + * legal values are "1" (QSFP class) and "2" (SFP class) + * And... CMIS spec is 1 i2c address, but puts the pageable + * bit in a different location, so CMIS devices are "3" + */ + + if (kstrtoint(buf, 0, &dev_class) != 0 || + dev_class < 1 || dev_class > 3) + return -EINVAL; + + mutex_lock(&optoe->lock); + if (dev_class == TWO_ADDR) { + /* SFP family */ + /* if it doesn't exist, create 0x51 i2c address */ + if (!optoe->client[1]) { + optoe->client[1] = i2c_new_dummy_device(client->adapter, 0x51); + if (!optoe->client[1]) { + dev_err(&client->dev, + "address 0x51 unavailable\n"); + mutex_unlock(&optoe->lock); + return -EADDRINUSE; + } + } + optoe->bin.size = TWO_ADDR_EEPROM_SIZE; + optoe->num_addresses = 2; + } else { + /* one-address (eg QSFP) and CMIS family */ + /* if it exists, remove 0x51 i2c address */ + if (optoe->client[1]) + i2c_unregister_device(optoe->client[1]); + optoe->bin.size = ONE_ADDR_EEPROM_SIZE; + optoe->num_addresses = 1; + } + optoe->dev_class = dev_class; + mutex_unlock(&optoe->lock); + + return count; +} + +/* + * if using the EEPROM CLASS driver, we don't report a port_name, + * the EEPROM CLASS drive handles that. Hence all this code is + * only compiled if we are NOT using the EEPROM CLASS driver. + */ +#ifndef EEPROM_CLASS + +static ssize_t show_port_name(struct device *dev, + struct device_attribute *dattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct optoe_data *optoe = i2c_get_clientdata(client); + ssize_t count; + + mutex_lock(&optoe->lock); + count = sprintf(buf, "%s\n", optoe->port_name); + mutex_unlock(&optoe->lock); + + return count; +} + +static ssize_t set_port_name(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct optoe_data *optoe = i2c_get_clientdata(client); + char port_name[MAX_PORT_NAME_LEN]; + + /* no checking, this value is not used except by show_port_name */ + + if (sscanf(buf, "%19s", port_name) != 1) + return -EINVAL; + + mutex_lock(&optoe->lock); + strcpy(optoe->port_name, port_name); + mutex_unlock(&optoe->lock); + + return count; +} + +static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); +#endif /* if NOT defined EEPROM_CLASS, the common case */ + +static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); + +static struct attribute *optoe_attrs[] = { +#ifndef EEPROM_CLASS + &dev_attr_port_name.attr, +#endif + &dev_attr_dev_class.attr, + NULL, +}; + +static struct attribute_group optoe_attr_group = { + .attrs = optoe_attrs, +}; + +static int optoe_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err; + int use_smbus = 0; + struct optoe_platform_data chip; + struct optoe_data *optoe; + int num_addresses = 0; + char port_name[MAX_PORT_NAME_LEN]; + + if (client->addr != 0x50) { + dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", + client->addr); + err = -EINVAL; + goto exit; + } + + if (client->dev.platform_data) { + chip = *(struct optoe_platform_data *)client->dev.platform_data; + /* take the port name from the supplied platform data */ +#ifdef EEPROM_CLASS + strncpy(port_name, chip.eeprom_data->label, MAX_PORT_NAME_LEN); +#else + memcpy(port_name, chip.port_name, MAX_PORT_NAME_LEN); +#endif + dev_dbg(&client->dev, + "probe, chip provided, flags:0x%x; name: %s\n", + chip.flags, client->name); + } else { + if (!id->driver_data) { + err = -ENODEV; + goto exit; + } + dev_dbg(&client->dev, "probe, building chip\n"); + strcpy(port_name, "unitialized"); + chip.flags = 0; +#ifdef EEPROM_CLASS + chip.eeprom_data = NULL; +#endif + } + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + err = -EPFNOSUPPORT; + goto exit; + } + } + + + /* + * Make room for two i2c clients + */ + num_addresses = 2; + + optoe = kzalloc(sizeof(struct optoe_data) + + num_addresses * sizeof(struct i2c_client *), + GFP_KERNEL); + if (!optoe) { + err = -ENOMEM; + goto exit; + } + + mutex_init(&optoe->lock); + + /* determine whether this is a one-address or two-address module */ + if ((strcmp(client->name, "optoe1") == 0) || + (strcmp(client->name, "sff8436") == 0)) { + /* one-address (eg QSFP) family */ + optoe->dev_class = ONE_ADDR; + chip.byte_len = ONE_ADDR_EEPROM_SIZE; + num_addresses = 1; + } else if ((strcmp(client->name, "optoe2") == 0) || + (strcmp(client->name, "24c04") == 0)) { + /* SFP family */ + optoe->dev_class = TWO_ADDR; + chip.byte_len = TWO_ADDR_EEPROM_SIZE; + num_addresses = 2; + } else if (strcmp(client->name, "optoe3") == 0) { + /* CMIS spec */ + optoe->dev_class = CMIS_ADDR; + chip.byte_len = ONE_ADDR_EEPROM_SIZE; + num_addresses = 1; + } else { /* those were the only choices */ + err = -EINVAL; + goto exit; + } + + dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class); + optoe->use_smbus = use_smbus; + optoe->chip = chip; + optoe->num_addresses = num_addresses; + memcpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN); + + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + sysfs_bin_attr_init(&optoe->bin); + optoe->bin.attr.name = "eeprom"; + optoe->bin.attr.mode = 0444; + optoe->bin.read = optoe_bin_read; + optoe->bin.size = chip.byte_len; + + if (!use_smbus || + (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + /* + * NOTE: AN-2079 + * Finisar recommends that the host implement 1 byte writes + * only since this module only supports 32 byte page boundaries. + * 2 byte writes are acceptable for PE and Vout changes per + * Application Note AN-2071. + */ + unsigned int write_max = 1; + + optoe->bin.write = optoe_bin_write; + optoe->bin.attr.mode |= 0200; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + optoe->write_max = write_max; + + /* buffer (data + address at the beginning) */ + optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL); + if (!optoe->writebuf) { + err = -ENOMEM; + goto exit_kfree; + } + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + + optoe->client[0] = client; + + /* SFF-8472 spec requires that the second I2C address be 0x51 */ + if (num_addresses == 2) { + optoe->client[1] = i2c_new_dummy_device(client->adapter, 0x51); + if (!optoe->client[1]) { + dev_err(&client->dev, "address 0x51 unavailable\n"); + err = -EADDRINUSE; + goto err_struct; + } + } + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin); + if (err) + goto err_struct; + + optoe->attr_group = optoe_attr_group; + + err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group); + if (err) { + dev_err(&client->dev, "failed to create sysfs attribute group.\n"); + goto err_struct; + } + +#ifdef EEPROM_CLASS + optoe->eeprom_dev = eeprom_device_register(&client->dev, + chip.eeprom_data); + if (IS_ERR(optoe->eeprom_dev)) { + dev_err(&client->dev, "error registering eeprom device.\n"); + err = PTR_ERR(optoe->eeprom_dev); + goto err_sysfs_cleanup; + } +#endif + + i2c_set_clientdata(client, optoe); + + dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", + optoe->bin.size, client->name, + optoe->bin.write ? "read/write" : "read-only"); + + if (use_smbus == I2C_SMBUS_WORD_DATA || + use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, + "Falling back to %s reads, performance will suffer\n", + use_smbus == I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } + + return 0; + +#ifdef EEPROM_CLASS +err_sysfs_cleanup: + sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); + sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); +#endif + +err_struct: + if (num_addresses == 2) { + if (optoe->client[1]) + i2c_unregister_device(optoe->client[1]); + } + + kfree(optoe->writebuf); +exit_kfree: + kfree(optoe); +exit: + dev_dbg(&client->dev, "probe error %d\n", err); + + return err; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_driver optoe_driver = { + .driver = { + .name = "optoe", + .owner = THIS_MODULE, + }, + .probe = optoe_probe, + .remove = optoe_remove, + .id_table = optoe_ids, +}; + +static int __init optoe_init(void) +{ + + if (!io_limit) { + pr_err("optoe: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + return i2c_add_driver(&optoe_driver); +} +module_init(optoe_init); + +static void __exit optoe_exit(void) +{ + i2c_del_driver(&optoe_driver); +} +module_exit(optoe_exit); + +MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs"); +MODULE_AUTHOR("DON BOLLINGER "); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile.h new file mode 100644 index 000000000000..2ce1f43b3a5c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile.h @@ -0,0 +1,155 @@ +#ifndef __RAGILE_H__ +#define __RAGILE_H__ + +#include +#include +#include + +/* debug switch level */ +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +typedef enum dfd_cpld_id { + BCM_CPLD0 = 0, + BCM_CPLD1, + CPLD0_MAC0, + CPLD0_MAC1, + CPLD1_MAC0, + CPLD2_MAC1, +} dfd_cpld_id_t; + + typedef enum dfd_cpld_bus { + SMBUS_BUS = 0 , + GPIO_BUS = 1, + PCA9641_BUS = 2, +} dfd_cpld_bus_t; + + typedef struct dfd_i2c_dev_s { + int bus; /* bus number */ + int addr; /* bus address */ + } dfd_i2c_dev_t; + + typedef enum dfd_cpld_addr { + CPLD_ADDR_MIN = 0x31, + BCM_CPLD0_ADDR = 0x32, /* pca9641 up */ + CPLD0_MAC0_ADDR = 0x33, /* SMBUS down */ + CPLD0_MAC1_ADDR = 0x34, + CPLD1_MAC0_ADDR = 0x35, + CPLD2_MAC1_ADDR = 0x36, + BCM_CPLD1_ADDR = 0x37, + CPLD_ADDR_MAX, +} dfd_cpld_addr_t; + +typedef struct dfd_dev_head_info_s { + uint8_t ver; /* The version number defined by the E2PROM file, the initial version is 0x01 */ + uint8_t flag; /* The new version of E2PROM is identified as 0x7E */ + uint8_t hw_ver; /* It consists of two parts: the main version number and the revised version */ + uint8_t type; /* Hardware type definition information */ + int16_t tlv_len; /* Effective data length (16 bits) */ +} dfd_dev_head_info_t; + +typedef enum dfd_intf_e{ + DFD_INTF_GET_FAN_HW_VERSION, + DFD_INTF_GET_FAN_STATUS, + DFD_INTF_GET_FAN_SPEED_LEVEL, + DFD_INTF_GET_FAN_SPEED, + DFD_INTF_GET_FAN_ATTRIBUTE, + DFD_INTF_GET_FAN_SN, + DFD_INTF_GET_FAN_TYPE, + DFD_INTF_SET_FAN_SPEED_LEVEL, + DFD_INTF_GET_FAN_SUB_NUM, + DFD_INTF_GET_FAN_FAIL_BITMAP, +}dfd_intf_t; + +typedef struct dfd_dev_tlv_info_s { + uint8_t type; /* the type of data */ + uint8_t len; /* the length of data */ + uint8_t data[0]; /* data */ +} dfd_dev_tlv_info_t; + +typedef enum dfd_dev_info_type_e { + DFD_DEV_INFO_TYPE_MAC = 1, + DFD_DEV_INFO_TYPE_NAME = 2, + DFD_DEV_INFO_TYPE_SN = 3, + DFD_DEV_INFO_TYPE_PWR_CONS = 4, + DFD_DEV_INFO_TYPE_HW_INFO = 5, + DFD_DEV_INFO_TYPE_DEV_TYPE = 6, +} dfd_dev_tlv_type_t; + +struct sfp_drivers_t{ + /* addr = sff present bitmap addr, index from 0 */ + void (*get_number) (unsigned int *number); + int (*get_port_start) (void); + int (*get_port_end) (void); + bool (*is_qsfp_port) (const unsigned int port_num); + bool (*get_present) (unsigned long *bitmap); + bool (*read_sfp_eeprom) (const unsigned int port, + const unsigned char addr, + const unsigned char offset, + const uint32_t count, char *buf); + bool (*write_sfp_eeprom) (const unsigned int port, + const unsigned char addr, + const unsigned char offset, + const unsigned char count, + const char *buf); + bool (*read_sysfs) (const unsigned int bus, + const unsigned char addr, + const unsigned char offset, + const uint32_t count, char *buf); + bool (*write_sysfs) (const unsigned int bus, + const unsigned char addr, + const unsigned char offset, + const unsigned char count, + const char *buf); + bool (*read_block_sysfs) (const unsigned int bus, + const unsigned char addr, + const unsigned char offset, + const uint32_t count, char *buf); +}; + +extern int debuglevel; +extern int dfd_cpld_read_chipid(int cpldid , uint32_t addr, int32_t size, unsigned char *buf); +extern int dfd_cpld_read(int32_t addr, uint8_t *val); +extern int dfd_cpld_write(int32_t addr, uint8_t val); +extern int rg_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset, uint32_t size, unsigned char *buf) ; +extern int rg_i2c_write(uint32_t bus, uint32_t addr, uint32_t offset, uint8_t buf); +extern int rg_i2c_read_block(uint32_t bus, uint32_t addr, uint32_t offset, uint32_t size, unsigned char *buf) ; +extern int ragile_setdebug(int val); +extern s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command); +extern s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values); +extern s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command); + +extern int sfp_drivers_register(struct sfp_drivers_t *drv); +extern int sfp_drivers_unregister(void); + +extern int sysfs_drivers_register(struct sfp_drivers_t *drv); +extern int sysfs_drivers_unregister(void); + +#define DBG_DEBUG(fmt, arg...) do { \ + if ( debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else if ( debuglevel >= DBG_ERROR ) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else { } \ +} while (0) + +#define DBG_INFO(fmt, arg...) do { \ + if ( debuglevel > DBG_KEY) { \ + printk(KERN_INFO "[INFO]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } \ + } while (0) + +#define DBG_ERROR(fmt, arg...) do { \ + if ( debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } \ + } while (0) + +#endif diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_common_module.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_common_module.c new file mode 100644 index 000000000000..599eaa3fe5a4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_common_module.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ragile.h" +#include "dfd_tlveeprom.h" + +#define PLATFORM_I2C_RETRY_TIMES 3 + +#define DFD_TLVEEPROM_I2C_BUS (0) +#define DFD_TLVEEPROM_I2C_ADDR (0x56) +#define DFD_E2PROM_MAX_LEN (256) +#define DFD_CARDTYPE_EXT_TLVLEN (4) + +#define PLATFORM_CARDTYPE_RETRY_CNT (10) +#define PLATFORM_CARDTYPE_RETRY_TIMES (1000) + + +int debuglevel = 0; +module_param(debuglevel, int, S_IRUGO | S_IWUSR); + +static int dfd_my_type = 0; +module_param(dfd_my_type, int, S_IRUGO | S_IWUSR); + +int g_common_debug_error = 0; +module_param(g_common_debug_error, int, S_IRUGO | S_IWUSR); + +int g_common_debug_verbose = 0; +module_param(g_common_debug_verbose, int, S_IRUGO | S_IWUSR); + +uint32_t dfd_my_type_i2c_bus = 0; +module_param(dfd_my_type_i2c_bus, int, S_IRUGO | S_IWUSR); + +uint32_t dfd_my_type_i2c_addr = 0; +module_param(dfd_my_type_i2c_addr, int, S_IRUGO | S_IWUSR); + +#define RAGILE_COMMON_DEBUG_VERBOSE(fmt, args...) do { \ + if (g_common_debug_verbose) { \ + printk(KERN_ERR "[RAGILE_COMMON][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define RAGILE_COMMON_DEBUG_ERROR(fmt, args...) do { \ + if (g_common_debug_error) { \ + printk(KERN_ERR "[RAGILE_COMMON][ERROR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + + +static int32_t dfd_i2c_read(char *dev, uint32_t addr, uint32_t offset_addr, unsigned char * +buf, int32_t size) +{ + struct file *fp; + mm_segment_t fs; + struct i2c_client client; + int i ,j ; + int rv; + s32 val_t; + + val_t = -1; + rv = 0; + fp = filp_open(dev, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + DBG_ERROR("i2c open fail.\n"); + RAGILE_COMMON_DEBUG_ERROR("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = addr; + fs = get_fs(); + set_fs(KERNEL_DS); + for (j = 0 ;j < size ;j++){ + for (i = 0; i < PLATFORM_I2C_RETRY_TIMES; i++) { + if ((val_t = i2c_smbus_read_byte_data(&client, (offset_addr + j))) < 0) { + DBG_DEBUG("read try(%d)time offset_addr:%x \n", i, offset_addr); + continue; + } else { + * (buf + j) = val_t; + break; + } + } + if (val_t < 0) { + rv = -1; + break; + } + } + filp_close(fp, NULL); + set_fs(fs); + return rv; +} + + +static int dfd_tlvinfo_get_cardtype(void) +{ + char i2c_path[16] = {0}; + int ret; + int cardtype; + u_int8_t eeprom[DFD_E2PROM_MAX_LEN]; + dfd_i2c_dev_t i2c_dev; + uint8_t buf[DFD_CARDTYPE_EXT_TLVLEN]; + uint8_t len; + dfd_tlv_type_t tlv_type; + + if (dfd_my_type_i2c_bus != 0) { + i2c_dev.bus = dfd_my_type_i2c_bus; + } else { + i2c_dev.bus = DFD_TLVEEPROM_I2C_BUS; + } + + if (dfd_my_type_i2c_addr != 0) { + i2c_dev.addr = dfd_my_type_i2c_addr; + } else { + i2c_dev.addr = DFD_TLVEEPROM_I2C_ADDR; + } + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_dev.bus); + RAGILE_COMMON_DEBUG_VERBOSE("Read device eeprom info:(dev:%s, addr:%02x).\n", i2c_path, i2c_dev.addr); + + ret = dfd_i2c_read(i2c_path, i2c_dev.addr, 0, eeprom, DFD_E2PROM_MAX_LEN); + if (ret != 0) { + DBG_ERROR("Read eeprom info error(dev: %s, addr: %02x).\n", i2c_path, i2c_dev.addr); + RAGILE_COMMON_DEBUG_ERROR("Read eeprom info error(dev: %s, addr: %02x).\n", i2c_path, i2c_dev.addr); + return ret; + } + + tlv_type.main_type = TLV_CODE_VENDOR_EXT; + tlv_type.ext_type = DFD_TLVINFO_EXT_TLV_TYPE_DEV_TYPE; + len = sizeof(buf); + memset(buf, 0, len); + ret = dfd_tlvinfo_get_e2prom_info(eeprom, DFD_E2PROM_MAX_LEN, &tlv_type, buf, &len); + if (ret) { + DBG_ERROR("dfd_tlvinfo_get_e2prom_info failed ret %d.\n", ret); + return -1; + } + for (ret = 0; ret < 4; ret++) { + DBG_DEBUG("buf 0x%02x.\n", buf[ret]); + } + + cardtype = ntohl(*((uint32_t *)buf)); + DBG_DEBUG("cardtype 0x%x.\n", cardtype); + return cardtype; +} + +static int __dfd_get_my_card_type(void) +{ + return dfd_tlvinfo_get_cardtype(); +} + +/* Get its own card type */ +int dfd_get_my_card_type(void) +{ + int type; + int cnt; + + if (dfd_my_type != 0) { + DBG_DEBUG("my_type = 0x%x\r\n", dfd_my_type); + return dfd_my_type; + } + + cnt = PLATFORM_CARDTYPE_RETRY_CNT; + while (cnt--) { + type = __dfd_get_my_card_type(); + if (type < 0) { + RAGILE_COMMON_DEBUG_ERROR("__dfd_get_my_card_type fail cnt %d, ret %d.\n", cnt, type); + msleep(PLATFORM_CARDTYPE_RETRY_TIMES); + continue; + } + RAGILE_COMMON_DEBUG_VERBOSE("success to get type 0x%x.\n", type); + break; + } + + + + dfd_my_type = type; + return dfd_my_type; +} +EXPORT_SYMBOL(dfd_get_my_card_type); + +static int __init ragile_common_init(void) +{ + int ret; + + RAGILE_COMMON_DEBUG_VERBOSE("Enter.\n"); + ret = dfd_get_my_card_type(); + if (ret <= 0) { + RAGILE_COMMON_DEBUG_ERROR("dfd_get_my_card_type failed, ret %d.\n", ret); + printk(KERN_ERR "Warning: Device type get failed, please check the TLV-EEPROM!\n"); + return -1; + } + + RAGILE_COMMON_DEBUG_VERBOSE("Leave success type 0x%x.\n", ret); + return 0; +} + +static void __exit ragile_common_exit(void) +{ + RAGILE_COMMON_DEBUG_VERBOSE("Exit.\n"); +} + +module_init(ragile_common_init); +module_exit(ragile_common_exit); + +MODULE_DESCRIPTION("ragile Platform Support"); +MODULE_AUTHOR("tangjiamiao "); +MODULE_LICENSE("GPL"); + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_platform.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_platform.c new file mode 100644 index 000000000000..15b19a14fb6d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/ragile_platform.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ragile.h" + +#define PLATFORM_I2C_RETRY_TIMES 3 + +s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_byte_data(client, command)) >= 0 ) + break; + } + return ret; + +} +EXPORT_SYMBOL(platform_i2c_smbus_read_byte_data); + +s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values)) >= 0 ) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_i2c_block_data); + +s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_word_data(client, command)) >= 0 ) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_word_data); + +static int __init ragile_platform_init(void) +{ + return 0; +} + +static void __exit ragile_platform_exit(void) +{ + +} + +module_init(ragile_platform_init); +module_exit(ragile_platform_exit); + +MODULE_DESCRIPTION("ragile Platform Support"); +MODULE_AUTHOR("tangjiamiao "); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rg_spi_gpio.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rg_spi_gpio.c new file mode 100644 index 000000000000..a359462b0436 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rg_spi_gpio.c @@ -0,0 +1,94 @@ +/* + * EEPROMs access control driver for display configuration EEPROMs + * on DigsyMTC board. + * + * (C) 2011 DENX Software Engineering, Anatolij Gustschin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define GPIO_TPM_CLK 496 +#define GPIO_TPM_CS 500 +#define GPIO_TPM_DI 499 +#define GPIO_TPM_DO 498 + +#define EE_SPI_BUS_NUM 1 + + +static struct spi_gpio_platform_data tpm_spi_gpio_data = { + .sck = GPIO_TPM_CLK, + .mosi = GPIO_TPM_DI, + .miso = GPIO_TPM_DO, + .num_chipselect = 2, +}; + +static void spi_gpio_release(struct device *dev) +{ + return; +} +static struct platform_device tpm_device = { + .name = "spi_gpio", + .id = 3, + .dev = { + .platform_data = &tpm_spi_gpio_data, + .release = spi_gpio_release, + } +}; + +static struct spi_board_info tpm_info = { + .modalias = "tpm_tis_spi", + .max_speed_hz = 1000000, + .bus_num = 3, + .chip_select = 0, /* 0 ,1 */ + .mode = SPI_MODE_0, + .controller_data = (void *)GPIO_TPM_CS, +}; + +static int __init tpm_devices_init(void) +{ + int ret; + struct spi_master *master; + + ret = platform_device_register(&tpm_device); + if (ret) { + printk("can't add spi-gpio device \n"); + return ret; + } + + master = spi_busnum_to_master(tpm_info.bus_num); + if( !master ) { + return -ENODEV; + } + printk(KERN_INFO "enter tpm_devices_init. \n"); + + spi_new_device(master, &tpm_info); + return 0 ; +} + + +static void __exit tpm_devices_exit(void) +{ + platform_device_unregister(&tpm_device); +} + +module_init(tpm_devices_init); +module_exit(tpm_devices_exit); + +MODULE_DESCRIPTION("ragile spi gpio device Support"); +MODULE_AUTHOR("support@ragilenetworks.com"); +MODULE_LICENSE("GPL"); + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rtc-pcf85063.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rtc-pcf85063.c new file mode 100644 index 000000000000..61e41b5130cb --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/rtc-pcf85063.c @@ -0,0 +1,262 @@ +/* + * An I2C driver for the PCF85063 RTC + * Copyright 2014 Rose Technology + * + * Author: Søren Andersen + * Maintainers: http://www.nslu2-linux.org/ + * + * based on the other drivers in this same directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include + +/* + * Information for this driver was pulled from the following datasheets. + * + * http://www.nxp.com/documents/data_sheet/PCF85063A.pdf + * http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf + * + * PCF85063A -- Rev. 6 — 18 November 2015 + * PCF85063TP -- Rev. 4 — 6 May 2015 +*/ + +#define PCF85063_REG_CTRL1 0x00 /* status */ +#define PCF85063_REG_CTRL1_CAP_SEL BIT(0) +#define PCF85063_REG_CTRL1_STOP BIT(5) +#define PCF85063_REG_CTRL2 0x01 +#define PCF85063_REG_CTRL2_COF 0x07 +#define PCF85063_REG_SC 0x04 /* datetime */ +#define PCF85063_REG_SC_OS 0x80 +#define PCF85063_REG_MN 0x05 +#define PCF85063_REG_HR 0x06 +#define PCF85063_REG_DM 0x07 +#define PCF85063_REG_DW 0x08 +#define PCF85063_REG_MO 0x09 +#define PCF85063_REG_YR 0x0A +#define PCF85063_SR 0x58 + +static struct i2c_driver pcf85063_driver; + +static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1) +{ + s32 ret; + + ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1); + if (ret < 0) { + dev_err(&client->dev, "Failing to stop the clock\n"); + return -EIO; + } + + /* stop the clock */ + ret |= PCF85063_REG_CTRL1_STOP; + + ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&client->dev, "Failing to stop the clock\n"); + return -EIO; + } + + *ctrl1 = ret; + + return 0; +} + +static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1) +{ + s32 ret; + + /* start the clock */ + ctrl1 &= ~PCF85063_REG_CTRL1_STOP; + ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1); + if (ret < 0) { + dev_err(&client->dev, "Failing to start the clock\n"); + return -EIO; + } + + return 0; +} + +static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + int rc; + u8 regs[7]; + + /* + * while reading, the time/date registers are blocked and not updated + * anymore until the access is finished. To not lose a second + * event, the access must be finished within one second. So, read all + * time/date registers in one turn. + */ + rc = i2c_smbus_read_i2c_block_data(client, PCF85063_REG_SC, + sizeof(regs), regs); + if (rc != sizeof(regs)) { + dev_err(&client->dev, "date/time register read error\n"); + return -EIO; + } + + /* if the clock has lost its power it makes no sense to use its time */ + if (regs[0] & PCF85063_REG_SC_OS) { + dev_warn(&client->dev, "Power loss detected, invalid time\n"); + return -EINVAL; + } + + tm->tm_sec = bcd2bin(regs[0] & 0x7F); + tm->tm_min = bcd2bin(regs[1] & 0x7F); + tm->tm_hour = bcd2bin(regs[2] & 0x3F); /* rtc hr 0-23 */ + tm->tm_mday = bcd2bin(regs[3] & 0x3F); + tm->tm_wday = regs[4] & 0x07; + tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */ + tm->tm_year = bcd2bin(regs[6]); + tm->tm_year += 100; + + return rtc_valid_tm(tm); +} + +static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + int rc; + u8 regs[7]; + u8 ctrl1; + u8 cof; + s32 err; + + cof = 0; + cof |= PCF85063_REG_CTRL2_COF; + if ((tm->tm_year < 100) || (tm->tm_year > 199)) + return -EINVAL; + + /* reset rtc-pcf85063 */ + err = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, PCF85063_SR); + if (err < 0) { + dev_err(&client->dev, "Failing to reset rtc-pcf85063\n"); + return EIO; + } + + /* + * to accurately set the time, reset the divider chain and keep it in + * reset state until all time/date registers are written + */ + rc = pcf85063_stop_clock(client, &ctrl1); + if (rc != 0) + return rc; + + /* set CTRL1 CAP_SEL is 12.5pF */ + ctrl1 |= PCF85063_REG_CTRL1_CAP_SEL; + err = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1); + if (err < 0) { + dev_err(&client->dev, "Failing to write the PCF85063_REG_CTRL1\n"); + return -EIO; + } + /* set CTRL2 CLKOUT is LOW */ + err = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL2, cof); + if (err < 0) { + dev_err(&client->dev, "Failing to write the PCF85063_REG_CTRL2\n"); + return -EIO; + } + + /* hours, minutes and seconds */ + regs[0] = bin2bcd(tm->tm_sec) & 0x7F; /* clear OS flag */ + + regs[1] = bin2bcd(tm->tm_min); + regs[2] = bin2bcd(tm->tm_hour); + + /* Day of month, 1 - 31 */ + regs[3] = bin2bcd(tm->tm_mday); + + /* Day, 0 - 6 */ + regs[4] = tm->tm_wday & 0x07; + + /* month, 1 - 12 */ + regs[5] = bin2bcd(tm->tm_mon + 1); + + /* year and century */ + regs[6] = bin2bcd(tm->tm_year - 100); + + /* write all registers at once */ + rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC, + sizeof(regs), regs); + if (rc < 0) { + dev_err(&client->dev, "date/time register write error\n"); + return rc; + } + + /* + * Write the control register as a separate action since the size of + * the register space is different between the PCF85063TP and + * PCF85063A devices. The rollover point can not be used. + */ + rc = pcf85063_start_clock(client, ctrl1); + if (rc != 0) + return rc; + + return 0; +} + +static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return pcf85063_get_datetime(to_i2c_client(dev), tm); +} + +static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return pcf85063_set_datetime(to_i2c_client(dev), tm); +} + +static const struct rtc_class_ops pcf85063_rtc_ops = { + .read_time = pcf85063_rtc_read_time, + .set_time = pcf85063_rtc_set_time +}; + +static int pcf85063_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct rtc_device *rtc; + + dev_dbg(&client->dev, "%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + rtc = devm_rtc_device_register(&client->dev, + pcf85063_driver.driver.name, + &pcf85063_rtc_ops, THIS_MODULE); + + rtc->uie_unsupported = 1; + + return PTR_ERR_OR_ZERO(rtc); +} + +static const struct i2c_device_id pcf85063_id[] = { + { "pcf85063", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcf85063_id); + + +static const struct of_device_id pcf85063_of_match[] = { + { .compatible = "nxp,pcf85063" }, + {} +}; +MODULE_DEVICE_TABLE(of, pcf85063_of_match); + + +static struct i2c_driver pcf85063_driver = { + .driver = { + .name = "rtc-pcf85063", + .of_match_table = of_match_ptr(pcf85063_of_match), + }, + .probe = pcf85063_probe, + .id_table = pcf85063_id, +}; + +module_i2c_driver(pcf85063_driver); + +MODULE_AUTHOR("Søren Andersen "); +MODULE_DESCRIPTION("PCF85063 RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-bitbang-txrx.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-bitbang-txrx.h new file mode 100644 index 000000000000..47bb9b898dfd --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-bitbang-txrx.h @@ -0,0 +1,107 @@ +/* + * Mix this utility code with some glue code to get one of several types of + * simple SPI master driver. Two do polled word-at-a-time I/O: + * + * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](), + * expanding the per-word routines from the inline templates below. + * + * - Drivers for controllers resembling bare shift registers. Provide + * chipselect() and txrx_word[](), with custom setup()/cleanup() methods + * that use your controller's clock and chipselect registers. + * + * Some hardware works well with requests at spi_transfer scope: + * + * - Drivers leveraging smarter hardware, with fifos or DMA; or for half + * duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(), + * and custom setup()/cleanup() methods. + */ + +/* + * The code that knows what GPIO pins do what should have declared four + * functions, ideally as inlines, before including this header: + * + * void setsck(struct spi_device *, int is_on); + * void setmosi(struct spi_device *, int is_on); + * int getmiso(struct spi_device *); + * void spidelay(unsigned); + * + * setsck()'s is_on parameter is a zero/nonzero boolean. + * + * setmosi()'s is_on parameter is a zero/nonzero boolean. + * + * getmiso() is required to return 0 or 1 only. Any other value is invalid + * and will result in improper operation. + * + * A non-inlined routine would call bitbang_txrx_*() routines. The + * main loop could easily compile down to a handful of instructions, + * especially if the delay is a NOP (to run at peak speed). + * + * Since this is software, the timings may not be exactly what your board's + * chips need ... there may be several reasons you'd need to tweak timings + * in these routines, not just to make it faster or slower to match a + * particular CPU clock rate. + */ + +static inline u32 +bitbang_txrx_be_cpha0(struct spi_device *spi, + unsigned nsecs, unsigned cpol, unsigned flags, + u32 word, u8 bits) +{ + /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ + + u32 oldbit = (!(word & (1<<(bits-1)))) << 31; + /* clock starts at inactive polarity */ + for (word <<= (32 - bits); likely(bits); bits--) { + + /* setup MSB (to slave) on trailing edge */ + if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((word & (1 << 31)) != oldbit) { + setmosi(spi, word & (1 << 31)); + oldbit = word & (1 << 31); + } + } + spidelay(nsecs); /* T(setup) */ + + setsck(spi, !cpol); + spidelay(nsecs); + + /* sample MSB (from slave) on leading edge */ + word <<= 1; + if ((flags & SPI_MASTER_NO_RX) == 0) + word |= getmiso(spi); + setsck(spi, cpol); + } + return word; +} + +static inline u32 +bitbang_txrx_be_cpha1(struct spi_device *spi, + unsigned nsecs, unsigned cpol, unsigned flags, + u32 word, u8 bits) +{ + /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ + + u32 oldbit = (!(word & (1<<(bits-1)))) << 31; + /* clock starts at inactive polarity */ + for (word <<= (32 - bits); likely(bits); bits--) { + + /* setup MSB (to slave) on leading edge */ + setsck(spi, !cpol); + if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((word & (1 << 31)) != oldbit) { + setmosi(spi, word & (1 << 31)); + oldbit = word & (1 << 31); + } + } + spidelay(nsecs); /* T(setup) */ + + setsck(spi, cpol); + spidelay(nsecs); + + /* sample MSB (from slave) on trailing edge */ + word <<= 1; + if ((flags & SPI_MASTER_NO_RX) == 0) + word |= getmiso(spi); + } + return word; +} diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-gpio.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-gpio.c new file mode 100644 index 000000000000..1c34c9314c8a --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/spi-gpio.c @@ -0,0 +1,547 @@ +/* + * SPI master driver using generic bitbanged GPIO + * + * Copyright (C) 2006,2008 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* + * This bitbanging SPI master driver should help make systems usable + * when a native hardware SPI engine is not available, perhaps because + * its driver isn't yet working or because the I/O pins it requires + * are used for other purposes. + * + * platform_device->driver_data ... points to spi_gpio + * + * spi->controller_state ... reserved for bitbang framework code + * spi->controller_data ... holds chipselect GPIO + * + * spi->master->dev.driver_data ... points to spi_gpio->bitbang + */ + +struct spi_gpio { + struct spi_bitbang bitbang; + struct spi_gpio_platform_data pdata; + struct platform_device *pdev; + unsigned long cs_gpios[0]; +}; + +/*----------------------------------------------------------------------*/ + +/* + * Because the overhead of going through four GPIO procedure calls + * per transferred bit can make performance a problem, this code + * is set up so that you can use it in either of two ways: + * + * - The slow generic way: set up platform_data to hold the GPIO + * numbers used for MISO/MOSI/SCK, and issue procedure calls for + * each of them. This driver can handle several such busses. + * + * - The quicker inlined way: only helps with platform GPIO code + * that inlines operations for constant GPIOs. This can give + * you tight (fast!) inner loops, but each such bus needs a + * new driver. You'll define a new C file, with Makefile and + * Kconfig support; the C code can be a total of six lines: + * + * #define DRIVER_NAME "myboard_spi2" + * #define SPI_MISO_GPIO 119 + * #define SPI_MOSI_GPIO 120 + * #define SPI_SCK_GPIO 121 + * #define SPI_N_CHIPSEL 4 + * #include "spi-gpio.c" + */ + +#ifndef DRIVER_NAME +#define DRIVER_NAME "spi_gpio" + +#define GENERIC_BITBANG /* vs tight inlines */ + +/* all functions referencing these symbols must define pdata */ +#define SPI_MISO_GPIO ((pdata)->miso) +#define SPI_MOSI_GPIO ((pdata)->mosi) +#define SPI_SCK_GPIO ((pdata)->sck) + +#define SPI_N_CHIPSEL ((pdata)->num_chipselect) + +#endif + +/*----------------------------------------------------------------------*/ + +static inline struct spi_gpio *__pure +spi_to_spi_gpio(const struct spi_device *spi) +{ + const struct spi_bitbang *bang; + struct spi_gpio *spi_gpio; + + bang = spi_master_get_devdata(spi->master); + spi_gpio = container_of(bang, struct spi_gpio, bitbang); + return spi_gpio; +} + +static inline struct spi_gpio_platform_data *__pure +spi_to_pdata(const struct spi_device *spi) +{ + return &spi_to_spi_gpio(spi)->pdata; +} + +/* this is #defined to avoid unused-variable warnings when inlining */ +#define pdata spi_to_pdata(spi) + +static inline void setsck(const struct spi_device *spi, int is_on) +{ + gpio_set_value_cansleep(SPI_SCK_GPIO, is_on); +} + +static inline void setmosi(const struct spi_device *spi, int is_on) +{ + gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on); +} + +static inline int getmiso(const struct spi_device *spi) +{ + return !!gpio_get_value_cansleep(SPI_MISO_GPIO); +} + +#undef pdata + +/* + * NOTE: this clocks "as fast as we can". It "should" be a function of the + * requested device clock. Software overhead means we usually have trouble + * reaching even one Mbit/sec (except when we can inline bitops), so for now + * we'll just assume we never need additional per-bit slowdowns. + */ +#define spidelay(nsecs) do {} while (0) + +#include "spi-bitbang-txrx.h" + +/* + * These functions can leverage inline expansion of GPIO calls to shrink + * costs for a txrx bit, often by factors of around ten (by instruction + * count). That is particularly visible for larger word sizes, but helps + * even with default 8-bit words. + * + * REVISIT overheads calling these functions for each word also have + * significant performance costs. Having txrx_bufs() calls that inline + * the txrx_word() logic would help performance, e.g. on larger blocks + * used with flash storage or MMC/SD. There should also be ways to make + * GCC be less stupid about reloading registers inside the I/O loops, + * even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3? + */ + +static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); +} + +static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); +} + +static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); +} + +static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); +} + +/* + * These functions do not call setmosi or getmiso if respective flag + * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to + * call when such pin is not present or defined in the controller. + * A separate set of callbacks is defined to get highest possible + * speed in the generic case (when both MISO and MOSI lines are + * available), as optimiser will remove the checks when argument is + * constant. + */ + +static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + unsigned flags = spi->master->flags; + return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); +} + +static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + unsigned flags = spi->master->flags; + return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); +} + +static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + unsigned flags = spi->master->flags; + return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); +} + +static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + unsigned flags = spi->master->flags; + return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); +} + +/*----------------------------------------------------------------------*/ + +static void spi_gpio_chipselect(struct spi_device *spi, int is_active) +{ + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + unsigned long cs = spi_gpio->cs_gpios[spi->chip_select]; + + /* set initial clock polarity */ + if (is_active) + setsck(spi, spi->mode & SPI_CPOL); + + if (cs != SPI_GPIO_NO_CHIPSELECT) { + /* SPI is normally active-low */ + gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); + } +} + +static int spi_gpio_setup(struct spi_device *spi) +{ + unsigned long cs; + int status = 0; + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + struct device_node *np = spi->master->dev.of_node; + + if (np) { + /* + * In DT environments, the CS GPIOs have already been + * initialized from the "cs-gpios" property of the node. + */ + cs = spi_gpio->cs_gpios[spi->chip_select]; + } else { + /* + * ... otherwise, take it from spi->controller_data + */ + cs = (uintptr_t) spi->controller_data; + } + + if (!spi->controller_state) { + if (cs != SPI_GPIO_NO_CHIPSELECT) { + status = gpio_request(cs, dev_name(&spi->dev)); + if (status) + return status; + status = gpio_direction_output(cs, + !(spi->mode & SPI_CS_HIGH)); + } + } + if (!status) { + /* in case it was initialized from static board data */ + spi_gpio->cs_gpios[spi->chip_select] = cs; + status = spi_bitbang_setup(spi); + } + + if (status) { + if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT) + gpio_free(cs); + } + return status; +} + +static void spi_gpio_cleanup(struct spi_device *spi) +{ + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + unsigned long cs = spi_gpio->cs_gpios[spi->chip_select]; + + if (cs != SPI_GPIO_NO_CHIPSELECT) + gpio_free(cs); + spi_bitbang_cleanup(spi); +} + +static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in) +{ + int value; + + value = gpio_request(pin, label); + if (value == 0) { + if (is_in) + value = gpio_direction_input(pin); + else + value = gpio_direction_output(pin, 0); + } + return value; +} + +static int spi_gpio_request(struct spi_gpio_platform_data *pdata, + const char *label, u16 *res_flags) +{ + int value; + + /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ + + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) { + value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); + if (value) + goto done; + } else { + /* HW configuration without MOSI pin */ + *res_flags |= SPI_MASTER_NO_TX; + } + + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) { + value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); + if (value) + goto free_mosi; + } else { + /* HW configuration without MISO pin */ + *res_flags |= SPI_MASTER_NO_RX; + } + + value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); + if (value) + goto free_miso; + + goto done; + +free_miso: + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) + gpio_free(SPI_MISO_GPIO); +free_mosi: + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) + gpio_free(SPI_MOSI_GPIO); +done: + return value; +} + +#ifdef CONFIG_OF +static const struct of_device_id spi_gpio_dt_ids[] = { + { .compatible = "spi-gpio" }, + {} +}; +MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); + +static int spi_gpio_probe_dt(struct platform_device *pdev) +{ + int ret; + u32 tmp; + struct spi_gpio_platform_data *pdata; + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *of_id = + of_match_device(spi_gpio_dt_ids, &pdev->dev); + + if (!of_id) + return 0; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = of_get_named_gpio(np, "gpio-sck", 0); + if (ret < 0) { + dev_err(&pdev->dev, "gpio-sck property not found\n"); + goto error_free; + } + pdata->sck = ret; + + ret = of_get_named_gpio(np, "gpio-miso", 0); + if (ret < 0) { + dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n"); + pdata->miso = SPI_GPIO_NO_MISO; + } else + pdata->miso = ret; + + ret = of_get_named_gpio(np, "gpio-mosi", 0); + if (ret < 0) { + dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n"); + pdata->mosi = SPI_GPIO_NO_MOSI; + } else + pdata->mosi = ret; + + ret = of_property_read_u32(np, "num-chipselects", &tmp); + if (ret < 0) { + dev_err(&pdev->dev, "num-chipselects property not found\n"); + goto error_free; + } + + pdata->num_chipselect = tmp; + pdev->dev.platform_data = pdata; + + return 1; + +error_free: + devm_kfree(&pdev->dev, pdata); + return ret; +} +#else +static inline int spi_gpio_probe_dt(struct platform_device *pdev) +{ + return 0; +} +#endif + +static int spi_gpio_probe(struct platform_device *pdev) +{ + int status; + struct spi_master *master; + struct spi_gpio *spi_gpio; + struct spi_gpio_platform_data *pdata; + u16 master_flags = 0; + bool use_of = 0; + int num_devices; + + status = spi_gpio_probe_dt(pdev); + if (status < 0) + return status; + if (status > 0) + use_of = 1; + + pdata = dev_get_platdata(&pdev->dev); +#ifdef GENERIC_BITBANG + if (!pdata || (!use_of && !pdata->num_chipselect)) + return -ENODEV; +#endif + + if (use_of && !SPI_N_CHIPSEL) + num_devices = 1; + else + num_devices = SPI_N_CHIPSEL; + + status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); + if (status < 0) + return status; + + master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) + + (sizeof(unsigned long) * num_devices)); + if (!master) { + status = -ENOMEM; + goto gpio_free; + } + spi_gpio = spi_master_get_devdata(master); + platform_set_drvdata(pdev, spi_gpio); + + spi_gpio->pdev = pdev; + if (pdata) + spi_gpio->pdata = *pdata; + + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); + master->flags = master_flags; + master->bus_num = pdev->id; + master->num_chipselect = num_devices; + master->setup = spi_gpio_setup; + master->cleanup = spi_gpio_cleanup; +#ifdef CONFIG_OF + master->dev.of_node = pdev->dev.of_node; + + if (use_of) { + int i; + struct device_node *np = pdev->dev.of_node; + + /* + * In DT environments, take the CS GPIO from the "cs-gpios" + * property of the node. + */ + + if (!SPI_N_CHIPSEL) + spi_gpio->cs_gpios[0] = SPI_GPIO_NO_CHIPSELECT; + else + for (i = 0; i < SPI_N_CHIPSEL; i++) { + status = of_get_named_gpio(np, "cs-gpios", i); + if (status < 0) { + dev_err(&pdev->dev, + "invalid cs-gpios property\n"); + goto gpio_free; + } + spi_gpio->cs_gpios[i] = status; + } + } +#endif + + spi_gpio->bitbang.master = master; + spi_gpio->bitbang.chipselect = spi_gpio_chipselect; + + if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { + spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; + spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; + spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; + spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; + } else { + spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; + spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1; + spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2; + spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; + } + spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; + spi_gpio->bitbang.flags = SPI_CS_HIGH; + + status = spi_bitbang_start(&spi_gpio->bitbang); + if (status < 0) { +gpio_free: + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) + gpio_free(SPI_MISO_GPIO); + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) + gpio_free(SPI_MOSI_GPIO); + gpio_free(SPI_SCK_GPIO); + spi_master_put(master); + } + + return status; +} + +static int spi_gpio_remove(struct platform_device *pdev) +{ + struct spi_gpio *spi_gpio; + struct spi_gpio_platform_data *pdata; + + spi_gpio = platform_get_drvdata(pdev); + pdata = dev_get_platdata(&pdev->dev); + + /* stop() unregisters child devices too */ + spi_bitbang_stop(&spi_gpio->bitbang); + + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) + gpio_free(SPI_MISO_GPIO); + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) + gpio_free(SPI_MOSI_GPIO); + gpio_free(SPI_SCK_GPIO); + spi_master_put(spi_gpio->bitbang.master); + + return 0; +} + +MODULE_ALIAS("platform:" DRIVER_NAME); + +static struct platform_driver spi_gpio_driver = { + .driver = { + .name = DRIVER_NAME, + .of_match_table = of_match_ptr(spi_gpio_dt_ids), + }, + .probe = spi_gpio_probe, + .remove = spi_gpio_remove, +}; +module_platform_driver(spi_gpio_driver); + +MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO "); +MODULE_AUTHOR("David Brownell"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/test.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/test.c new file mode 100644 index 000000000000..1a6556027a7d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/test.c @@ -0,0 +1,68 @@ +#include /* Wd're doing kernel work */ +#include /* specifically, a module */ +#include /* Need for the macros */ +#include +#include +#include +#include "ragile.h" + +/* static int32_t addr = 0x000300AB; */ +/* module_param(addr, long, S_IRUGO); */ + +static long witrevalue = 0x54; +module_param(witrevalue, long, S_IRUGO); + +static int readwrite = 0; +module_param(readwrite, int, S_IRUGO); + +static int debug = 0; +module_param(debug, int, S_IRUGO); + +static void testRead(void) +{ + struct file *file = NULL; + mm_segment_t old_fs; + char buf[128]; + + memset(buf, 0, 128); + file = filp_open("/test.txt", O_RDWR | O_APPEND | O_CREAT, 0644); + if (IS_ERR(file)) { + pr_err("error open file\n"); + return ; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_read(file, buf, 128, &file->f_pos); + pr_err("%s", buf); + set_fs(old_fs); + filp_close(file, NULL); + + return (void)0; + + +} + + +static int __init test_init(void) +{ + ragile_setdebug(debug); + testRead(); + + return 0; +} + +static void __exit test_exit(void) +{ + pr_err("finish test_exit ko\n"); + ragile_setdebug(0); +} + +module_init(test_init); +module_exit(test_exit); + + +MODULE_AUTHOR("test "); +MODULE_DESCRIPTION("test"); +MODULE_LICENSE("GPL"); + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm.h new file mode 100644 index 000000000000..a4fc2badf633 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm.h @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2015 Intel Corporation + * + * Authors: + * Leendert van Doorn + * Dave Safford + * Reiner Sailer + * Kylene Hall + * + * Maintained by: + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + */ + +#ifndef __TPM_H__ +#define __TPM_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum tpm_const { + TPM_MINOR = 224, /* officially assigned */ + TPM_BUFSIZE = 4096, + TPM_NUM_DEVICES = 65536, + TPM_RETRY = 50, /* 5 seconds */ +}; + +enum tpm_timeout { + TPM_TIMEOUT = 5, /* msecs */ + TPM_TIMEOUT_RETRY = 100 /* msecs */ +}; + +/* TPM addresses */ +enum tpm_addr { + TPM_SUPERIO_ADDR = 0x2E, + TPM_ADDR = 0x4E, +}; + +/* Indexes the duration array */ +enum tpm_duration { + TPM_SHORT = 0, + TPM_MEDIUM = 1, + TPM_LONG = 2, + TPM_UNDEFINED, +}; + +#define TPM_WARN_RETRY 0x800 +#define TPM_WARN_DOING_SELFTEST 0x802 +#define TPM_ERR_DEACTIVATED 0x6 +#define TPM_ERR_DISABLED 0x7 +#define TPM_ERR_INVALID_POSTINIT 38 + +#define TPM_HEADER_SIZE 10 + +enum tpm2_const { + TPM2_PLATFORM_PCR = 24, + TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), + TPM2_TIMEOUT_A = 750, + TPM2_TIMEOUT_B = 2000, + TPM2_TIMEOUT_C = 200, + TPM2_TIMEOUT_D = 30, + TPM2_DURATION_SHORT = 20, + TPM2_DURATION_MEDIUM = 750, + TPM2_DURATION_LONG = 2000, +}; + +enum tpm2_structures { + TPM2_ST_NO_SESSIONS = 0x8001, + TPM2_ST_SESSIONS = 0x8002, +}; + +enum tpm2_return_codes { + TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ + TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ + TPM2_RC_DISABLED = 0x0120, + TPM2_RC_TESTING = 0x090A, /* RC_WARN */ +}; + +enum tpm2_algorithms { + TPM2_ALG_SHA1 = 0x0004, + TPM2_ALG_KEYEDHASH = 0x0008, + TPM2_ALG_SHA256 = 0x000B, + TPM2_ALG_SHA384 = 0x000C, + TPM2_ALG_SHA512 = 0x000D, + TPM2_ALG_NULL = 0x0010, + TPM2_ALG_SM3_256 = 0x0012, +}; + +enum tpm2_command_codes { + TPM2_CC_FIRST = 0x011F, + TPM2_CC_SELF_TEST = 0x0143, + TPM2_CC_STARTUP = 0x0144, + TPM2_CC_SHUTDOWN = 0x0145, + TPM2_CC_CREATE = 0x0153, + TPM2_CC_LOAD = 0x0157, + TPM2_CC_UNSEAL = 0x015E, + TPM2_CC_FLUSH_CONTEXT = 0x0165, + TPM2_CC_GET_CAPABILITY = 0x017A, + TPM2_CC_GET_RANDOM = 0x017B, + TPM2_CC_PCR_READ = 0x017E, + TPM2_CC_PCR_EXTEND = 0x0182, + TPM2_CC_LAST = 0x018F, +}; + +enum tpm2_permanent_handles { + TPM2_RS_PW = 0x40000009, +}; + +enum tpm2_capabilities { + TPM2_CAP_TPM_PROPERTIES = 6, +}; + +enum tpm2_startup_types { + TPM2_SU_CLEAR = 0x0000, + TPM2_SU_STATE = 0x0001, +}; + +#define TPM_VID_INTEL 0x8086 +#define TPM_VID_WINBOND 0x1050 +#define TPM_VID_STM 0x104A + +#define TPM_PPI_VERSION_LEN 3 + +enum tpm_chip_flags { + TPM_CHIP_FLAG_REGISTERED = BIT(0), + TPM_CHIP_FLAG_TPM2 = BIT(1), + TPM_CHIP_FLAG_IRQ = BIT(2), + TPM_CHIP_FLAG_VIRTUAL = BIT(3), + TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), +}; + +struct tpm_chip { + struct device dev; + struct cdev cdev; + + /* A driver callback under ops cannot be run unless ops_sem is held + * (sometimes implicitly, eg for the sysfs code). ops becomes null + * when the driver is unregistered, see tpm_try_get_ops. + */ + struct rw_semaphore ops_sem; + const struct tpm_class_ops *ops; + + unsigned int flags; + + int dev_num; /* /dev/tpm# */ + unsigned long is_open; /* only one allowed */ + + struct mutex tpm_mutex; /* tpm is processing */ + + unsigned long timeout_a; /* jiffies */ + unsigned long timeout_b; /* jiffies */ + unsigned long timeout_c; /* jiffies */ + unsigned long timeout_d; /* jiffies */ + bool timeout_adjusted; + unsigned long duration[3]; /* jiffies */ + bool duration_adjusted; + + struct dentry **bios_dir; + + const struct attribute_group *groups[3]; + unsigned int groups_cnt; +#ifdef CONFIG_ACPI + acpi_handle acpi_dev_handle; + char ppi_version[TPM_PPI_VERSION_LEN + 1]; +#endif /* CONFIG_ACPI */ +}; + +#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) + +static inline int tpm_read_index(int base, int index) +{ + outb(index, base); + return inb(base+1) & 0xFF; +} + +static inline void tpm_write_index(int base, int index, int value) +{ + outb(index, base); + outb(value & 0xFF, base+1); +} +struct tpm_input_header { + __be16 tag; + __be32 length; + __be32 ordinal; +} __packed; + +struct tpm_output_header { + __be16 tag; + __be32 length; + __be32 return_code; +} __packed; + +#define TPM_TAG_RQU_COMMAND cpu_to_be16(193) + +struct stclear_flags_t { + __be16 tag; + u8 deactivated; + u8 disableForceClear; + u8 physicalPresence; + u8 physicalPresenceLock; + u8 bGlobalLock; +} __packed; + +struct tpm_version_t { + u8 Major; + u8 Minor; + u8 revMajor; + u8 revMinor; +} __packed; + +struct tpm_version_1_2_t { + __be16 tag; + u8 Major; + u8 Minor; + u8 revMajor; + u8 revMinor; +} __packed; + +struct timeout_t { + __be32 a; + __be32 b; + __be32 c; + __be32 d; +} __packed; + +struct duration_t { + __be32 tpm_short; + __be32 tpm_medium; + __be32 tpm_long; +} __packed; + +struct permanent_flags_t { + __be16 tag; + u8 disable; + u8 ownership; + u8 deactivated; + u8 readPubek; + u8 disableOwnerClear; + u8 allowMaintenance; + u8 physicalPresenceLifetimeLock; + u8 physicalPresenceHWEnable; + u8 physicalPresenceCMDEnable; + u8 CEKPUsed; + u8 TPMpost; + u8 TPMpostLock; + u8 FIPS; + u8 operator; + u8 enableRevokeEK; + u8 nvLocked; + u8 readSRKPub; + u8 tpmEstablished; + u8 maintenanceDone; + u8 disableFullDALogicInfo; +} __packed; + +typedef union { + struct permanent_flags_t perm_flags; + struct stclear_flags_t stclear_flags; + bool owned; + __be32 num_pcrs; + struct tpm_version_t tpm_version; + struct tpm_version_1_2_t tpm_version_1_2; + __be32 manufacturer_id; + struct timeout_t timeout; + struct duration_t duration; +} cap_t; + +enum tpm_capabilities { + TPM_CAP_FLAG = cpu_to_be32(4), + TPM_CAP_PROP = cpu_to_be32(5), + CAP_VERSION_1_1 = cpu_to_be32(0x06), + CAP_VERSION_1_2 = cpu_to_be32(0x1A) +}; + +enum tpm_sub_capabilities { + TPM_CAP_PROP_PCR = cpu_to_be32(0x101), + TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103), + TPM_CAP_FLAG_PERM = cpu_to_be32(0x108), + TPM_CAP_FLAG_VOL = cpu_to_be32(0x109), + TPM_CAP_PROP_OWNER = cpu_to_be32(0x111), + TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), + TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), + +}; + +struct tpm_getcap_params_in { + __be32 cap; + __be32 subcap_size; + __be32 subcap; +} __packed; + +struct tpm_getcap_params_out { + __be32 cap_size; + cap_t cap; +} __packed; + +struct tpm_readpubek_params_out { + u8 algorithm[4]; + u8 encscheme[2]; + u8 sigscheme[2]; + __be32 paramsize; + u8 parameters[12]; /*assuming RSA*/ + __be32 keysize; + u8 modulus[256]; + u8 checksum[20]; +} __packed; + +typedef union { + struct tpm_input_header in; + struct tpm_output_header out; +} tpm_cmd_header; + +struct tpm_pcrread_out { + u8 pcr_result[TPM_DIGEST_SIZE]; +} __packed; + +struct tpm_pcrread_in { + __be32 pcr_idx; +} __packed; + +struct tpm_pcrextend_in { + __be32 pcr_idx; + u8 hash[TPM_DIGEST_SIZE]; +} __packed; + +/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 + * bytes, but 128 is still a relatively large number of random bytes and + * anything much bigger causes users of struct tpm_cmd_t to start getting + * compiler warnings about stack frame size. */ +#define TPM_MAX_RNG_DATA 128 + +struct tpm_getrandom_out { + __be32 rng_data_len; + u8 rng_data[TPM_MAX_RNG_DATA]; +} __packed; + +struct tpm_getrandom_in { + __be32 num_bytes; +} __packed; + +struct tpm_startup_in { + __be16 startup_type; +} __packed; + +typedef union { + struct tpm_getcap_params_out getcap_out; + struct tpm_readpubek_params_out readpubek_out; + u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; + struct tpm_getcap_params_in getcap_in; + struct tpm_pcrread_in pcrread_in; + struct tpm_pcrread_out pcrread_out; + struct tpm_pcrextend_in pcrextend_in; + struct tpm_getrandom_in getrandom_in; + struct tpm_getrandom_out getrandom_out; + struct tpm_startup_in startup_in; +} tpm_cmd_params; + +struct tpm_cmd_t { + tpm_cmd_header header; + tpm_cmd_params params; +} __packed; + +/* A string buffer type for constructing TPM commands. This is based on the + * ideas of string buffer code in security/keys/trusted.h but is heap based + * in order to keep the stack usage minimal. + */ + +enum tpm_buf_flags { + TPM_BUF_OVERFLOW = BIT(0), +}; + +struct tpm_buf { + struct page *data_page; + unsigned int flags; + u8 *data; +}; + +static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +{ + struct tpm_input_header *head; + + buf->data_page = alloc_page(GFP_HIGHUSER); + if (!buf->data_page) + return -ENOMEM; + + buf->flags = 0; + buf->data = kmap(buf->data_page); + + head = (struct tpm_input_header *) buf->data; + + head->tag = cpu_to_be16(tag); + head->length = cpu_to_be32(sizeof(*head)); + head->ordinal = cpu_to_be32(ordinal); + + return 0; +} + +static inline void tpm_buf_destroy(struct tpm_buf *buf) +{ + kunmap(buf->data_page); + __free_page(buf->data_page); +} + +static inline u32 tpm_buf_length(struct tpm_buf *buf) +{ + struct tpm_input_header *head = (struct tpm_input_header *) buf->data; + + return be32_to_cpu(head->length); +} + +static inline u16 tpm_buf_tag(struct tpm_buf *buf) +{ + struct tpm_input_header *head = (struct tpm_input_header *) buf->data; + + return be16_to_cpu(head->tag); +} + +static inline void tpm_buf_append(struct tpm_buf *buf, + const unsigned char *new_data, + unsigned int new_len) +{ + struct tpm_input_header *head = (struct tpm_input_header *) buf->data; + u32 len = tpm_buf_length(buf); + + /* Return silently if overflow has already happened. */ + if (buf->flags & TPM_BUF_OVERFLOW) + return; + + if ((len + new_len) > PAGE_SIZE) { + WARN(1, "tpm_buf: overflow\n"); + buf->flags |= TPM_BUF_OVERFLOW; + return; + } + + memcpy(&buf->data[len], new_data, new_len); + head->length = cpu_to_be32(len + new_len); +} + +static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value) +{ + tpm_buf_append(buf, &value, 1); +} + +static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value) +{ + __be16 value2 = cpu_to_be16(value); + + tpm_buf_append(buf, (u8 *) &value2, 2); +} + +static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) +{ + __be32 value2 = cpu_to_be32(value); + + tpm_buf_append(buf, (u8 *) &value2, 4); +} + +extern struct class *tpm_class; +extern dev_t tpm_devt; +extern const struct file_operations tpm_fops; +extern struct idr dev_nums_idr; + +enum tpm_transmit_flags { + TPM_TRANSMIT_UNLOCKED = BIT(0), +}; + +ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, + unsigned int flags); +ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len, + unsigned int flags, const char *desc); +ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap, + const char *desc); +int tpm_get_timeouts(struct tpm_chip *); +int tpm1_auto_startup(struct tpm_chip *chip); +int tpm_do_selftest(struct tpm_chip *chip); +unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); +int tpm_pm_suspend(struct device *dev); +int tpm_pm_resume(struct device *dev); +int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, + wait_queue_head_t *queue, bool check_cancel); + +struct tpm_chip *tpm_chip_find_get(int chip_num); +__must_check int tpm_try_get_ops(struct tpm_chip *chip); +void tpm_put_ops(struct tpm_chip *chip); + +struct tpm_chip *tpm_chip_alloc(struct device *dev, + const struct tpm_class_ops *ops); +struct tpm_chip *tpmm_chip_alloc(struct device *pdev, + const struct tpm_class_ops *ops); +int tpm_chip_register(struct tpm_chip *chip); +void tpm_chip_unregister(struct tpm_chip *chip); + +void tpm_sysfs_add_device(struct tpm_chip *chip); + +int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); + +#ifdef CONFIG_ACPI +extern void tpm_add_ppi(struct tpm_chip *chip); +#else +static inline void tpm_add_ppi(struct tpm_chip *chip) +{ +} +#endif + +static inline inline u32 tpm2_rc_value(u32 rc) +{ + return (rc & BIT(7)) ? rc & 0xff : rc; +} + +int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); +int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash); +int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); +int tpm2_seal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options); +int tpm2_unseal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options); +ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, + u32 *value, const char *desc); + +int tpm2_auto_startup(struct tpm_chip *chip); +void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); +unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); +int tpm2_probe(struct tpm_chip *chip); +#endif diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.c new file mode 100644 index 000000000000..f9aa47ec7af7 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.c @@ -0,0 +1,855 @@ +/* + * Copyright (C) 2005, 2006 IBM Corporation + * Copyright (C) 2014, 2015 Intel Corporation + * + * Authors: + * Leendert van Doorn + * Kylene Hall + * + * Maintained by: + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG TPM Interface Spec version 1.2, revision 1.0. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tpm.h" +#include "tpm_tis_core.h" + +/* Before we attempt to access the TPM we must see that the valid bit is set. + * The specification says that this bit is 0 at reset and remains 0 until the + * 'TPM has gone through its self test and initialization and has established + * correct values in the other bits.' + */ +static int wait_startup(struct tpm_chip *chip, int l) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + unsigned long stop = jiffies + chip->timeout_a; + + do { + int rc; + u8 access; + + rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); + if (rc < 0) + return rc; + + if (access & TPM_ACCESS_VALID) + return 0; + msleep(TPM_TIMEOUT); + } while (time_before(jiffies, stop)); + return -1; +} + +static int check_locality(struct tpm_chip *chip, int l) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc; + u8 access; + + rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); + if (rc < 0) + return rc; + + if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == + (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) + return priv->locality = l; + + return -1; +} + +static void release_locality(struct tpm_chip *chip, int l, int force) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc; + u8 access; + + rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); + if (rc < 0) + return; + + if (force || (access & + (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == + (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) + tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); + +} + +static int request_locality(struct tpm_chip *chip, int l) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + unsigned long stop, timeout; + long rc; + + if (check_locality(chip, l) >= 0) + return l; + + rc = tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE); + if (rc < 0) + return rc; + + stop = jiffies + chip->timeout_a; + + if (chip->flags & TPM_CHIP_FLAG_IRQ) { +again: + timeout = stop - jiffies; + if ((long)timeout <= 0) + return -1; + rc = wait_event_interruptible_timeout(priv->int_queue, + (check_locality + (chip, l) >= 0), + timeout); + if (rc > 0) + return l; + if (rc == -ERESTARTSYS && freezing(current)) { + clear_thread_flag(TIF_SIGPENDING); + goto again; + } + } else { + /* wait for burstcount */ + do { + if (check_locality(chip, l) >= 0) + return l; + msleep(TPM_TIMEOUT); + } while (time_before(jiffies, stop)); + } + return -1; +} + +static u8 tpm_tis_status(struct tpm_chip *chip) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc; + u8 status; + + rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status); + if (rc < 0) + return 0; + + return status; +} + +static void tpm_tis_ready(struct tpm_chip *chip) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + + /* this causes the current command to be aborted */ + tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_COMMAND_READY); +} + +static int get_burstcount(struct tpm_chip *chip) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + unsigned long stop; + int burstcnt, rc; + u32 value; + + /* wait for burstcount */ + if (chip->flags & TPM_CHIP_FLAG_TPM2) + stop = jiffies + chip->timeout_a; + else + stop = jiffies + chip->timeout_d; + do { + rc = tpm_tis_read32(priv, TPM_STS(priv->locality), &value); + if (rc < 0) + return rc; + + burstcnt = (value >> 8) & 0xFFFF; + if (burstcnt) + return burstcnt; + msleep(TPM_TIMEOUT); + } while (time_before(jiffies, stop)); + return -EBUSY; +} + +static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int size = 0, burstcnt, rc; + + while (size < count && + wait_for_tpm_stat(chip, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + chip->timeout_c, + &priv->read_queue, true) == 0) { + burstcnt = get_burstcount(chip); + if (burstcnt < 0) { + dev_err(&chip->dev, "Unable to read burstcount\n"); + return burstcnt; + } + burstcnt = min_t(int, burstcnt, count - size); + + rc = tpm_tis_read_bytes(priv, TPM_DATA_FIFO(priv->locality), + burstcnt, buf + size); + if (rc < 0) + return rc; + + size += burstcnt; + } + return size; +} + +static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int size = 0; + int status; + u32 expected; + + if (count < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } + + size = recv_data(chip, buf, TPM_HEADER_SIZE); + /* read first 10 bytes, including tag, paramsize, and result */ + if (size < TPM_HEADER_SIZE) { + dev_err(&chip->dev, "Unable to read header\n"); + goto out; + } + + expected = be32_to_cpu(*(__be32 *) (buf + 2)); + if (expected > count || expected < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } + + size += recv_data(chip, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); + if (size < expected) { + dev_err(&chip->dev, "Unable to read remainder of result\n"); + size = -ETIME; + goto out; + } + + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, + &priv->int_queue, false); + status = tpm_tis_status(chip); + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ + dev_err(&chip->dev, "Error left over data\n"); + size = -EIO; + goto out; + } + +out: + tpm_tis_ready(chip); + release_locality(chip, priv->locality, 0); + return size; +} + +/* + * If interrupts are used (signaled by an irq set in the vendor structure) + * tpm.c can skip polling for the data to be available as the interrupt is + * waited for here + */ +static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc, status, burstcnt; + size_t count = 0; + bool itpm = priv->flags & TPM_TIS_ITPM_POSSIBLE; + + if (request_locality(chip, 0) < 0) + return -EBUSY; + + status = tpm_tis_status(chip); + if ((status & TPM_STS_COMMAND_READY) == 0) { + tpm_tis_ready(chip); + if (wait_for_tpm_stat + (chip, TPM_STS_COMMAND_READY, chip->timeout_b, + &priv->int_queue, false) < 0) { + rc = -ETIME; + goto out_err; + } + } + + while (count < len - 1) { + burstcnt = get_burstcount(chip); + if (burstcnt < 0) { + dev_err(&chip->dev, "Unable to read burstcount\n"); + rc = burstcnt; + goto out_err; + } + burstcnt = min_t(int, burstcnt, len - count - 1); + rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality), + burstcnt, buf + count); + if (rc < 0) + goto out_err; + + count += burstcnt; + + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, + &priv->int_queue, false); + status = tpm_tis_status(chip); + if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { + rc = -EIO; + goto out_err; + } + } + + /* write last byte */ + rc = tpm_tis_write8(priv, TPM_DATA_FIFO(priv->locality), buf[count]); + if (rc < 0) + goto out_err; + + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, + &priv->int_queue, false); + status = tpm_tis_status(chip); + if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) { + rc = -EIO; + goto out_err; + } + + return 0; + +out_err: + tpm_tis_ready(chip); + release_locality(chip, priv->locality, 0); + return rc; +} + +static void disable_interrupts(struct tpm_chip *chip) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + u32 intmask; + int rc; + + rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); + if (rc < 0) + intmask = 0; + + intmask &= ~TPM_GLOBAL_INT_ENABLE; + rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); + + devm_free_irq(chip->dev.parent, priv->irq, chip); + priv->irq = 0; + chip->flags &= ~TPM_CHIP_FLAG_IRQ; +} + +/* + * If interrupts are used (signaled by an irq set in the vendor structure) + * tpm.c can skip polling for the data to be available as the interrupt is + * waited for here + */ +static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc; + u32 ordinal; + unsigned long dur; + + rc = tpm_tis_send_data(chip, buf, len); + if (rc < 0) + return rc; + + /* go and do it */ + rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); + if (rc < 0) + goto out_err; + + if (chip->flags & TPM_CHIP_FLAG_IRQ) { + ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + dur = tpm2_calc_ordinal_duration(chip, ordinal); + else + dur = tpm_calc_ordinal_duration(chip, ordinal); + + if (wait_for_tpm_stat + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, + &priv->read_queue, false) < 0) { + rc = -ETIME; + goto out_err; + } + } + return len; +out_err: + tpm_tis_ready(chip); + release_locality(chip, priv->locality, 0); + return rc; +} + +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) +{ + int rc, irq; + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + + if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested) + return tpm_tis_send_main(chip, buf, len); + + /* Verify receipt of the expected IRQ */ + irq = priv->irq; + priv->irq = 0; + chip->flags &= ~TPM_CHIP_FLAG_IRQ; + rc = tpm_tis_send_main(chip, buf, len); + priv->irq = irq; + chip->flags |= TPM_CHIP_FLAG_IRQ; + if (!priv->irq_tested) + msleep(1); + if (!priv->irq_tested) + disable_interrupts(chip); + priv->irq_tested = true; + return rc; +} + +struct tis_vendor_timeout_override { + u32 did_vid; + unsigned long timeout_us[4]; +}; + +static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = { + /* Atmel 3204 */ + { 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000), + (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, +}; + +static bool tpm_tis_update_timeouts(struct tpm_chip *chip, + unsigned long *timeout_cap) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int i, rc; + u32 did_vid; + + rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); + if (rc < 0) + return rc; + + for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { + if (vendor_timeout_overrides[i].did_vid != did_vid) + continue; + memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, + sizeof(vendor_timeout_overrides[i].timeout_us)); + return true; + } + + return false; +} + +/* + * Early probing for iTPM with STS_DATA_EXPECT flaw. + * Try sending command without itpm flag set and if that + * fails, repeat with itpm flag set. + */ +static int probe_itpm(struct tpm_chip *chip) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc = 0; + u8 cmd_getticks[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0xf1 + }; + size_t len = sizeof(cmd_getticks); + u16 vendor; + + rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor); + if (rc < 0) + return rc; + + /* probe only iTPMS */ + if (vendor != TPM_VID_INTEL) + return 0; + + rc = tpm_tis_send_data(chip, cmd_getticks, len); + if (rc == 0) + goto out; + + tpm_tis_ready(chip); + release_locality(chip, priv->locality, 0); + + rc = tpm_tis_send_data(chip, cmd_getticks, len); + if (rc == 0) { + dev_info(&chip->dev, "Detected an iTPM.\n"); + rc = 1; + } else + rc = -EFAULT; + +out: + tpm_tis_ready(chip); + release_locality(chip, priv->locality, 0); + + return rc; +} + +static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + + switch (priv->manufacturer_id) { + case TPM_VID_WINBOND: + return ((status == TPM_STS_VALID) || + (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); + case TPM_VID_STM: + return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); + default: + return (status == TPM_STS_COMMAND_READY); + } +} + +static irqreturn_t tis_int_handler(int dummy, void *dev_id) +{ + struct tpm_chip *chip = dev_id; + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + u32 interrupt; + int i, rc; + + rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); + if (rc < 0) + return IRQ_NONE; + + if (interrupt == 0) + return IRQ_NONE; + + priv->irq_tested = true; + if (interrupt & TPM_INTF_DATA_AVAIL_INT) + wake_up_interruptible(&priv->read_queue); + if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) + for (i = 0; i < 5; i++) + if (check_locality(chip, i) >= 0) + break; + if (interrupt & + (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | + TPM_INTF_CMD_READY_INT)) + wake_up_interruptible(&priv->int_queue); + + /* Clear interrupts handled with TPM_EOI */ + rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt); + if (rc < 0) + return IRQ_NONE; + + tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); + return IRQ_HANDLED; +} + +static int tpm_tis_gen_interrupt(struct tpm_chip *chip) +{ + const char *desc = "attempting to generate an interrupt"; + u32 cap2; + cap_t cap; + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); + else + return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc); +} + +/* Register the IRQ and issue a command that will cause an interrupt. If an + * irq is seen then leave the chip setup for IRQ operation, otherwise reverse + * everything and leave in polling mode. Returns 0 on success. + */ +static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask, + int flags, int irq) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + u8 original_int_vec; + int rc; + u32 int_status; + + if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags, + dev_name(&chip->dev), chip) != 0) { + dev_info(&chip->dev, "Unable to request irq: %d for probe\n", + irq); + return -1; + } + priv->irq = irq; + + rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), + &original_int_vec); + if (rc < 0) + return rc; + + rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq); + if (rc < 0) + return rc; + + rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status); + if (rc < 0) + return rc; + + /* Clear all existing */ + rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status); + if (rc < 0) + return rc; + + /* Turn on */ + rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), + intmask | TPM_GLOBAL_INT_ENABLE); + if (rc < 0) + return rc; + + priv->irq_tested = false; + + /* Generate an interrupt by having the core call through to + * tpm_tis_send + */ + rc = tpm_tis_gen_interrupt(chip); + if (rc < 0) + return rc; + + /* tpm_tis_send will either confirm the interrupt is working or it + * will call disable_irq which undoes all of the above. + */ + if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { + rc = tpm_tis_write8(priv, original_int_vec, + TPM_INT_VECTOR(priv->locality)); + if (rc < 0) + return rc; + + return 1; + } + + return 0; +} + +/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that + * do not have ACPI/etc. We typically expect the interrupt to be declared if + * present. + */ +static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + u8 original_int_vec; + int i, rc; + + rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), + &original_int_vec); + if (rc < 0) + return; + + if (!original_int_vec) { + if (IS_ENABLED(CONFIG_X86)) + for (i = 3; i <= 15; i++) + if (!tpm_tis_probe_irq_single(chip, intmask, 0, + i)) + return; + } else if (!tpm_tis_probe_irq_single(chip, intmask, 0, + original_int_vec)) + return; +} + +void tpm_tis_remove(struct tpm_chip *chip) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + u32 reg = TPM_INT_ENABLE(priv->locality); + u32 interrupt; + int rc; + + rc = tpm_tis_read32(priv, reg, &interrupt); + if (rc < 0) + interrupt = 0; + + tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); + release_locality(chip, priv->locality, 1); +} +EXPORT_SYMBOL_GPL(tpm_tis_remove); + +static const struct tpm_class_ops tpm_tis = { + .flags = TPM_OPS_AUTO_STARTUP, + .status = tpm_tis_status, + .recv = tpm_tis_recv, + .send = tpm_tis_send, + .cancel = tpm_tis_ready, + .update_timeouts = tpm_tis_update_timeouts, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_canceled = tpm_tis_req_canceled, +}; + +int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, + const struct tpm_tis_phy_ops *phy_ops, + acpi_handle acpi_dev_handle) +{ + u32 vendor, intfcaps, intmask; + u8 rid; + int rc, probe; + struct tpm_chip *chip; + + chip = tpmm_chip_alloc(dev, &tpm_tis); + if (IS_ERR(chip)) + return PTR_ERR(chip); + +#ifdef CONFIG_ACPI + chip->acpi_dev_handle = acpi_dev_handle; +#endif + + /* Maximum timeouts */ + chip->timeout_a = msecs_to_jiffies(TIS_TIMEOUT_A_MAX); + chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); + chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX); + chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX); + priv->phy_ops = phy_ops; + dev_set_drvdata(&chip->dev, priv); + + if (wait_startup(chip, 0) != 0) { + rc = -ENODEV; + goto out_err; + } + + /* Take control of the TPM's interrupt hardware and shut it off */ + rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); + if (rc < 0) + goto out_err; + + intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | + TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; + intmask &= ~TPM_GLOBAL_INT_ENABLE; + tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); + + if (request_locality(chip, 0) != 0) { + rc = -ENODEV; + goto out_err; + } + + rc = tpm2_probe(chip); + if (rc) + goto out_err; + + rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); + if (rc < 0) + goto out_err; + + priv->manufacturer_id = vendor; + + rc = tpm_tis_read8(priv, TPM_RID(0), &rid); + if (rc < 0) + goto out_err; + + dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", + vendor >> 16, rid); + + if (!(priv->flags & TPM_TIS_ITPM_POSSIBLE)) { + probe = probe_itpm(chip); + if (probe < 0) { + rc = -ENODEV; + goto out_err; + } + + if (!!probe) + priv->flags |= TPM_TIS_ITPM_POSSIBLE; + } + + /* Figure out the capabilities */ + rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps); + if (rc < 0) + goto out_err; + + dev_dbg(dev, "TPM interface capabilities (0x%x):\n", + intfcaps); + if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) + dev_dbg(dev, "\tBurst Count Static\n"); + if (intfcaps & TPM_INTF_CMD_READY_INT) + dev_dbg(dev, "\tCommand Ready Int Support\n"); + if (intfcaps & TPM_INTF_INT_EDGE_FALLING) + dev_dbg(dev, "\tInterrupt Edge Falling\n"); + if (intfcaps & TPM_INTF_INT_EDGE_RISING) + dev_dbg(dev, "\tInterrupt Edge Rising\n"); + if (intfcaps & TPM_INTF_INT_LEVEL_LOW) + dev_dbg(dev, "\tInterrupt Level Low\n"); + if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) + dev_dbg(dev, "\tInterrupt Level High\n"); + if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) + dev_dbg(dev, "\tLocality Change Int Support\n"); + if (intfcaps & TPM_INTF_STS_VALID_INT) + dev_dbg(dev, "\tSts Valid Int Support\n"); + if (intfcaps & TPM_INTF_DATA_AVAIL_INT) + dev_dbg(dev, "\tData Avail Int Support\n"); + + /* Very early on issue a command to the TPM in polling mode to make + * sure it works. May as well use that command to set the proper + * timeouts for the driver. + */ + if (tpm_get_timeouts(chip)) { + dev_err(dev, "Could not get TPM timeouts and durations\n"); + rc = -ENODEV; + goto out_err; + } + + /* INTERRUPT Setup */ + init_waitqueue_head(&priv->read_queue); + init_waitqueue_head(&priv->int_queue); + if (irq != -1) { + if (irq) { + tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, + irq); + if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) + dev_err(&chip->dev, FW_BUG + "TPM interrupt not working, polling instead\n"); + } else { + tpm_tis_probe_irq(chip, intmask); + } + } + + return tpm_chip_register(chip); +out_err: + tpm_tis_remove(chip); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_tis_core_init); + +#ifdef CONFIG_PM_SLEEP +static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + u32 intmask; + int rc; + + /* reenable interrupts that device may have lost or + * BIOS/firmware may have disabled + */ + rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq); + if (rc < 0) + return; + + rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); + if (rc < 0) + return; + + intmask |= TPM_INTF_CMD_READY_INT + | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT + | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE; + + tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); +} + +int tpm_tis_resume(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + int ret; + + if (chip->flags & TPM_CHIP_FLAG_IRQ) + tpm_tis_reenable_interrupts(chip); + + ret = tpm_pm_resume(dev); + if (ret) + return ret; + + /* TPM 1.2 requires self-test on resume. This function actually returns + * an error code but for unknown reason it isn't handled. + */ + if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) + tpm_do_selftest(chip); + + return 0; +} +EXPORT_SYMBOL_GPL(tpm_tis_resume); +#endif + +MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); +MODULE_DESCRIPTION("TPM Driver"); +MODULE_VERSION("2.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.h b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.h new file mode 100644 index 000000000000..e1c2193f2ed3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_core.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2005, 2006 IBM Corporation + * Copyright (C) 2014, 2015 Intel Corporation + * + * Authors: + * Leendert van Doorn + * Kylene Hall + * + * Maintained by: + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG TPM Interface Spec version 1.2, revision 1.0. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ + +#ifndef __TPM_TIS_CORE_H__ +#define __TPM_TIS_CORE_H__ + +#include "tpm.h" + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum tis_status { + TPM_STS_VALID = 0x80, + TPM_STS_COMMAND_READY = 0x40, + TPM_STS_GO = 0x20, + TPM_STS_DATA_AVAIL = 0x10, + TPM_STS_DATA_EXPECT = 0x08, +}; + +enum tis_int_flags { + TPM_GLOBAL_INT_ENABLE = 0x80000000, + TPM_INTF_BURST_COUNT_STATIC = 0x100, + TPM_INTF_CMD_READY_INT = 0x080, + TPM_INTF_INT_EDGE_FALLING = 0x040, + TPM_INTF_INT_EDGE_RISING = 0x020, + TPM_INTF_INT_LEVEL_LOW = 0x010, + TPM_INTF_INT_LEVEL_HIGH = 0x008, + TPM_INTF_LOCALITY_CHANGE_INT = 0x004, + TPM_INTF_STS_VALID_INT = 0x002, + TPM_INTF_DATA_AVAIL_INT = 0x001, +}; + +enum tis_defaults { + TIS_MEM_LEN = 0x5000, + TIS_SHORT_TIMEOUT = 750, /* ms */ + TIS_LONG_TIMEOUT = 2000, /* 2 sec */ +}; + +/* Some timeout values are needed before it is known whether the chip is + * TPM 1.0 or TPM 2.0. + */ +#define TIS_TIMEOUT_A_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) +#define TIS_TIMEOUT_B_MAX max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) +#define TIS_TIMEOUT_C_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) +#define TIS_TIMEOUT_D_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D) + +#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) +#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) +#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) +#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) +#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) +#define TPM_STS(l) (0x0018 | ((l) << 12)) +#define TPM_STS3(l) (0x001b | ((l) << 12)) +#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) + +#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) +#define TPM_RID(l) (0x0F04 | ((l) << 12)) + +enum tpm_tis_flags { + TPM_TIS_ITPM_POSSIBLE = BIT(0), +}; + +struct tpm_tis_data { + u16 manufacturer_id; + int locality; + int irq; + bool irq_tested; + unsigned int flags; + wait_queue_head_t int_queue; + wait_queue_head_t read_queue; + const struct tpm_tis_phy_ops *phy_ops; +}; + +struct tpm_tis_phy_ops { + int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *result); + int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, + const u8 *value); + int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); + int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); + int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); +}; + +static inline int tpm_tis_read_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, u8 *result) +{ + return data->phy_ops->read_bytes(data, addr, len, result); +} + +static inline int tpm_tis_read8(struct tpm_tis_data *data, u32 addr, u8 *result) +{ + return data->phy_ops->read_bytes(data, addr, 1, result); +} + +static inline int tpm_tis_read16(struct tpm_tis_data *data, u32 addr, + u16 *result) +{ + return data->phy_ops->read16(data, addr, result); +} + +static inline int tpm_tis_read32(struct tpm_tis_data *data, u32 addr, + u32 *result) +{ + return data->phy_ops->read32(data, addr, result); +} + +static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, const u8 *value) +{ + return data->phy_ops->write_bytes(data, addr, len, value); +} + +static inline int tpm_tis_write8(struct tpm_tis_data *data, u32 addr, u8 value) +{ + return data->phy_ops->write_bytes(data, addr, 1, &value); +} + +static inline int tpm_tis_write32(struct tpm_tis_data *data, u32 addr, + u32 value) +{ + return data->phy_ops->write32(data, addr, value); +} + +void tpm_tis_remove(struct tpm_chip *chip); +int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, + const struct tpm_tis_phy_ops *phy_ops, + acpi_handle acpi_dev_handle); + +#ifdef CONFIG_PM_SLEEP +int tpm_tis_resume(struct device *dev); +#endif + +#endif diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_spi.c b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_spi.c new file mode 100644 index 000000000000..950c2d28d81d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/modules/tpm_tis_spi.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2015 Infineon Technologies AG + * Copyright (C) 2016 STMicroelectronics SAS + * + * Authors: + * Peter Huewe + * Christophe Ricard + * + * Maintained by: + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native + * SPI access_. + * + * It is based on the original tpm_tis device driver from Leendert van + * Dorn and Kyleen Hall and Jarko Sakkinnen. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "tpm.h" +#include "tpm_tis_core.h" + +#define MAX_SPI_FRAMESIZE 64 + +struct tpm_tis_spi_phy { + struct tpm_tis_data priv; + struct spi_device *spi_device; + u8 *iobuf; +}; + +static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) +{ + return container_of(data, struct tpm_tis_spi_phy, priv); +} + +static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *in, const u8 *out) +{ + struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); + int ret = 0; + int i; + struct spi_message m; + struct spi_transfer spi_xfer; + u8 transfer_len; + + spi_bus_lock(phy->spi_device->master); + + while (len) { + transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); + + phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1); + phy->iobuf[1] = 0xd4; + phy->iobuf[2] = addr >> 8; + phy->iobuf[3] = addr; + + memset(&spi_xfer, 0, sizeof(spi_xfer)); + spi_xfer.tx_buf = phy->iobuf; + spi_xfer.rx_buf = phy->iobuf; + spi_xfer.len = 4; + spi_xfer.cs_change = 1; + + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + + if ((phy->iobuf[3] & 0x01) == 0) { + // handle SPI wait states + phy->iobuf[0] = 0; + + for (i = 0; i < TPM_RETRY; i++) { + spi_xfer.len = 1; + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + if (phy->iobuf[0] & 0x01) + break; + } + + if (i == TPM_RETRY) { + ret = -ETIMEDOUT; + goto exit; + } + } + + spi_xfer.cs_change = 0; + spi_xfer.len = transfer_len; + spi_xfer.delay_usecs = 5; + + if (in) { + spi_xfer.tx_buf = NULL; + } else if (out) { + spi_xfer.rx_buf = NULL; + memcpy(phy->iobuf, out, transfer_len); + out += transfer_len; + } + + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + + if (in) { + memcpy(in, phy->iobuf, transfer_len); + in += transfer_len; + } + + len -= transfer_len; + } + +exit: + spi_bus_unlock(phy->spi_device->master); + return ret; +} + +static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, u8 *result) +{ + return tpm_tis_spi_transfer(data, addr, len, result, NULL); +} + +static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, const u8 *value) +{ + return tpm_tis_spi_transfer(data, addr, len, NULL, value); +} + +static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) +{ + int rc; + + rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), (u8 *)result); + if (!rc) + *result = le16_to_cpu(*result); + return rc; +} + +static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) +{ + int rc; + + rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), (u8 *)result); + if (!rc) + *result = le32_to_cpu(*result); + return rc; +} + +static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) +{ + value = cpu_to_le32(value); + return data->phy_ops->write_bytes(data, addr, sizeof(u32), + (u8 *)&value); +} + +static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { + .read_bytes = tpm_tis_spi_read_bytes, + .write_bytes = tpm_tis_spi_write_bytes, + .read16 = tpm_tis_spi_read16, + .read32 = tpm_tis_spi_read32, + .write32 = tpm_tis_spi_write32, +}; + +static int tpm_tis_spi_probe(struct spi_device *dev) +{ + struct tpm_tis_spi_phy *phy; + int irq; + + phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy), + GFP_KERNEL); + if (!phy) + return -ENOMEM; + + phy->spi_device = dev; + + phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); + if (!phy->iobuf) + return -ENOMEM; + + /* If the SPI device has an IRQ then use that */ + if (dev->irq > 0) + irq = dev->irq; + else + irq = -1; + + return tpm_tis_core_init(&dev->dev, &phy->priv, irq, &tpm_spi_phy_ops, + NULL); +} + +static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); + +static int tpm_tis_spi_remove(struct spi_device *dev) +{ + struct tpm_chip *chip = spi_get_drvdata(dev); + + tpm_chip_unregister(chip); + tpm_tis_remove(chip); + return 0; +} + +static const struct spi_device_id tpm_tis_spi_id[] = { + {"tpm_tis_spi", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id); + +static const struct of_device_id of_tis_spi_match[] = { + { .compatible = "st,st33htpm-spi", }, + { .compatible = "infineon,slb9670", }, + { .compatible = "tcg,tpm_tis-spi", }, + {} +}; +MODULE_DEVICE_TABLE(of, of_tis_spi_match); + +static const struct acpi_device_id acpi_tis_spi_match[] = { + {"SMO0768", 0}, + {} +}; +MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match); + +static struct spi_driver tpm_tis_spi_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "tpm_tis_spi", + .pm = &tpm_tis_pm, + .of_match_table = of_match_ptr(of_tis_spi_match), + .acpi_match_table = ACPI_PTR(acpi_tis_spi_match), + }, + .probe = tpm_tis_spi_probe, + .remove = tpm_tis_spi_remove, + .id_table = tpm_tis_spi_id, +}; +module_spi_driver(tpm_tis_spi_driver); + +MODULE_DESCRIPTION("TPM Driver for native SPI access"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/avscontrol.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/avscontrol.py new file mode 100644 index 000000000000..bdd2dc718e71 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/avscontrol.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import sys +import click +import os +import subprocess +import time +from ragileutil import * +import syslog +from monitor import status +import traceback +try: + from rest.rest import BMCMessage +except: + pass + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def avswarninglog(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_WARNING,s) + +def avscriticallog(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_CRIT,s) + +def avserror(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR,s) + +def avsinfo(s): + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_INFO,s) + +def doAvsCtrol(): + index = 0 + url = "/xyz/openbmc_project/hostchannel/attr/MacRov" + while True: + if STARTMODULE.__contains__("avscontrol_restful") and STARTMODULE['avscontrol_restful'] == 1: + try: + # for alibmc rest.py has define get_macrov_value function + macrov_value = -1 + get_macrov_value = getattr(BMCMessage(), "get_macrov_value", None) + if callable(get_macrov_value): + macrov_value = int(get_macrov_value()) + else: + macrov_value = int(BMCMessage().getBmcValue(url)) + if macrov_value >= 0: + break + except Exception as e: + time.sleep(2) + continue + else: + if AVSUTIL.mac_adj(): + break + + index += 1 + if index >= 10: + avserror("%%DEV_MONITOR-AVS: MAC Voltage adjust failed.") + exit(-1) + avsinfo("%%AVSCONTROL success") + exit(0) + +def run(interval): + while True: + try: + if waitForDocker(timeout = 0) == True: + time.sleep(10) # docker get up and wait 10 seconds + doAvsCtrol() + time.sleep(interval) + except Exception as e: + traceback.print_exc() + print(e) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + '''start AVS control''' + avsinfo("%%AVSCONTROL start") + interval = 5 + run(interval) + +# device_i2c operation +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/cmdx.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/cmdx.py new file mode 100644 index 000000000000..aa87f67f6004 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/cmdx.py @@ -0,0 +1,51 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +import os +import sys +import click +import subprocess + + +def io_rd(reg_addr, length =1): + '''io read''' + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str1 = os.read(fd, length) + return "".join(["%02x"% ord(item) for item in str1]) + except ValueError: + return None + except Exception as e: + print (e) + return None + finally: + os.close(fd) + return None + +@click.group() +def cli(): + pass + +@cli.command() +@click.argument('addr', required=True) +@click.argument('length', required=True,type = int) +def reg_read(addr,length): + try: + value = io_rd(addr,length) + if value == None: + print ("read failed") + else: + print (value) + except Exception as e: + print (e) + return None + +if __name__ == '__main__': + cli() + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/dev_monitor.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/dev_monitor.py new file mode 100644 index 000000000000..e86bebf2d764 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/dev_monitor.py @@ -0,0 +1,293 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import sys +import click +import os +import subprocess +import time +from ragileutil import * +import syslog +import traceback +import json + + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def devwarninglog(s): + # s = s.decode('utf-8').encode('gb2312') + syslog.openlog("DEVMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_WARNING,s) + +def devcriticallog(s): + # s = s.decode('utf-8').encode('gb2312') + syslog.openlog("DEVMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_CRIT,s) + +def deverror(s): + # s = s.decode('utf-8').encode('gb2312') + syslog.openlog("DEVMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR,s) + +def devdebuglog(s): + # s = s.decode('utf-8').encode('gb2312') + if DEVMONITORDEBUG == 1: + syslog.openlog("DEVMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG,s) + + +class DevMonitor(): + + def getpresentstatus(self,param): + '''Obtain the status of the device. PRESENT is returned ABSENT. ABSENT Returns NOT OK''' + try: + ret = {} + ret["status"] = '' + totalerr = 0 + gettype = param.get('gettype') + presentbit = param.get('presentbit') + okval = param.get('okval') + if gettype == "io": + io_addr = param.get('io_addr') + val = io_rd(io_addr) + if val is not None: + retval = val + else: + totalerr -= 1 + else: + bus = param.get('bus') + loc = param.get('loc') + offset = param.get('offset') + ind, val = rji2cget(bus, loc,offset) + if ind == True: + retval = val + else: + totalerr -= 1 + if totalerr < 0 : + ret["status"] = "NOT OK" + return ret + val_t = (int(retval,16) & (1<< presentbit)) >> presentbit + if val_t != okval: + ret["status"] = "ABSENT" + else: + ret["status"] = "PRESENT" + except Exception as e: + ret["status"] = "NOT OK" + deverror("getpresentstatus error") + deverror(str(e)) + return ret + + def removeDev(self,bus, loc): + cmd = "echo 0x%02x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath): + os.system(cmd) + + def addDev(self,name, bus, loc): + if name == "lm75": + time.sleep(0.1) + pdevpath = "/sys/bus/i2c/devices/i2c-%d/" % (bus) + cmd = "echo %s 0x%02x > /sys/bus/i2c/devices/i2c-%d/new_device" % (name, loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath) == False: + os.system(cmd) + + def checkattr(self,bus,loc,attr): + '''Determines whether the property is generated''' + try: + attrpath = "/sys/bus/i2c/devices/%d-%04x/%s"%(bus, loc,attr) + if os.path.exists(attrpath): + return True + except Exception as e: + deverror("checkattr error") + deverror(str(e)) + return False + + def monitor(self,ret): + totalerr = 0 + for item in ret: + try: + name = item.get('name') + itemattr = '%sattr' % name + val_t = getattr(DevMonitor,itemattr,None) + if val_t == 'OK': + continue + present = item.get('present') + devices = item.get('device') + err_t = 0 + for item_dev in devices: + item_devattr = '%s' % (item_dev['id']) + val_t = getattr(DevMonitor,item_devattr,None) + if val_t == 'OK': + continue + devname = item_dev.get('name') + bus = item_dev.get('bus') + loc = item_dev.get('loc') + attr = item_dev.get('attr') + if self.checkattr(bus,loc,attr) == False: # Attribute not generated + err_t -= 1 + setattr(DevMonitor,item_devattr,'NOT OK') + presentstatus = self.getpresentstatus(present) # Read in-position + devdebuglog("%s present status:%s" % (name,presentstatus.get('status'))) + if presentstatus.get('status') == 'PRESENT': + self.removeDev(bus,loc) + time.sleep(0.1) + self.addDev(devname, bus, loc) + else: + setattr(DevMonitor,item_devattr,'OK') + val_t = getattr(DevMonitor,item_devattr,None) + devdebuglog("%s status %s" % (item_devattr,val_t)) + if err_t == 0: + setattr(DevMonitor,itemattr,'OK') + else: + totalerr -= 1 + setattr(DevMonitor,itemattr,'NOT OK') + val_t = getattr(DevMonitor,itemattr,None) + devdebuglog("%s status %s" % (itemattr,val_t)) + except Exception as e: + totalerr -= 1 + deverror("monitor error") + deverror(str(e)) + return totalerr + + def psusmonitor(self): + psus_conf = DEV_MONITOR_PARAM.get('psus') + if psus_conf is None: + return 0 + psusattr = 'psusattr' + val_t = getattr(DevMonitor,psusattr,None) + if val_t == 'OK': + return 0 + ret = self.monitor(psus_conf) + if ret == 0: + setattr(DevMonitor,psusattr,'OK') + else: + setattr(DevMonitor,psusattr,'NOT OK') + val_t = getattr(DevMonitor,psusattr,None) + devdebuglog("psusattr:value:%s" % (val_t)) + return ret + + def fansmonitor(self): + fans_conf = DEV_MONITOR_PARAM.get('fans') + if fans_conf is None: + return 0 + fansattr = 'fansattr' + val_t = getattr(DevMonitor,fansattr,None) + if val_t == 'OK': + return 0 + ret = self.monitor(fans_conf) + if ret == 0: + setattr(DevMonitor,fansattr,'OK') + else: + setattr(DevMonitor,fansattr,'NOT OK') + val_t = getattr(DevMonitor,fansattr,None) + devdebuglog("fansattr:value:%s" % (val_t)) + return ret + + def slotsmonitor(self): + slots_conf = DEV_MONITOR_PARAM.get('slots') + if slots_conf is None: + return 0 + slotsattr = 'slotsattr' + val_t = getattr(DevMonitor,slotsattr,None) + if val_t == 'OK': + return 0 + ret = self.monitor(slots_conf) + if ret == 0: + setattr(DevMonitor,slotsattr,'OK') + else: + setattr(DevMonitor,slotsattr,'NOT OK') + val_t = getattr(DevMonitor,slotsattr,None) + devdebuglog("slotsattr:value:%s" % (val_t)) + return ret + + def sdkmonitor(self): + '''Monitor whether the SDK is up and ensure that the SDK is up before enabling the stream light''' + sdk_conf = DEV_MONITOR_PARAM.get('sdk') + ret = 0 + if sdk_conf is None: + return ret + sdkattr = 'sdkattr' + val_t = getattr(DevMonitor,sdkattr,None) + if val_t == 'OK': + return ret + if waitForDocker(timeout = 0) == True: # SDK boot OK + setattr(DevMonitor,sdkattr,'OK') + acts = sdk_conf.get("act",[]) + for item in acts: + if item.get('gettype') == 'i2c': + bus = item.get('bus') + loc = item.get('loc') + offset = item.get('offset') + value = item.get('value') + rji2cset(bus,loc,offset,value) + else: + pass + else: + ret = -1 + setattr(DevMonitor,sdkattr,'NOT OK') + val_t = getattr(DevMonitor,sdkattr,None) + devdebuglog("sdkattr:value:%s" % (val_t)) + return ret + + +def doDevMonitor(devMonitor): + '''Monitors fan, power supply, and subcard properties''' + ret_t = 0 + # PSU + ret_t += devMonitor.psusmonitor() + # FAN + ret_t += devMonitor.fansmonitor() + # Daughter card + ret_t += devMonitor.slotsmonitor() + # SDK + ret_t += devMonitor.sdkmonitor() + return ret_t + +def run(interval, devMonitor): + # devMonitor.devattrinit() + while True: + try: + ret = doDevMonitor(devMonitor) + except Exception as e: + traceback.print_exc() + deverror(str(e)) + ret = -1 + if ret == 0 : + devwarninglog("dev_monitor finished!") + exit(0) + time.sleep(interval) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + '''start device monitor''' + devwarninglog("dev_monitor start") + devMonitor = DevMonitor() + interval = DEV_MONITOR_PARAM.get('polling_time',10)# polling time in the configuration file is 10 seconds by default + run(interval, devMonitor) + +@main.command() +def stop(): + '''stop device monitor ''' + devwarninglog("stop") + +# device_i2c operation +if __name__ == '__main__': + main() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/device_i2c.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/device_i2c.py new file mode 100644 index 000000000000..53e01253a255 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/device_i2c.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +import sys +import click +import os +import subprocess +import time +import mmap +from ragileconfig import * +from ragileutil import rjpciwr, rj_os_system + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def log_os_system(cmd): + '''execute shell command''' + status, output = rj_os_system(cmd) + if status: + print (output) + return status, output + +def write_sysfs_value(reg_name, value): + '''write sysfs files''' + retval = 'ERR' + mb_reg_file = "/sys/bus/i2c/devices/" + reg_name + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return False + try: + with open(mb_reg_file, 'w') as fd: + fd.write(value) + except Exception as error: + return False + return True + +def check_driver(): + '''determine whether there is a driver starting with rg''' + status, output = log_os_system("lsmod | grep rg | wc -l") + # System execution error + if status: + return False + if output.isdigit() and int(output) > 0: + return True + else: + return False + +def getPid(name): + ret = [] + for dirname in os.listdir('/proc'): + if dirname == 'curproc': + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='rb') as fd: + content = fd.read() + except Exception: + continue + if name in content: + ret.append(dirname) + return ret + +def startAvscontrol(): + cmd = "nohup avscontrol.py start >/dev/null 2>&1 &" + rets = getPid("avscontrol.py") + if len(rets) == 0: + os.system(cmd) + pass + +def startFanctrol(): + if STARTMODULE['fancontrol'] == 1: + cmd = "nohup fancontrol.py start >/dev/null 2>&1 &" + rets = getPid("fancontrol.py") + if len(rets) == 0: + os.system(cmd) + +def starthal_fanctrl(): + if STARTMODULE.get('hal_fanctrl',0) == 1: + cmd = "nohup hal_fanctrl.py start >/dev/null 2>&1 &" + rets = getPid("hal_fanctrl.py") + if len(rets) == 0: + os.system(cmd) + +def starthal_ledctrl(): + if STARTMODULE.get('hal_ledctrl',0) == 1: + cmd = "nohup hal_ledctrl.py start >/dev/null 2>&1 &" + rets = getPid("hal_ledctrl.py") + if len(rets) == 0: + os.system(cmd) + +def startDevmonitor(): + if STARTMODULE.get('dev_monitor',0) == 1: + cmd = "nohup dev_monitor.py start >/dev/null 2>&1 &" + rets = getPid("dev_monitor.py") + if len(rets) == 0: + os.system(cmd) + +def startSlotmonitor(): + if STARTMODULE.get('slot_monitor',0) == 1: + cmd = "nohup slot_monitor.py start >/dev/null 2>&1 &" + rets = getPid("slot_monitor.py") + if len(rets) == 0: + os.system(cmd) + +def stopFanctrol(): + '''disable the fan timing service''' + if STARTMODULE['fancontrol'] == 1: + rets = getPid("fancontrol.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def stophal_fanctrl(): + if STARTMODULE.get('hal_fanctrl',0) == 1: + rets = getPid("hal_fanctrl.py") + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def stophal_ledctrl(): + if STARTMODULE.get('hal_ledctrl',0) == 1: + rets = getPid("hal_ledctrl.py") + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + + +def stopSlotmonitor(): + '''disable the slot timing service''' + if STARTMODULE.get('slot_monitor',0) == 1: + rets = getPid("slot_monitor.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def removeDev(bus, loc): + cmd = "echo 0x%02x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath): + log_os_system(cmd) + +def addDev(name, bus, loc): + if name == "lm75": + time.sleep(0.1) + pdevpath = "/sys/bus/i2c/devices/i2c-%d/" % (bus) + for i in range(1, 100):# Wait a maximum of 10 seconds for the generation of the bus + if os.path.exists(pdevpath) == True: + break + time.sleep(0.1) + if i % 10 == 0: + click.echo("%%DEVICE_I2C-INIT: %s not found, wait 0.1 second ! i %d " % (pdevpath,i)) + + cmd = "echo %s 0x%02x > /sys/bus/i2c/devices/i2c-%d/new_device" % (name, loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath) == False: + os.system(cmd) + +def removeQSFP(): + '''add SFP based on all configurations''' + qsfpconfig = GLOBALCONFIG["QSFP"] + for bus in range(qsfpconfig["endbus"], qsfpconfig["startbus"] - 1, -1): + removeDev(bus , 0x50) + removeDev(bus , 0x51) + +def addQSFP(): + qsfpconfig = GLOBALCONFIG["QSFP"] + for bus in range(qsfpconfig["startbus"], qsfpconfig["endbus"] + 1): + addDev("rg_sff", bus , 0x50) + addDev("rg_sff", bus , 0x51) + +def removedevs(): + devs = GLOBALCONFIG["DEVS"] + for index in range(len(devs)-1, -1, -1 ): + removeDev(devs[index]["bus"] , devs[index]["loc"]) + +def adddevs(): + devs = GLOBALCONFIG["DEVS"] + for dev in range(0, devs.__len__()): + addDev(devs[dev]["name"], devs[dev]["bus"] , devs[dev]["loc"]) + +def checksignaldriver(name): + modisexistcmd = "lsmod | grep %s | wc -l" % name + status, output = log_os_system(modisexistcmd) + # System execution error + if status: + return False + if output.isdigit() and int(output) > 0: + return True + else: + return False + +def adddriver(name, delay): + cmd = "modprobe %s" % name + if delay != 0: + time.sleep(delay) + if checksignaldriver(name) != True: + log_os_system(cmd) + +def removedriver(name, delay): + realname = name.lstrip().split(" ")[0]; + cmd = "rmmod -f %s" % realname + if checksignaldriver(realname): + log_os_system(cmd) + +def removedrivers(): + '''remove all drivers''' + if GLOBALCONFIG == None: + click.echo("%%DEVICE_I2C-INIT: load global config failed.") + return + drivers = GLOBALCONFIG.get("DRIVERLISTS", None) + if drivers == None: + click.echo("%%DEVICE_I2C-INIT: load driver list failed.") + return + for index in range(len(drivers)-1, -1, -1 ): + delay = 0 + name = "" + if type(drivers[index]) == dict and drivers[index].__contains__("delay"): + name = drivers[index].get("name") + delay = drivers[index]["delay"] + else: + name = drivers[index] + if name == "i2c_mux_pca954x": + continue + removedriver(name, delay) + +def adddrivers(): + '''add drivers''' + if GLOBALCONFIG == None: + click.echo("%%DEVICE_I2C-INIT: load global config failed.") + return + drivers = GLOBALCONFIG.get("DRIVERLISTS", None) + if drivers == None: + click.echo("%%DEVICE_I2C-INIT: load driver list failed.") + return + for index in range(0 ,len(drivers)): + delay = 0 + name = "" + if type(drivers[index]) == dict and drivers[index].__contains__("delay"): + name = drivers[index].get("name") + delay = drivers[index]["delay"] + else: + name = drivers[index] + adddriver(name, delay) + +def otherinit(): + for index in GLOBALINITPARAM: + delay = index.get('delay',0) + if delay !=0 : + time.sleep(1) + write_sysfs_value(index["loc"], index["value"]) + + for index in GLOBALINITCOMMAND: + log_os_system(index) + +def unload_driver(): + '''unload the device and driver''' + stopFanctrol() # stop the fan control service + stophal_fanctrl() # stop the hal_fan control service + stophal_ledctrl() # stop the LED control service + removeQSFP() # remove optical Modules + removedevs() # remove other devices + removedrivers() # remove drivers + +def reload_driver(): + '''reload the device and driver''' + removedevs() # remove other devices + removedrivers() # remove drivers + time.sleep(1) + adddrivers() + adddevs() + + +def i2c_check(bus,retrytime = 6): + try: + i2cpath = "/sys/bus/i2c/devices/" + bus + while retrytime and not os.path.exists(i2cpath): + click.echo("%%DEVICE_I2C-HA: i2c bus abnormal, last bus %s is not exist." % i2cpath) + reload_driver() + retrytime -= 1 + time.sleep(1) + except Exception as e: + click.echo("%%DEVICE_I2C-HA: %s" % str(e)) + return + +def MacLedSet(data): + '''write pci register''' + pcibus = MAC_LED_RESET.get("pcibus") + slot = MAC_LED_RESET.get("slot") + fn = MAC_LED_RESET.get("fn") + bar = MAC_LED_RESET.get("bar") + offset = MAC_LED_RESET.get("offset") + val = MAC_LED_RESET.get(data, None) + if val == None: + click.echo("%%DEVICE_I2C-INIT: MacLedSet wrong input") + return + rjpciwr(pcibus, slot, fn, bar, offset, val) + +def load_driver(): + '''load the device and driver''' + adddrivers(); + adddevs(); + if STARTMODULE.get("i2ccheck",0) == 1: # i2c HA + busend = i2ccheck_params.get("busend") + retrytime = i2ccheck_params.get("retrytime") + i2c_check(busend,retrytime) + addQSFP() # adding an Optical Module eeprom + startFanctrol() # open the fan + starthal_fanctrl() # open the fan control + starthal_ledctrl() # open the LED control + if STARTMODULE['avscontrol'] == 1: + startAvscontrol() # avs pressure adjusting + startDevmonitor() # pluggable device driver monitoring + startSlotmonitor() # Initialization monitoring of cable card insertion and removal + otherinit(); # Others and the optical module Initializes + if STARTMODULE.get("macledreset",0) == 1: + MacLedSet("reset") + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + + +@main.command() +def start(): + '''load device ''' + if check_driver(): + unload_driver() + load_driver() + +@main.command() +def stop(): + '''stop device ''' + unload_driver() + +@main.command() +def restart(): + '''restart device''' + unload_driver() + load_driver() + +if __name__ == '__main__': + '''device_i2c operation''' + main() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/env_check.sh b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/env_check.sh new file mode 100644 index 000000000000..28dd9e20b8e9 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/env_check.sh @@ -0,0 +1,82 @@ +#!/bin/bash +</dev/null 2>&1 &" + rets = getPid("fancontrol.py") + if len(rets) == 0: + os.system(cmd) + +def test_stop_fanctrol(): + stopFanctrol() + return True,"" + +def test_start_fanctrol(): + startFanctrol() + return True,"" + +# Menu Prints a menu item with a numeric prompt in front +def printList(_list, id): + try: + RJPRINT("****************************************") + for index in range(len(_list)): + RJPRINT(formatStringLevel1 %( listindex[index] , _list[index]["name"])) + if id != STARTMENUID: + RJPRINT("q.返回上一层") + else: + RJPRINT("q.退出") + RJPRINT("****************************************") + except Exception as e: + log_error(e) + sys.exit(-1) + +# Menu: Single test +def test_signal(id): + startMenu(id) + +def dealfunc(func): + msg = "" + for i in range(0, 3): + ret, msg = func() + if ret == True: + return True + else: + continue + raise Exception(msg) + return False + +def dealchoosefunc(list): + '''Real menu processing items''' + RET = ERROR_RETURN + funcbefore = None + functest = None + funcafter = None + param_tt = None + param_val = None + funcbeforestr = list.get(ITEMBEFORE, None) + functeststr = list.get(MENUITEMDEAL, None) + funcafterstr = list.get(ITEMAFTER, None) + param_tt = list.get(CHILDID, None) + param_val = list.get('param', None) + + if funcbeforestr is not None: + funcbefore = eval(funcbeforestr) + if functeststr is not None: + functest = eval(functeststr) + if funcafterstr is not None: + funcafter = eval(funcafterstr) + try: + if funcbefore is not None: + log_debug(" 测试项前置:%s " % (funcbefore)) + dealfunc(funcbefore) + if functest is not None: + log_debug(" 测试项 :%s " % (functest)) + if param_tt is not None: + RET = functest(param_tt) + else: + if param_val is not None: + RET = functest(param_val) + else: + RET = functest() + else: + raise Exception("fun test is none") + + except Exception as e: + RJPRINT(e) + RJPRINT("error\n\n") + finally: + if funcafter is not None: + log_debug(" 测试项后置:%s " % (funcafter)) + for i in range(0, 3): + if funcafter() == True: + break + else: + continue + return RET + +def getch(msg): + ret = "" + fd = sys.stdin.fileno() + old_ttyinfo = termios.tcgetattr(fd) + new_ttyinfo = old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + sys.stdout.write(msg) + sys.stdout.flush() + try: + termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo) + ret = os.read(fd, 1) + finally: + # print "try to setting" + termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo) + return ret + +# Menu to print +# printMenu +# param: list_t Menu item list +# id Menu id + +def printMenu(list_t, id): + while True: + try: + printList(list_t, id) + test = "请选择:" + str= getch(test) + RJPRINT(" %s" % str) + log_debug("选择:%s" % str) + str = str.lstrip().lower() + if str == "q": + if id == STARTMENUID: # Top level directory. There's no way back + quit() + else: + break + if str not in listindex: + log_debug("%s 不在菜单项中" % str); + RJPRINT("\n\n") + continue + else: + RJPRINT("=======================> %s <======================="%list_t[listindex.index(str)][MENUITEMNAME]) + log_debug("选择的测试项为:%s id:%d" % (list_t[listindex.index(str)][MENUITEMNAME], id)) + + RET = dealchoosefunc(list_t[listindex.index(str)]) + if RET == None: + RJPRINT("\n\n") + continue + RJPRINT(" ") + if RET[RETURN_KEY1] == 0: + RJPRINT("Test Result: Pass") + log_debug("菜单测试结果:" + SUCCESS_TIPS) + elif RET[RETURN_KEY1] == 1: + pass + else: + RJPRINT("Test Result: Fail") + log_debug("[%s]测试结果:" % list_t[listindex.index(str)][MENUITEMNAME] + 'error') + RJPRINT("\n\n") + except IndexError as d: + RJPRINT("\n\n非法输入\n\n") + except Exception as e: + RJPRINT(e) + # log_debug(e) + RJPRINTERR("\n\n 异常\n\n" ) + +def getMenuFromList(list, id): + for key in list: + if key[MENUID] == id: + return key[MENUVALUE],True + return 0, False + +def getParentIdMenuFromList(list, id): + for key in list: + if key[MENUID] == id: + return key[MENUPARENT],True + return -1, False + +# Get the menu by ID +def startMenu(id): + list,code = getMenuFromList(menuList, id) + if code == False: + log_error("错误的文件结构") + RJPRINT("无此菜单,请确认") + sys.exit(1) + log_debug("根据ID获取到相应的菜单列表") + printMenu(list, id) + +# start +def start(): + global STARTMENUID + if STARTMENUID is None: + STARTMENUID = 0 + startMenu(STARTMENUID) + +def rj_os_system(cmd): + status, output = commands.getstatusoutput(cmd) + return status, output + +def io_wr(reg_addr, reg_data): + '''io write''' + try: + regdata = 0 + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + if type(reg_data) == int: + regdata = reg_data + else: + regdata = int(reg_data, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + ret = os.write(fd, chr(regdata)) + return True + except ValueError as e: + print (e) + return False + except Exception as e: + print (e) + return False + finally: + os.close(fd) + return False + +def rji2cset(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + +def rji2cget(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + +def get_fane2_sysfs(bus, loc): + rg_fan_e2 = "%d-%04x/fan" % (bus, loc) + eeprom = get_sysfs_value(rg_fan_e2) + return eeprom + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR + reg_name + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + try: + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + log_error("Unable to open " + mb_reg_file + "file !") + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + # log_debug(retval) + return retval + +def get_sysfs_value(location): + pos_t = str(location) + name = get_pmc_register(pos_t) + return name + +def get_sys_eeprom(): + onietlv = onie_tlv() + eeprom = get_sysfs_value(rg_eeprom) + return onietlv.decode(eeprom) + +def getsyseeprombyId(id): # Obtain the system system by ID + ret = get_sys_eeprom() + for item in ret: + if item["code"] == id: + return item + return None + +def getsysvalue(location): + retval = None + mb_reg_file = location + try: + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + log_error("Unable to open " + mb_reg_file + "file !") + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + # log_debug(retval) + return retval + +class I2CUTIL(): + @staticmethod + def getvaluefromdevice(name): + ret = [] + if DEVICE == None: + return None + for item in DEVICE: + if item["name"] == name: + ret.append(item) + return ret + + @staticmethod + def openFanE2Protect(): + if FAN_PROTECT is None or len(FAN_PROTECT) <= 0: + return True + if type(FAN_PROTECT) == list: # expand 20190429 + for item in FAN_PROTECT: + status, log = rji2cset(item["bus"], item["devno"], + item["addr"], item["open"]) + if status == False: + return False + elif type(FAN_PROTECT) == dict: + status, log = rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + if status == False: + return False + else: + return False + return True + + @staticmethod + def closeFanE2Protect(): + if FAN_PROTECT is None or len(FAN_PROTECT) <= 0: + return True + if type(FAN_PROTECT) == list: # expand 20190429 + for item in FAN_PROTECT: + status, log = rji2cset(item["bus"], item["devno"], + item["addr"], item["close"]) + if status == False: + return False + elif type(FAN_PROTECT) == dict: + status, log = rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + if status == False: + return False + else: + return False + return True + + @staticmethod + def writeToE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + status, log = rji2cset(bus, loc, index, ord(item)) + if status == False: + return False + index += 1 + return True + + @staticmethod + def getE2File(bus, loc): + return "/sys/bus/i2c/devices/%d-00%02x/eeprom" % (bus, loc) + + @staticmethod + def dumpValueByI2c(bus, loc): + str = "" + for i in range(256): + ret,val = rji2cget(bus, loc, i) + str += chr(int(val, 16)) + return str + +def fac_fan_setmac(item): + + status = I2CUTIL.openFanE2Protect() + if status == False: + return False + status = I2CUTIL.writeToE2(item.fanbus, item.fanloc, item.generate_fan_value()) + if status == False: + return False + I2CUTIL.closeFanE2Protect() + return True + +def fac_fru_fan_setmac(bus,loc,value): + '''fan FRU setmac''' + status = I2CUTIL.openFanE2Protect() + if status == False: + return False + status = I2CUTIL.writeToE2(bus, loc, value) + if status == False: + return False + I2CUTIL.closeFanE2Protect() + return True + +def fac_fans_show_tlv(ret): + totalerr = 0 + fans = ret + for fan in fans: + try: + RJPRINT("===============fan%d ================getmessage" % (fans.index(fan)+1)) + # eeprom = I2CUTIL.dumpValueByI2c(fan.get('bus'), fan.get('loc')) + loc = "%d-%04x/fan" % (fan.get('bus'), fan.get('loc')) + eeprom = get_sysfs_value(loc) + tlv = fan_tlv() + rets = tlv.decode(eeprom) + if len(rets) == 0: + totalerr -= 1 + RJPRINT("fan E2 read error, please set fan E2 !") + continue + RJPRINT("%-15s %-5s %-5s %-20s" % ("TLV name","Code","lens","Value")) + for item in rets: + RJPRINT("%-15s 0x%-02X %-5s %-20s" % (item["name"],item["code"],item["lens"],item["value"])) + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + + if totalerr < 0: + return False + return True + +def fac_fans_show_fru(ret): + fans = ret + totalerr = 0 + for fan in fans: + try: + RJPRINT("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + + RJPRINT("=================board=================") + RJPRINT(fru.boardInfoArea) + RJPRINT("=================product=================") + RJPRINT(fru.productInfoArea) + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + if totalerr <0: + return False + return True + +def test_fan_eeprom(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + try: + if (fans_eeprom_show() == False): + totalerr -= 1 + except Exception as e: + RJPRINTERR(e) + totalerr -= 1 + RET[RETURN_KEY1] = totalerr + return RET + +def fans_eeprom_show(): + ret = I2CUTIL.getvaluefromdevice("rg_fan") + if ret is not None and len(ret) > 0: + return fac_fans_show_tlv(ret) + fans = FRULISTS.get('fans', None) + if fans is not None and len(fans)>0: + return fac_fans_show_fru(fans) + return False + +def test_fan_fru_e2set(product_info,frulist): + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + fans = frulist + fanfrus = {} + for fan in fans: + try: + RJPRINT("===============%s E2信息转换中================" % fan.get('name')) + # Read the NFUR information of the original fan first + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + if eeprom is None: + raise Exception("错误") + fru = ipmifru() + fru.decodeBin(eeprom) + bia = fru.boardInfoArea + boardinfo = product_info.get("BOARD",{}) + bia.boardManufacturer = boardinfo.get("boardManufacturer",bia.boardManufacturer) + bia.boardProductName = boardinfo.get("boardProductName",bia.boardProductName) + bia.boardPartNumber = boardinfo.get("boardPartNumber",bia.boardPartNumber) + bia.fruFileId = boardinfo.get("fruFileId",bia.fruFileId) + # board extension field boardextra1 is used as the hardware version number and is not modified. The field starts from boardextra2 + for i in range(2, 11): + valtmp = "boardextra%d" % i + if valtmp in boardinfo: + setattr(bia,valtmp,boardinfo[valtmp]) + else: + break + + pia = fru.productInfoArea + productinfo = product_info.get("PRODUCT",{}) + pia.productManufacturer = productinfo.get("productManufacturer",pia.productManufacturer) + pia.productName = productinfo.get("productName",pia.productName) + pia.productPartModelName = productinfo.get("productPartModelName",pia.productPartModelName) + pia.productAssetTag = productinfo.get("productAssetTag",pia.productAssetTag) + pia.fruFileId = productinfo.get("fruFileId",pia.fruFileId) + # product Expand the fields + for i in range(1, 11): + valtmp = "productextra%d" % i + if valtmp in productinfo: + setattr(pia,valtmp,productinfo[valtmp]) + else: + break + fru.recalcute() + # writetoE2 + status = fac_fru_fan_setmac(fan.get('bus'), fan.get('loc'), fru.bindata) + if status == False: + RET[RETURN_KEY1] -= 1 + RJPRINT("===========%s E2转换失败!============" % fan.get('name')) + continue + # readFanE2 + RJPRINT("===========%s E2转换完成,显示如下:============" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + + RJPRINT("=================board=================") + RJPRINT(fru.boardInfoArea) + RJPRINT("=================product=================") + RJPRINT(fru.productInfoArea) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] -= 1 + return RET + +def test_fan_tlv_e2set(product_info,fanlist): + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + totalerr = 0 + for fan in fanlist: + try: + _value = {} + RJPRINT("===============fan%d E2信息转换中================" % (fanlist.index(fan)+1)) + fantlv = fan_tlv() + fantlv.fanbus = fan.get('bus') + fantlv.fanloc = fan.get('loc') + fan_eeprom = get_fane2_sysfs(fantlv.fanbus,fantlv.fanloc) + rets = fantlv.decode(fan_eeprom) + if len(rets) == 0: + totalerr -= 1 + RJPRINT("风扇E2解析失败,请确认是否正常烧片 !") + continue + # Obtain the fan name and ID from the configuration file + fantlv.typename = product_info.get("FAN_NAME") + fantlv.typedevtype = product_info.get("FAN_ID") + status = fac_fan_setmac(fantlv) + if status == False: + RJPRINT("===========fan%d E2转换失败!============" % (fanlist.index(fan)+1)) + continue + RJPRINT("===========fan%d E2转换完成,显示如下:============" % (fanlist.index(fan)+1)) + eeprom = get_fane2_sysfs(fantlv.fanbus,fantlv.fanloc) + rets = fantlv.decode(eeprom) + RJPRINT("%-15s %-5s %-5s %-20s" % ("TLV name","Code","lens","Value")) + for item in rets: + RJPRINT("%-15s 0x%-02X %-5s %-20s" % (item["name"],item["code"],item["lens"],item["value"])) + RJPRINT("") + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def test_fan_e2set(productname): + '''Do fan-E2 conversion based on product name''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + product_info = FAN_E2.get(productname,None) + if product_info is None: + RJPRINT("%s无风扇E2转换配置" % productname) + return RET + try: + stopFanctrol() + ret = I2CUTIL.getvaluefromdevice("rg_fan") + if ret is not None and len(ret) > 0: + return test_fan_tlv_e2set(product_info,ret) + fans = FRULISTS.get('fans', None) + if fans is not None and len(fans) > 0: + return test_fan_fru_e2set(product_info,fans) + except Exception as e: + RJPRINT(str(e)) + finally: + startFanctrol() + RET[RETURN_KEY1] = -1 + return RET + +def test_show_tlv_eeprom(is_sonic = True): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + eeprom = "" + totalerr = 0 + params = {} + try: + if is_sonic == True: + eeprom = get_sysfs_value(rg_eeprom) + else: + loc = BMC_E2_LOC.get("tlv",None) + ret = test_get_bmc_eeprom(loc) + if ret[RETURN_KEY1] < 0: + RJPRINT("读取BMC-TLV-E2失败") + RET[RETURN_KEY1] = -1 + return RET + eeprom = ret[RETURN_KEY2] + onietlv = onie_tlv() + rets = onietlv.decode(eeprom) + RJPRINT("%-20s %-5s %-5s %-20s" % ("TLV name","Code","lens","Value")) + for item in rets: + if item["code"] == 0xfd: + RJPRINT("%-20s 0x%-02X %-5s" % (item["name"],item["code"],item["lens"])) + else: + RJPRINT("%-20s 0x%-02X %-5s %-20s" % (item["name"],item["code"],item["lens"],item["value"])) + RJPRINT("") + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def generate_onie_tlv_value(product_info,is_sonic = True): + '''Generate burn files for each product''' + RET = {RETURN_KEY1:0, RETURN_KEY2:""} + _value = {} + params = {} + eeprom = "" + try: + if is_sonic == True: + eeprom = get_sysfs_value(rg_eeprom) + else: + loc = BMC_E2_LOC.get("tlv",None) + ret = test_get_bmc_eeprom(loc) + if ret[RETURN_KEY1] < 0: + RJPRINT("读取BMC-TLV-E2失败") + RET[RETURN_KEY1] = -1 + return RET + eeprom = ret[RETURN_KEY2] + onietlv = onie_tlv() + rets = onietlv.decode(eeprom) + if onietlv.serialnum == "": # There is no SEMAC, only one ID is set + _value[onietlv.TLV_CODE_VENDOR_EXT] = onietlv.generate_ext(product_info.get("CARDID")) + else: + # The serial number, MAC, and hardware version remain the same + _value[onietlv.TLV_CODE_SERIAL_NUMBER] = onietlv.serialnum + _value[onietlv.TLV_CODE_DEVICE_VERSION] = onietlv.deviceversion + _value[onietlv.TLV_CODE_MAC_BASE] = onietlv.macbase + # Replace with the information in the configuration file + vendor_ext = product_info.get("RAGILE_VENDOR_EXTENSION") + if vendor_ext is None: + _value[onietlv.TLV_CODE_VENDOR_EXT] = onietlv.generate_ext(product_info.get("CARDID")) # Generates an ID unique to ragile + else: + hwversion = str(onietlv.deviceversion) + new_hwversion = hwversion[0:1] + "." + hwversion[1:] + newstr = vendor_ext[0:16] + new_hwversion + vendor_ext[20:] + _value[onietlv.TLV_CODE_VENDOR_EXT] = newstr + + _value[onietlv.TLV_CODE_PRODUCT_NAME] = product_info.get("RAGILE_PRODUCTNAME") + _value[onietlv.TLV_CODE_PART_NUMBER] = product_info.get("RAGILE_PART_NUMBER") + _value[onietlv.TLV_CODE_LABEL_REVISION] = product_info.get("RAGILE_LABEL_REVISION") + _value[onietlv.TLV_CODE_PLATFORM_NAME] = product_info.get("RAGILE_PLATFORM_NAME") + _value[onietlv.TLV_CODE_ONIE_VERSION] = product_info.get("RAGILE_ONIE_VERSION") + _value[onietlv.TLV_CODE_MAC_SIZE] = product_info.get("RAGILE_MAC_SIZE") + _value[onietlv.TLV_CODE_MANUF_NAME] = product_info.get("RAGILE_MANUF_NAME") + _value[onietlv.TLV_CODE_MANUF_COUNTRY] = product_info.get("RAGILE_MANUF_COUNTRY") + _value[onietlv.TLV_CODE_VENDOR_NAME] = product_info.get("RAGILE_VENDOR_NAME") + _value[onietlv.TLV_CODE_DIAG_VERSION] = product_info.get("RAGILE_DIAG_VERSION") + _value[onietlv.TLV_CODE_SERVICE_TAG] = product_info.get("RAGILE_SERVICE_TAG") + _value[onietlv.TLV_CODE_MANUF_DATE] = time.strftime( + '%m/%d/%Y %H:%M:%S', time.localtime()) # Automatically add setMAC time + rst, ret = onietlv.generate_value(_value) + RET[RETURN_KEY2] = rst + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + return RET + +def writeToEEprom(rst_arr): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + try: + dealtype = E2_PROTECT.get('gettype',None) + if dealtype is None: + rst, log = rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["open"]) + elif dealtype == "io": + rst = io_wr(E2_PROTECT["io_addr"], E2_PROTECT["open"]) + if rst == False: + RJPRINT("Write E2 protect Failed!") + RET[RETURN_KEY1] = -1 + return RET + index = 0 + for item in rst_arr: + rst, log = rji2cset(E2_LOC["bus"], E2_LOC["devno"], index, ord(item)) + if rst == False: + RJPRINT("Write E2 protect Failed!") + RET[RETURN_KEY1] = -1 + return RET + index += 1 + + if dealtype is None: + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["close"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["close"]) + # Finally, the system driver is dealt with + os.system("rmmod at24 ") + os.system("modprobe at24 ") + os.system("rm -f /var/cache/sonic/decode-syseeprom/syseeprom_cache") + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + return RET + +def writeToBMCEEprom(rst_arr, loc, ep_param): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + params = {} + try: + params["value"] = [] + params["loc"] = loc + params.update(ep_param) + for item in rst_arr: # Item is a character, converted to ASCII + params["value"].append(ord(item)) + func = "test_bmc_write_eeprom" + RET = test_bmc_func(func,params) + if RET[RETURN_KEY1] < 0: + return RET + except Exception as e: + RET[RETURN_KEY2] = str(e) + RET[RETURN_KEY1] = -1 + return RET + +def test_get_bmc_eeprom(loc): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + params = {} + eeprom = "" + params["loc"] = loc + func = "test_bmc_read_eeprom" + try: + ret = test_bmc_func(func,params) + if ret[RETURN_KEY1] < 0: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = ret[RETURN_KEY2] + return RET + value = ret.get("value","") + for i in value: + eeprom += chr(i) + RET[RETURN_KEY2] = eeprom + except Exception as e: + RET[RETURN_KEY1] -= 1 + RET[RETURN_KEY2] = str(e) + return RET + +def test_bmc_tlv_e2set(productname): + '''Perform TLV--E2 conversion on the BMC side according to the product name''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + product_info = ONIE_E2.get(productname,None) + if product_info is None or FACE2MODULE.get("tlvbmce2set",0) == 0: + RJPRINT("%s无BMC-TLV-E2转换配置" % productname) + return RET + try: + RJPRINT("===============BMC-TLV-E2信息转换中================") + # Generate the BMC ONie-E2 burn file + RET = generate_onie_tlv_value(product_info,is_sonic = True) # Read onie-E2 on X86 to generate burn sheets + if RET[RETURN_KEY1] < 0: + RJPRINT("生成BMC-TLV-E2烧录文件失败") + return RET + # write BMC E2 + loc = BMC_E2_LOC.get("tlv") + eeprom = RET[RETURN_KEY2] + ep_param = {} + if isinstance(BMC_E2_PROTECT, dict): + ep_param = BMC_E2_PROTECT.get("tlv", {}) + + for i in range(0,3): + RET = writeToBMCEEprom(eeprom, loc, ep_param) + if RET[RETURN_KEY1] >= 0: + break + time.sleep(3) + if RET[RETURN_KEY1] < 0: + RJPRINT("BMC-TLV-E2转换失败") + RJPRINT(RET[RETURN_KEY2]) + return RET + RJPRINT("===========BMC-TLV-E2转换成功,信息显示如下:===========") + test_show_tlv_eeprom( is_sonic = False ) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + return RET + +def test_onie_e2set(productname): + '''Do the ONIE-E2 conversion based on the product name''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + product_info = ONIE_E2.get(productname,None) + if product_info is None: + RJPRINT("%s无ONIE-E2转换配置" % productname) + return RET + # Generate onie-E2 burn file + try: + RJPRINT("===============ONIE-E2信息转换中================") + RET = generate_onie_tlv_value(product_info) + if RET[RETURN_KEY1] < 0: + RJPRINT("生成ONIE-E2烧录文件失败") + return RET + # write E2 + RET = writeToEEprom(RET[RETURN_KEY2]) + if RET[RETURN_KEY1] < 0: + RJPRINT("ONIE-E2转换失败") + return RET + RJPRINT("===========ONIE-E2转换完成,信息显示如下:===========") + test_show_tlv_eeprom() + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + return RET + +def fac_init_cardidcheck(): + onie_tlv = onietlv() + rest = getsyseeprombyId(onie_tlv.TLV_CODE_RJ_CARID) # Check whether cardId are the sam + if rest == None: + print ("需要烧写bin文件") + return False + return True + +def fac_setmac_check(): + # Check the CARD ID + if fac_init_cardidcheck() == False: + RJPRINTERR("\n\n板卡ID检测失败,请确认!\n\n") + sys.exit(-1); + return True + +def root_check(): + if os.geteuid() != 0: + click.echo("请在Root权限下执行!") + sys.exit(1) + +def test_show_slots_tlv_eeprom(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + slots = FRULISTS.get('slots_tlv', []) + for slot in slots: + try: + RJPRINT("===============%s ================getmessage" % slot.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + tlv = fan_tlv() + rets = tlv.decode(eeprom) + if len(rets) == 0: + totalerr -= 1 + RJPRINT("子卡TLV-E2读取失败,请确认烧片是否正常 !") + continue + RJPRINT("%-15s %-5s %-5s %-20s" % ("TLV name","Code","lens","Value")) + for item in rets: + RJPRINT("%-15s 0x%-02X %-5s %-20s" % (item["name"],item["code"],item["lens"],item["value"])) + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def test_slots_tlv_e2set(productname): + '''According to the product name to do child card TLV-E2 conversion''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + totalerr = 0 + product_info = SLOTS_TLV_E2.get(productname,None) + if product_info is None or FACE2MODULE.get("tlvslote2set",0) == 0: + RJPRINT("%s无子卡TLV-E2转换配置" % productname) + return RET + slots = FRULISTS.get('slots_tlv', []) + protect = TLV_SLOTS_PROTECT + try: + for item in protect: + status = rji2cset(item["bus"], item["devno"], item["addr"], item["open"]) + if status == False: + RJPRINT("子卡TLV-E2写保护设置失败") + RET[RETURN_KEY1] = -1 + return RET + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + return RET + for slot in slots: + try: + RJPRINT("===============tlv_%s E2信息转换中================" % slot.get('name')) + slottlv = fan_tlv() + slot_eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + rets = slottlv.decode(slot_eeprom) + if len(rets) == 0: + totalerr -= 1 + RJPRINT("子卡TLV-E2解析失败,请确认是否正常烧片 !") + continue + # Get the name and ID of the subcard from the configuration file + slottlv.typename = product_info.get("SLOT_NAME",slottlv.typename) + slottlv.typedevtype = product_info.get("SLOT_ID",slottlv.typedevtype) + status = I2CUTIL.writeToE2(slot.get('bus'), slot.get('loc'), slottlv.generate_fan_value()) + if status == False: + RJPRINT("===========%s TLV-E2转换失败!============" % slot.get('name')) + continue + RJPRINT("===========%s TLV-E2转换完成,显示如下:============" % slot.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + rets = slottlv.decode(eeprom) + RJPRINT("%-15s %-5s %-5s %-20s" % ("TLV name","Code","lens","Value")) + for item in rets: + RJPRINT("%-15s 0x%-02X %-5s %-20s" % (item["name"],item["code"],item["lens"],item["value"])) + RJPRINT("") + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + if totalerr < 0: + RET[RETURN_KEY1] = -1 + for item in protect: + rji2cset(item["bus"], item["devno"], item["addr"], item["close"]) + return RET + +def test_slots_fru_e2set(productname): + '''Make the FRU-E2 conversion for the sub-card according to the product name''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + totalerr = 0 + product_info = SLOTS_FRU_E2.get(productname,None) + if product_info is None or FACE2MODULE.get("fruslote2set",0) == 0: + RJPRINT("%s无子卡FRU-E2转换配置" % productname) + return RET + slots = FRULISTS.get('slots_fru', []) + protect = FRU_SLOTS_PROTECT + try: + for item in protect: + status = rji2cset(item["bus"], item["devno"], item["addr"], item["open"]) + if status == False: + RJPRINT("子卡FRU-E2写保护设置失败") + RET[RETURN_KEY1] = -1 + return RET + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + return RET + for slot in slots: + try: + RJPRINT("===============fru_%s E2信息转换中================" % slot.get('name')) + slotfru = ipmifru() + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + slotfru.decodeBin(eeprom) + # Get the name and ID of the subcard from the configuration file + bia = slotfru.boardInfoArea + bia.boardManufacturer = product_info.get("boardManufacturer",bia.boardManufacturer) + bia.boardProductName = product_info.get("boardProductName",bia.boardProductName) + bia.boardPartNumber = product_info.get("boardPartNumber",bia.boardPartNumber) + bia.fruFileId = product_info.get("fruFileId",bia.fruFileId) + # board extension field boardextra1 is used as the hardware version number and is not modified. The field starts from boardextra2 + for i in range(2, 11): + valtmp = "boardextra%d" % i + if valtmp in product_info: + setattr(bia,valtmp,product_info[valtmp]) + else: + break + slotfru.recalcute() + status = I2CUTIL.writeToE2(slot.get('bus'), slot.get('loc'), slotfru.bindata) + if status == False: + RJPRINT("===========%s FRU-E2转换失败!============" % slot.get('name')) + continue + RJPRINT("===========%s FRU-E2转换完成,显示如下:============" % slot.get('name')) + new_eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + slotfru.decodeBin(new_eeprom) + RJPRINT(slotfru.boardInfoArea) + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + if totalerr < 0: + RET[RETURN_KEY1] = -1 + for item in protect: + rji2cset(item["bus"], item["devno"], item["addr"], item["close"]) + return RET + +def test_slots_tlvtofru_e2set(productname): + '''Subcard TLV to FRU''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + totalerr = 0 + product_info = SLOTS_FRU_E2.get(productname,None) + if product_info is None: + RJPRINT("%s无子卡FRU-E2转换配置" % productname) + return RET + protect = FRU_SLOTS_PROTECT + try: + for item in protect: + status = rji2cset(item["bus"], item["devno"], item["addr"], item["open"]) + if status == False: + RJPRINT("子卡FRU-E2写保护设置失败") + RET[RETURN_KEY1] = -1 + return RET + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + return RET + tlv_slots = FRULISTS.get('slots_tlv', []) + fru_slots = FRULISTS.get('slots_fru') + for slot in tlv_slots: + try: + RJPRINT("===============%s E2信息转换中================" % slot.get('name')) + slottlv = fan_tlv() + # Read the E2 information of the original TLV subcard + slot_eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + rets = slottlv.decode(slot_eeprom) + if len(rets) == 0: + totalerr -= 1 + RJPRINT("子卡TLV-E2解析失败,无法进行转换,请确认是否正常烧片 !") + continue + # Generate an FRU burn file based on the configuration file and the SERIAL number and hardware version of the TLV subcard + slotfru = ipmifru() + slotfru.boardInfoArea = BoardInfoArea(name="Board Info Area") + slotfru.boardInfoArea.isPresent = 1 + slotfru.boardInfoArea.boardManufacturer = product_info.get('boardManufacturer') + slotfru.boardInfoArea.boardProductName = product_info.get('boardProductName') + slotfru.boardInfoArea.boardPartNumber = product_info.get('boardPartNumber') + slotfru.boardInfoArea.fruFileId = product_info.get('fruFileId') + slotfru.boardInfoArea.boardSerialNumber = slottlv.typesn + slotfru.boardInfoArea.boardextra1 = slottlv.typehwinfo + slotfru.recalcute() + fru_slot_bus = fru_slots[tlv_slots.index(slot)].get('bus') + fru_slot_loc = fru_slots[tlv_slots.index(slot)].get('loc') + status = I2CUTIL.writeToE2(fru_slot_bus, fru_slot_loc, slotfru.bindata) + if status == False: + RJPRINT("===========%s E2转换失败!============" % slot.get('name')) + continue + RJPRINT("===========%s E2转换完成,显示如下:============" % slot.get('name')) + new_eeprom = I2CUTIL.dumpValueByI2c(fru_slot_bus, fru_slot_loc) + slotfru.decodeBin(new_eeprom) + RJPRINT(slotfru.boardInfoArea) + RJPRINT("") + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + if totalerr < 0: + RET[RETURN_KEY1] = -1 + for item in protect: + rji2cset(item["bus"], item["devno"], item["addr"], item["close"]) + return RET + +def test_show_slots_fru_eeprom(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + slots = FRULISTS.get('slots_fru', []) + for slot in slots: + try: + RJPRINT("===============%s ================getmessage" % slot.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + if eeprom is None: + raise Exception("错误") + slote2 = ipmifru() + slote2.decodeBin(eeprom) + RJPRINT(slote2.boardInfoArea) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] -= 1 + RET[RETURN_KEY2] = str(e) + + return RET + +def test_show_bmc_fru_eeprom(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + try: + loc = BMC_E2_LOC.get("fru",None) + ret = test_get_bmc_eeprom(loc) + if ret[RETURN_KEY1] < 0 : + RJPRINT("读取BMC-FRU-E2失败") + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = ret[RETURN_KEY2] + return RET + eeprom = ret[RETURN_KEY2] + bmcfru = ipmifru() + bmcfru.decodeBin(eeprom) + RJPRINT(bmcfru.boardInfoArea) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] -= 1 + RET[RETURN_KEY2] = str(e) + return RET + +def test_bmc_fru_e2set(productname): + '''Perform BMC FRU-E2 conversion according to product name''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + product_info = BMC_FRU_E2.get(productname,None) + if product_info is None: + RJPRINT("%s无BMC FRU-E2转换配置" % productname) + return RET + RJPRINT("===============BMC-FRU-E2信息转换中================") + try: + loc = BMC_E2_LOC.get("fru",None) + ret = test_get_bmc_eeprom(loc) + if ret[RETURN_KEY1] < 0 : + RET[RETURN_KEY1] = -1 + return RET + # Generate the BMC ONie-E2 burn file + eeprom = ret[RETURN_KEY2] + fru_size = len(eeprom) + bmcfru = ipmifru() + bmcfru.decodeBin(eeprom) + # Get the name and ID of the subcard from the configuration file + bia = bmcfru.boardInfoArea + bia.boardManufacturer = product_info.get("boardManufacturer",bia.boardManufacturer) + bia.boardProductName = product_info.get("boardProductName",bia.boardProductName) + bia.boardPartNumber = product_info.get("boardPartNumber",bia.boardPartNumber) + bia.fruFileId = product_info.get("fruFileId",bia.fruFileId) + # board extension field boardextra1 is used as the hardware version number and is not modified. The field starts from boardextra2 + for i in range(2, 11): + valtmp = "boardextra%d" % i + if valtmp in product_info: + setattr(bia,valtmp,product_info[valtmp]) + else: + break + bmcfru.recalcute(fru_eeprom_size = fru_size) + # write BMC E2 + loc = BMC_E2_LOC.get("fru") + ep_param = {} + if isinstance(BMC_E2_PROTECT, dict): + ep_param = BMC_E2_PROTECT.get("fru", {}) + for i in range(0,3): + RET = writeToBMCEEprom(bmcfru.bindata, loc, ep_param) + if RET[RETURN_KEY1] >= 0: + break + time.sleep(3) + if RET[RETURN_KEY1] < 0: + RJPRINT("BMC-FRU-E2转换失败") + RJPRINT(RET[RETURN_KEY2]) + return RET + RJPRINT("===========BMC-FRU-E2转换成功,信息显示如下:===========") + RET = test_show_bmc_fru_eeprom() + except Exception as e: + RET[RETURN_KEY2] = str(e) + RJPRINT(RET[RETURN_KEY2]) + RET[RETURN_KEY1] = -1 + return RET + +def test_all_e2set(productname): + '''Convert all E2s by product name''' + RET = {RETURN_KEY1 : 0 , RETURN_KEY2 : ""} + totalerr = 0 + # ONIE-E2 conversion + ret = test_onie_e2set(productname) + if ret[RETURN_KEY1] < 0: + totalerr -= 1 + + # fan E2 conversion + ret = test_fan_e2set(productname) + if ret[RETURN_KEY1] < 0: + totalerr -= 1 + + # Daughter card-TLV-E2 conversion + if FACE2MODULE.get("tlvslote2set",0) == 1: + ret = test_slots_tlv_e2set(productname) + if ret[RETURN_KEY1] < 0: + totalerr -= 1 + + # Daughter card-FRU-E2 conversion + if FACE2MODULE.get("fruslote2set",0) == 1: + ret = test_slots_fru_e2set(productname) + if ret[RETURN_KEY1] < 0: + totalerr -= 1 + + # BMC-TLV-E2 conversion + if FACE2MODULE.get("tlvbmce2set",0) == 1: + status, msg = test_bmc_channel() + if status == False: + RJPRINT("到BMC通路异常,无法进行BMC-TLV-E2转换,请确认!") + totalerr -= 1 + else: + ret = test_bmc_tlv_e2set(productname) + if ret[RETURN_KEY1] < 0: + totalerr -= 1 + + # BMC-FRU-E2 conversion + if FACE2MODULE.get("frubmce2set",0) == 1: + status, msg = test_bmc_channel() + if status == False: + RJPRINT("到BMC通路异常,无法进行BMC-FRU-E2转换,请确认!") + totalerr -= 1 + else: + ret = test_bmc_fru_e2set(productname) + if ret[RETURN_KEY1] < 0: + totalerr -= 1 + + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +# Product E2 conversion main program +if __name__ == '__main__': + root_check() + # fac_setmac_check() # setmac first check + log_info("产品E2转换主程序") + start() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/facfwupdate b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/facfwupdate new file mode 100644 index 000000000000..cd916e554154 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/facfwupdate @@ -0,0 +1,1188 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +import os +import sys +import signal +import time +import threading +import hashlib +import re +import datetime +import syslog +import fcntl +import logging +import subprocess +import json +import unicodedata +import tty +import glob +from tabulate import tabulate +from faclib.all import * +import pexpect +from faclib.util.rest import HttpRest + +from rjutil.baseutil import get_machine_info +from rjutil.baseutil import get_platform_info + +MAILBOX_DIR = "/sys/bus/i2c/devices/" # sysfs Top-level directory + + +def getdeviceplatform(): + x = get_platform_info(get_machine_info()) + if x != None: + filepath = "/usr/share/sonic/device/" + x + return filepath + +platform = get_platform_info(get_machine_info()) # platform Obtaining platform information x86_64-ragile_b6520-64cq-r0 +platformpath = getdeviceplatform() # platformpath Gets the mapable Docker directory /usr/share/sonic/device/x86_64-ragile_b6520-64cq-r0 +grtd_productfile = (platform + "_fwupdate_config").replace("-","_") +configfile_pre = "/usr/local/bin/" # py path +import sys +sys.path.append(platformpath) +sys.path.append(configfile_pre) + +global module_product +if os.path.exists(configfile_pre + grtd_productfile + ".py"): + module_product = __import__(grtd_productfile, globals(), locals(), [], -1) +else: + print ("不存在配置文件,退出") + exit(-1) + + +def get_var(name): + global module_product + var_name = "module_product." + name + try : + var_value = eval(var_name) + except: + var_value = None + return var_value + +menuList = get_var("menuList") +STARTMENUID = get_var("STARTMENUID") +TESTCASE = get_var("TESTCASE") +CPLDVERSIONS = get_var("CPLDVERSIONS") + +SUCCESS_TIPS = "PASS" +RETURN_KEY1 = "code" +RETURN_KEY2 = "msg" +ERROR_RETURN = {RETURN_KEY1 : -1, RETURN_KEY2 : "init error"} +SUCCESS_RETURN = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} +ERROR_RETURN_DETAIL = {RETURN_KEY1 : -1, RETURN_KEY2 : []} + +MENUID = "menuid" +MENUPARENT = "parentid" +MENUVALUE = "value" +CHILDID = "childid" +MENUITEMNAME = "name" +MENUITEMDEAL = "deal" +GOBACK = "goBack" +GOQUIT = "quit" +ITEMBEFORE = 'before' +ITEMAFTER = 'after' + +listindex=['1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'] +formatStringLevel1 = "%s.%s" +SYSINFOTIPS_FORMAT = "%30s : %s" + +SYSLOG_IDENTIFIER = "FWUPDATE" +OPENBMC_PASSWORD = "0penBmc" +g_info_tmp = "" + +# Signal processing: No processing ctrl + N +def sigint_handler(signum, frame): + RJPRINT("\n\n不接收ctrl+c退出") + +signal.signal(signal.SIGINT, sigint_handler) +signal.signal(signal.SIGHUP, sigint_handler) +signal.signal(signal.SIGTERM, sigint_handler) + +def log_info(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + if also_print_to_console: + click.echo(msg) + +def log_debug(msg, also_print_to_console=False): + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + except Exception as e: + pass + +def log_warning(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +def log_error(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +def print_temp(str,cache = True): + if cache: + global g_info_tmp + g_info_tmp += str+"\n" + else: + print (str) + +def print_temp_flush(): + global g_info_tmp + if g_info_tmp != "": + print (g_info_tmp) + g_info_tmp = "" + +def print_clean(): + global g_info_tmp + g_info_tmp = "" + +def test_tbd(): + RJPRINT("待实现") + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + return RET + +def quit(): + sys.exit(0) + +def RJPRINTLINE(x): + '''Keep the function and adapt later 3.x''' + print (x,) + +def RJPRINT(x,newline = True): + '''Keep the function and adapt later 3.x''' + if newline == True: + print (x) + else: + print (x,) + +def RJPRINTERR(str): + print("\033[0;31m%s\033[0m" % str) + +def getRealUrl(case, param=None): + http = TESTCASE.get('BMC').get('requesthttp') + realurl = "" + if param is None: + realurl = "%scase=%s" %(http, case) + else: + realurl = "%scase=%s¶m=%s"% (http, case, param) + return realurl + +def test_bmc_func(func,param=None,timeout=80): + if param is None: + ret = HttpRest().Get(getRealUrl(func),timeout) + else: + ret = HttpRest().Get(getRealUrl(func,json.dumps(param)),timeout) + return ret + +def test_bmc_channel(): + '''Testing the BMC Path''' + ip = TESTCASE.get('BMC').get('ip') + port = TESTCASE.get('BMC').get('port') + msg = '' + returncode = False + import socket + sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sk.settimeout(5) + try: + sk.connect((ip,port)) + returncode = True + except Exception: + msg = '到BMC通路失败,请确认' + returncode = False + sk.close() + return returncode, msg + +def test_bmc_testcase(param_t): + ret = test_bmc_func(param_t) + RJPRINT(ret.get(RETURN_KEY2)) + return ret + + +# Menu Prints a menu item with a numeric prompt in front +def printList(_list, id): + try: + RJPRINT("****************************************") + for index in range(len(_list)): + RJPRINT(formatStringLevel1 %( listindex[index] , _list[index]["name"])) + if id != STARTMENUID: + RJPRINT("q.返回上一层") + else: + RJPRINT("q.退出") + RJPRINT("****************************************") + except Exception as e: + log_error(e) + sys.exit(-1) + +# Menu: Single test +def test_signal(id): + startMenu(id) + +def dealfunc(func): + msg = "" + for i in range(0, 3): + ret, msg = func() + if ret == True: + return True + else: + continue + raise Exception(msg) + return False + + +def dealchoosefunc(list): + '''Real menu processing items''' + RET = ERROR_RETURN + funcbefore = None + functest = None + funcafter = None + param_tt = None + param_val = None + funcbeforestr = list.get(ITEMBEFORE, None) + functeststr = list.get(MENUITEMDEAL, None) + funcafterstr = list.get(ITEMAFTER, None) + param_tt = list.get(CHILDID, None) + param_val = list.get('param', None) + + if funcbeforestr is not None: + funcbefore = eval(funcbeforestr) + if functeststr is not None: + functest = eval(functeststr) + if funcafterstr is not None: + funcafter = eval(funcafterstr) + try: + if funcbefore is not None: + log_debug(" 测试项前置:%s " % (funcbefore)) + dealfunc(funcbefore) + if functest is not None: + log_debug(" 测试项 :%s " % (functest)) + if param_tt is not None: + RET = functest(param_tt) + else: + if param_val is not None: + RET = functest(param_val) + else: + RET = functest() + else: + raise Exception("fun test is none") + + except Exception as e: + RJPRINT(e) + RJPRINT("error\n\n") + finally: + if funcafter is not None: + log_debug(" 测试项后置:%s " % (funcafter)) + for i in range(0, 3): + if funcafter() == True: + break + else: + continue + return RET + +def getch(msg): + ret = "" + fd = sys.stdin.fileno() + old_ttyinfo = termios.tcgetattr(fd) + new_ttyinfo = old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + sys.stdout.write(msg) + sys.stdout.flush() + try: + termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo) + ret = os.read(fd, 1) + finally: + # print "try to setting" + termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo) + return ret + +# Menu to print +# printMenu +# param: list_t Menu item list +# id Menu id + +def printMenu(list_t, id): + while True: + try: + printList(list_t, id) + test = "请选择:" + str= getch(test) + RJPRINT(" %s" % str) + log_debug("选择:%s" % str) + str = str.lstrip().lower() + if str == "q": + if id == STARTMENUID: # Top level directory. There's no way back + quit() + else: + break + if str not in listindex: + log_debug("%s 不在菜单项中" % str); + RJPRINT("\n\n") + continue + else: + RJPRINT("=======================> %s <======================="%list_t[listindex.index(str)][MENUITEMNAME]) + log_debug("选择的测试项为:%s id:%d" % (list_t[listindex.index(str)][MENUITEMNAME], id)) + + RET = dealchoosefunc(list_t[listindex.index(str)]) + if RET == None: + RJPRINT("\n\n") + continue + RJPRINT(" ") + if RET[RETURN_KEY1] == 0: + RJPRINT("Test Result: Pass") + log_debug("菜单测试结果:" + SUCCESS_TIPS) + elif RET[RETURN_KEY1] == 1: + pass + else: + RJPRINT("Test Result: Fail") + log_debug("[%s]测试结果:" % list_t[listindex.index(str)][MENUITEMNAME] + 'error') + RJPRINT("\n\n") + except IndexError as d: + RJPRINT("\n\n非法输入\n\n") + except Exception as e: + RJPRINT(e) + # log_debug(e) + RJPRINTERR("\n\n 异常\n\n" ) + +def getMenuFromList(list, id): + for key in list: + if key[MENUID] == id: + return key[MENUVALUE],True + return 0, False + +def getParentIdMenuFromList(list, id): + for key in list: + if key[MENUID] == id: + return key[MENUPARENT],True + return -1, False + +# Get the menu by ID +def startMenu(id): + list,code = getMenuFromList(menuList, id) + if code == False: + log_error("错误的文件结构") + RJPRINT("无此菜单,请确认") + sys.exit(1) + log_debug("根据ID获取到相应的菜单列表") + printMenu(list, id) + +# start +def start(): + global STARTMENUID + if STARTMENUID is None: + STARTMENUID = 0 + startMenu(STARTMENUID) + +def usb0_init(): + '''Set the IP address of USB0''' + usbip = TESTCASE.get("SONIC",{}).get("ip","1.1.1.1") + cmd = "ifconfig usb0 %s netmask 255.255.255.0" % usbip + ret,log = log_os_system(cmd, 0) + if ret or "ERROR" in log: + return False + return True + +def fac_init_check_ipmi(): + if not os.path.exists("/dev/ipmi0"): + ret, log = log_os_system("rmmod ipmi_watchdog; rmmod ipmi_si; modprobe ipmi_msghandler; modprobe ipmi_si trydefaults=1 tryacpi=1;modprobe ipmi_devintf", 0) + if not os.path.exists("/dev/ipmi0"): + msg =" 无/dev/ipmi0设备,请检查" + RJPRINT(msg) + return False + return True + +# ==================================== +# Executing shell commands +# ==================================== +def log_os_system(cmd, show): + status, output = subprocess.getstatusoutput(cmd) + if status: + log_error('Failed :'+cmd) + if show: + RJPRINT('Failed :'+ cmd) + return status, output + +def root_check(): + if os.geteuid() != 0: + click.echo("请在Root权限下执行!") + sys.exit(1) + +def get_raw_input(): + ret="" + fd=sys.stdin.fileno() + old_ttyinfo=termios.tcgetattr(fd) + new_ttyinfo=old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + try: + termios.tcsetattr(fd,termios.TCSANOW,new_ttyinfo) + ret=raw_input("") + except Exception as e: + print (e) + finally: + termios.tcsetattr(fd,termios.TCSANOW,old_ttyinfo) + return ret + +# Compare strings regardless of size +def astrcmp(str1,str2): + return str1.lower()==str2.lower() + +def makesure(info, default = True ,echo = False): + while True: + print (info,) + if echo: + str = raw_input() + else: + str = get_raw_input() + if astrcmp(str, ""): + return default + if astrcmp(str, "y") or astrcmp(str, "ye") or astrcmp(str, "yes"): + return True + elif astrcmp(str, "n") or astrcmp(str, "no"): + return False + else: + RJPRINT("输入无效,请重新输入,") + +def password_command(cmd, password, exec_timeout=30): + + newkey = 'continue connecting' + log_os_system("rm -rf ~/.ssh", 0) + msg = "" + try_times = 3 + try_times_conter = try_times + while try_times_conter: + child = pexpect.spawn(cmd) + if try_times != try_times_conter: + time.sleep(5) + try_times_conter -= 1 + try: + i = child.expect([pexpect.TIMEOUT, newkey, 'password: ',"refused",pexpect.EOF],timeout=30) + # If the login times out, print an error message and exit. + if i == 0: # Timeout + msg = '与BMC连接超时' + continue + # no public key + if i == 1: + child.sendline ('yes') + i = child.expect([pexpect.TIMEOUT, 'password: '],timeout=30) + if i == 0: # Timeout + msg = '与BMC连接超时' + continue + if i == 1:# Go below and enter the logic of the password + i = 2 + if i == 2: # Enter the password + child.sendline (password) + i = child.expect([pexpect.EOF, pexpect.TIMEOUT], exec_timeout) + if i == 0: + return True,child.before + if i == 1: + msg = str(child.before)+"\nBMC执行命令超时" + return False,msg + if i == 3: # BMC rejects connection + msg = '连接BMC失败' + continue + if i == 4: + msg = child.before + except Exception as e: + msg = str(child.before)+"\n连接BMC失败" + + return False,msg + +def getfilevalue(location): + try: + with open(location, 'r') as fd: + value = fd.read() + return True, value.strip() + except Exception as e: + return False, "error" + +def searchDirByName(name, dir): + result = [] + try: + files = os.listdir(dir) + for file in files: + if name in file: + result.append(os.path.join(dir, file)) + except Exception as e: + pass + return result + +def getUsbLocation(): + dir = "/sys/block/" + spect = "sd" + usbpath = "" + result = searchDirByName(spect, dir) + if len(result) <= 0: + return False + for item in result: + with open(os.path.join(item, "removable"), 'r') as fd: + value = fd.read() + if value.strip() == "1": # USB flash drive is found + usbpath = item + break + if usbpath == "": # No flash drive was found + log_debug("no usb found") + return False, usbpath + return True, usbpath + +def getusbinfo(): + ret, path = getUsbLocation() + if ret == False: + return False, "not usb exists" + str = os.path.join(path, "size") + ret, value = getfilevalue(str) + if ret == True: + return True, {"id": os.path.basename(path), "size": float(value) * 512 / 1024 / 1024 / 1024} + else: + return False, "Err" + +def mount_usb(print_cached = False): + totalerr = 0 + errmsg = "" + usb_mount_file = "/tmp/usb" + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret , info = getusbinfo(); + if ret == False: + RJPRINT("读取USB信息失败") + RET[RETURN_KEY1] = -1 + return RET + + print_clean() + RET["already_mount"] = False + RET["mount_dir"] = None + + usb_dev = info["id"] + cmd = "fdisk -l |grep '%s'|grep 'Disk' -v|sort -k4 |tail -n1|awk '{print $1;}'"%usb_dev + ret, usb_disk = log_os_system(cmd,0) + cmd = "df -h 2>/dev/null|grep " + usb_disk + ret, usb_already_mount_file = log_os_system(cmd,0) + + if "/" in usb_already_mount_file: + RET["already_mount"] = True + RET["mount_dir"] = re.split("\s+",usb_already_mount_file)[-1] + return RET + + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + if not os.path.exists(usb_mount_file): + ret, log = log_os_system("mkdir %s && mount %s %s"%(usb_mount_file, usb_disk, usb_mount_file), 0) + else: + ret, log = log_os_system("mount %s %s"%(usb_disk, usb_mount_file), 0) + if ret != 0 or len(log) > 0: + print_temp(log,print_cached) + print_temp("挂载U盘 FAILED",print_cached) + RET[RETURN_KEY1] = -1 + return RET + RET["mount_dir"] = usb_mount_file + return RET + +def bin_pre_process(image_to_upgrade_rerules,remote = False,bin_dir = None): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + if bin_dir == None: + RET = mount_usb() + if RET[RETURN_KEY1] == -1: + return RET + bin_dir = RET["mount_dir"] + + image_to_use = None + cmd = "ls %s |grep -E '%s'"%(bin_dir,image_to_upgrade_rerules) + + ret, image_msg = log_os_system(cmd,0) + if ret != 0 and len(image_msg) != 0: + print("执行指令 %s 出错:%s"%(cmd,image_msg)) + RET[RETURN_KEY1] = -2 + return RET + if len(image_msg) == 0: + print ("没有找到符合命名规则(%s)的升级文件"%image_to_upgrade_rerules) + RET[RETURN_KEY1] = -3 + return RET + + image_list = image_msg.split("\n") + image_to_use = sorted(image_list,reverse=True)[0] + + image_list_len = len(image_list) + if image_list_len != 1: + print ("检测到多个升级文件,选择升级最新版本") + print ("升级文件:%s"%image_to_use) + RET["bin_dir"] = bin_dir + RET["image_to_use"] = image_to_use + if remote: + bmcip = TESTCASE.get("BMC",{}).get("ip","1.1.1.2") + cmd = 'scp -r %s/%s root@%s:/tmp'%(bin_dir,image_to_use,bmcip) + ret, log = password_command(cmd,OPENBMC_PASSWORD,200) + if ret and "100%" in log: + RET["bin_name"] = "/tmp/"+image_to_use + return RET + else: + print (log) + print ("传输bin文件失败") + RET[RETURN_KEY1] = -4 + return RET + else: + RET["bin_name"] = bin_dir+'/'+image_to_use + return RET + +def test_bmc_image_update(bmc_info): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + if makesure("升级BMC将导致BMC重启,是否继续?[Yes/No]:",True,echo = True): + RET = bin_pre_process(TESTCASE["UPGRADE_CASE"]["bmc_regexp"],False) + if RET[RETURN_KEY1] == -1: + return RET + cmd = "cp %s /tmp/image-bmc"%(RET["bin_name"]) + ret, image_msg = log_os_system(cmd,0) + if ret != 0 and len(image_msg) != 0: + RJPRINT("执行指令 %s 出错:%s"%(cmd,image_msg)) + RET[RETURN_KEY1] = -1 + return RET + cmd = "which upgrade-bmc-bios.sh" + ret, log = log_os_system(cmd,0) + if ret or len(log) == 0: + RJPRINT("未找到BMC升级脚本") + RET[RETURN_KEY1] = -1 + return RET + cmdstr="%s upgrade bmc /tmp/image-bmc %s erase" % (log,bmc_info) + RJPRINT("BMC升级中,请等待...") + successtips="succeeded to upgrade" + log_debug(cmdstr) + # os.system(cmdstr) + ret1, status = log_os_system(cmdstr,0) + log_debug(status) + if ret1 == 0 and successtips in status: + RJPRINT("BMC 升级成功,等待BMC重启...") + else: + RJPRINT("BMC 升级失败!") + RET[RETURN_KEY1] = -1 + return RET + # BMC upgrade will restart the BMC, and you need to reconfigure the USB0 IP address on the X86 terminal + # time.sleep(90) Instead, restart and upgrade without waiting. + ret_t = usb0_init() + timeout = TESTCASE.get("SONIC",{}).get("timeout",120) + while timeout > 0: + if ret_t == False: + ret_t = usb0_init() + status,msg = test_bmc_channel() + if status == True: + break + time.sleep(2) + timeout -= 2 + if timeout < 0: + RJPRINT(msg) + RET[RETURN_KEY1] = -1 + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + +def test_bmc_update_bcm5387(): + RET = {RETURN_KEY1 : 0 ,RETURN_KEY2 : ""} + if makesure("确认升级BCM5387?[Yes/No]:",True,echo = True): + tmp = TESTCASE.get("UPGRADE_CASE",{}).get("bcm5387", None) + if tmp == None: + RJPRINT("无BCM5387升级配置") + RET[RETURN_KEY1] = 1 + return RET + upgrade_file = tmp.get("upgrade_file", None) + if upgrade_file == None: + RJPRINT("无BCM5387升级文件信息") + RET[RETURN_KEY1] = 1 + return RET + RET = bin_pre_process(upgrade_file,True) + if RET[RETURN_KEY1] == -1: + return RET + bcm5387 = RET["bin_name"] + func = 'bmc_log_os_system' + url = tmp.get("url", None) + if url == None: + RJPRINT("无BCM5387升级路径") + RET[RETURN_KEY1] = 1 + return RET + cmd = "cat %s > /sys/bus/spi/devices/%s/eeprom " % (bcm5387, url) + log_debug(cmd) + ret = test_bmc_func(func, cmd) + if ret.get(RETURN_KEY1) != 0: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "BCM5387升级失败\nmessage:%s" % (ret.get(RETURN_KEY2)) + else: + RJPRINT("BCM5387升级成功") + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + +def test_bmc_image_update_master(): + return test_bmc_image_update("master") + +def test_bmc_image_update_slave(): + return test_bmc_image_update("slave") + +def test_bmc_image_update_both(): + return test_bmc_image_update("both") + +def test_bios_image_update(bios_info): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + if makesure("确认升级BIOS?[Yes/No]:",True,echo = True): + RET = bin_pre_process(TESTCASE["UPGRADE_CASE"]["bios_regexp"],False) + if RET[RETURN_KEY1] == -1: + return RET + bios_image = RET["bin_name"] + cmd = "which upgrade-bmc-bios.sh" + ret, log = log_os_system(cmd,0) + if ret or len(log) == 0: + RJPRINT("未找到BIOS升级脚本") + RET[RETURN_KEY1] = -1 + return RET + cmdstr="%s upgrade bios %s %s" % (log,bios_image,bios_info) + RJPRINT("BIOS升级中,请等待...") + successtips="upgrade success" + log_debug(cmdstr) + # os.system(cmdstr) + ret1, status = log_os_system(cmdstr,0) + log_debug(status) + if ret1 == 0 and successtips in status: + if bios_info == "master": + RJPRINT("主BIOS 升级成功,需要从主BIOS启动,获取更新后的BIOS版本") + elif bios_info == "slave": + RJPRINT("备BIOS 升级成功,需要从备BIOS启动,获取更新后的BIOS版本") + else: + RJPRINT("主备BIOS 升级成功,需要主备BIOS切换一次,获取更新后的BIOS版本") + else: + RJPRINT("BIOS 升级失败!") + RET[RETURN_KEY1] = -1 + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + +def test_bios_image_update_by_cpu(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + if makesure("确认升级BIOS?[Yes/No]:",True,echo = True): + RET = bin_pre_process(TESTCASE["UPGRADE_CASE"]["bios_regexp"],False) + if RET[RETURN_KEY1] == -1: + return RET + bios_image = RET["bin_name"] + RET = bin_pre_process(TESTCASE["BIOS_UPDATE_TOOL"],False) + if RET[RETURN_KEY1] == -1: + return RET + bios_afulnx = RET["bin_name"] + + cmd_mod = "chmod 755 %s" % bios_afulnx + ret, log = log_os_system(cmd_mod,0) + if ret != 0: + return {RETURN_KEY1: -1, RETURN_KEY2: log} + + cmd="%s %s /P /B /N /L /K"%(bios_afulnx,bios_image) + RJPRINT("BIOS升级中,请等待...") + successtips="Verifying RomHole Block ..... done" + log_debug(cmd) + ret1, status = log_os_system(cmd,0) + log_debug(status) + if ret1 == 0 and successtips in status: + RJPRINT("BIOS 升级成功,需要系统重启,获取更新后的BIOS版本") + else: + RJPRINT("BIOS 升级失败!") + RET[RETURN_KEY1] = -1 + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + +def test_bios_image_update_master(): + return test_bios_image_update("master") + +def test_bios_image_update_slave(): + return test_bios_image_update("slave") + +def test_bios_image_update_both(): + return test_bios_image_update("both") + +def test_update_fpga_image(remote = False): + RET = {RETURN_KEY1 : 0 ,RETURN_KEY2 : ""} + if makesure("确认升级FPGA?[Yes/No]:",True,echo = True): + fpga_package=TESTCASE.get("UPGRADE_CASE",{}).get("fpga_regexp") + if fpga_package == None: + RJPRINT("无FPGA升级配置信息") + RET[RETURN_KEY1] = 1 + return RET + if isinstance(fpga_package, dict): + fpath = fpga_package.get("file") + if not os.path.exists(fpath): + RJPRINT("产品识别文件:%s, 不存在,请先执行facinit" % fpath) + RET[RETURN_KEY1] = -1 + return RET + with open(fpath,'r') as fd: + ret = fd.read() + fpga_package = fpga_package.get(ret) + for item in fpga_package: + RJPRINT("================= %s ===============" % item.get("name")) + tmp_fpga_regexp = item.get("image") + RJPRINT("查找规则(%s)的文件" % tmp_fpga_regexp) + RET_BIN = bin_pre_process(tmp_fpga_regexp,remote) + if RET_BIN[RETURN_KEY1] == -1: # USB flash drive is not inserted or is abnormally mounted + RET[RETURN_KEY1] = -1 + return RET + if RET_BIN[RETURN_KEY1] < 0: + RET[RETURN_KEY1] = -1 + continue + upgrade_name=RET_BIN["bin_name"] + slotlist = item.get("slot") + successtips="FPGA Upgrade succeeded!" + for slot in slotlist: + if item.get("displayname") is not None: + message = item.get("displayname") % slot + else: + message = item.get("name") + RJPRINT("%s 升级中,请等待..." % message) + if remote == False: # X86 upgrade fpga + ret, log = log_os_system("which firmware_upgrade ",0) + if ret != 0 or len(log) <= 0: + RJPRINT("未找到升级工具") + return {RETURN_KEY1:-1, RETURN_KEY2:"Error, can't find firmware_upgrade"} + cmdstr = "%s %s fpga %d fpga"%(log,upgrade_name,slot) + log_debug(cmdstr) + ret1, status = log_os_system(cmdstr,0) + log_debug(status) + if ret1 == 0 and successtips in status: + RJPRINT("%s 升级成功!" % message) + else: + RJPRINT("%s 升级失败!" % message) + RET[RETURN_KEY1] = -1 + else: # BMC upgrade + params = {} + params["slot"] = slot + params["image"] = upgrade_name + ret_t = test_bmc_func("test_bmc_update_fpga_image",params,600) + log_debug(ret_t[RETURN_KEY2]) + if ret_t[RETURN_KEY1] == -2: + RJPRINT("未找到升级工具") + RET[RETURN_KEY1] = ret_t[RETURN_KEY1] + RET[RETURN_KEY2] = ret_t[RETURN_KEY2] + return RET + if ret_t[RETURN_KEY1] == 0: + RJPRINT("%s 升级成功!" % message) + else: + RJPRINT("%s 升级失败!" % message) + RET[RETURN_KEY1] = -1 + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + +def test_update_cpld_image(remote = False): + RET = {RETURN_KEY1 : 0 ,RETURN_KEY2 : ""} + if makesure("确认升级CPLD?[Yes/No]:",True,echo = True): + cpld_package=TESTCASE.get("UPGRADE_CASE",{}).get("cpld_regexp") + if cpld_package == None: + RJPRINT("无CPLD升级配置信息") + RET[RETURN_KEY1] = 1 + return RET + if isinstance(cpld_package, dict): + fpath = cpld_package.get("file") + if not os.path.exists(fpath): + RJPRINT("产品识别文件:%s, 不存在,请先执行facinit" % fpath) + RET[RETURN_KEY1] = -1 + return RET + with open(fpath,'r') as fd: + ret = fd.read() + cpld_package = cpld_package.get(ret) + for item in cpld_package: + RJPRINT("================= %s ===============" % item.get("name")) + tmp_cpld_regexp = item.get("image") + RJPRINT("查找规则(%s)的文件" % tmp_cpld_regexp) + RET_BIN = bin_pre_process(tmp_cpld_regexp,remote) + if RET_BIN[RETURN_KEY1] == -1: # USB flash drive is not inserted or is abnormally mounted + RET[RETURN_KEY1] = -1 + return RET + if RET_BIN[RETURN_KEY1] < 0: + RET[RETURN_KEY1] = -1 + continue + upgrade_name=RET_BIN["bin_name"] + slotlist = item.get("slot") + successtips="CPLD Upgrade succeeded!" + for slot in slotlist: + if item.get("displayname") is not None: + message = item.get("displayname") % slot + else: + message = item.get("name") + RJPRINT("%s 升级中,请等待..." % message) + if remote == False: # X86 upgrade CPLD + ret, log = log_os_system("which firmware_upgrade ",0) + if ret != 0 or len(log) <= 0: + RJPRINT("未找到升级工具") + return {RETURN_KEY1:-1, RETURN_KEY2:"Error, can't find firmware_upgrade"} + cmdstr = "%s %s cpld %d cpld"%(log,upgrade_name,slot) + log_debug(cmdstr) + ret1, status = log_os_system(cmdstr,0) + log_debug(status) + if ret1 == 0 and successtips in status: + RJPRINT("%s 升级成功!" % message) + else: + RJPRINT("%s 升级失败!" % message) + RET[RETURN_KEY1] = -1 + else: # BMC upgrade + params = {} + params["slot"] = slot + params["image"] = upgrade_name + ret_t = test_bmc_func("test_bmc_update_cpld_image",params,600) + log_debug(ret_t[RETURN_KEY2]) + if ret_t[RETURN_KEY1] == -2: + RJPRINT("未找到升级工具") + RET[RETURN_KEY1] = ret_t[RETURN_KEY1] + RET[RETURN_KEY2] = ret_t[RETURN_KEY2] + return RET + if ret_t[RETURN_KEY1] == 0: + RJPRINT("%s 升级成功!" % message) + else: + RJPRINT("%s 升级失败!" % message) + RET[RETURN_KEY1] = -1 + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + + +def test_cpu_update_cpld_image(): + return test_update_cpld_image(remote=False) + +def test_bmc_update_cpld_image(): + return test_update_cpld_image(remote=True) + +def rji2cget(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = log_os_system(command_line,0) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + +def get_bios_info(): + biosstatusdecode = TESTCASE.get("biosstatusdecode",None) + biosstatus = TESTCASE.get("biosstatus",None) + + if biosstatus is None or biosstatusdecode is None: + return None + + if biosstatus["gettype"] == "i2c": + bus = biosstatus["bus"] + loc = biosstatus["loc"] + reg = biosstatus["reg"] + ind, val = rji2cget(bus, loc,reg) + if ind == False: + val = None + else: + io_addr = biosstatus.get('io_addr') + val = io_rd(io_addr) + if val is not None: + bitmask = biosstatus["bitmask"] + val_t = int(val,16) & bitmask + if val_t not in biosstatusdecode.keys(): + return None + return biosstatusdecode.get(val_t,None) + return None + +def test_bios_force_switch(bios_info): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + log = get_bios_info() + + if log == None: + RET[RETURN_KEY1] = -1 + RJPRINT("获取BIOS信息失败") + return RET + elif bios_info in log: + RJPRINT("已是%s,无需切换"%bios_info,False) + RET[RETURN_KEY1] = 0 + return RET + + if bios_info == "master": + switch_mod = 0 + else: + switch_mod = 1 + + if makesure("切换BIOS会导致X86重启,是否继续?[Yes/No]:",True,echo = True): + func = "test_bmc_bios_switch" + ret = test_bmc_func(func,switch_mod) + return ret + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + +def test_bios_force_switch_slave(): + return test_bios_force_switch("slave") + +def test_bios_force_switch_master(): + return test_bios_force_switch("master") + +def test_bmc_image_force_switch(bmc_info): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + RET = test_bmc_func("bmc_get_flash") + status = False + timeout = TESTCASE.get("SONIC",{}).get("timeout",120) + if RET[RETURN_KEY1]: + RJPRINT(RET[RETURN_KEY2]) + return RET + if bmc_info in RET[RETURN_KEY2]: + RJPRINT("已是%s,无需切换"%bmc_info) + RET[RETURN_KEY1] = 0 + return RET + if makesure("切换会导致BMC重启,是否继续?[Yes/No]:",False,echo = True): + RJPRINT("执行切换中,请等待约90s...") + path = getRealUrl("bmc_test_switch") + cmd = "curl -m 90 %s" % path + ret, log =log_os_system(cmd, 0) + if "timed out" not in log: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "强制切换BMC失败" + return RET + RJPRINT("已成功执行切换操作") + # After the BMC switchover, the USB0 IP address on the X86 terminal will be lost and needs to be reconfigured + ret_t = usb0_init() + while timeout > 0: + if ret_t == False: + ret_t = usb0_init() + status,msg = test_bmc_channel() + if status == True: + break + time.sleep(2) + timeout -= 2 + if timeout < 0: + RJPRINT(msg) + RET[RETURN_KEY1] = -1 + else: + RJPRINT("已撤销") + RET[RETURN_KEY1] = 1 + return RET + +def test_bmc_image_force_switch_master(): + return test_bmc_image_force_switch("master") + +def test_bmc_image_force_switch_slave(): + return test_bmc_image_force_switch("slave") + +def test_bios_flash(): + '''Verify this by reading the active and standby BIOS versions''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : "","master":"","slave":""} + file_path = TESTCASE.get("BIOS_INFO",None) + if file_path == None: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "No BIOS flash test case." + return RET + try: + with open(file_path, 'r') as fd: + log = fd.read().strip() + # RJPRINT(log) + if "master" not in log.lower() or "slave" not in log.lower(): + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "No master/slave BIOS version!" + return RET + version = log.split("\n",1) + for version_item in version: + bios_version = version_item.split(":",1) + if len(bios_version) != 2 or len(bios_version[1].strip()) == 0: + RET[RETURN_KEY1] -= 1 + if "master" in bios_version[0]: + RET[RETURN_KEY2] += "master BIOS version read error!\n" + else: + RET[RETURN_KEY2] += "slave BIOS version read error!\n" + continue + if "master" in bios_version[0]: + RET["master"] = bios_version[1].strip() + else: + RET["slave"] = bios_version[1].strip() + except Exception as error: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(error) + return RET + +def test_bios_version(): + RET = test_bios_flash() + RJPRINT("%-21s: %s" % ('主BIOS版本',"%s"%(RET["master"]))) + RJPRINT("%-21s: %s" % ('备BIOS版本',"%s"%(RET["slave"]))) + log = get_bios_info() + RJPRINT("%-20s: %s" % ('当前BIOS',"%s"%(log))) + return RET + +def io_rd(reg_addr, len =1): + '''io read''' + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str = os.read(fd, len) + return "".join(["%02x"% ord(item) for item in str]) + except ValueError: + return None + except Exception as e: + print (e) + return None + finally: + os.close(fd) + return None + +def get_cpld_version(): + result = [] + totalerr = 0 + for cpld in CPLDVERSIONS: + dict = {} + gettype = cpld.get("gettype",None) + bus = cpld.get("bus",None) + devno = cpld.get("devno",None) + url = cpld.get("url",None) + io_addr = cpld.get("io_addr",None) + data = "" + t = True + ret = None + if gettype == "io": + for i in range(4): + ret = io_rd(io_addr + i) + if ret == None: + t = False + break; + data += chr(int(ret,16)) + else: + for i in range(4): + ind, ret = rji2cget(bus, devno, i) + if ind == False: + t = False + break; + data += chr(int(ret,16)) + if data == "": + totalerr -= 1 + result.append([ cpld.get('name',None),"NA","NA" ]) + else: + result.append([ cpld.get('name',None),"%02x%02x%02x" % (ord(data[1]) ,ord(data[2]) ,ord(data[3])),"%02x" % (ord(data[0]))]) + return totalerr,result + +def test_cpld_version(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ind, val = get_cpld_version() + for item in val: + formatstr = " %-20s: %s%s" + RJPRINT(formatstr%(item[0],item[2],item[1])) + RET[RETURN_KEY1] = ind + return RET + +# Firmware upgrade main program +if __name__ == '__main__': + root_check() + fac_init_check_ipmi() + usb0_init() + log_info("固件升级主程序") + start() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/factest b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/factest new file mode 100644 index 000000000000..52120e540353 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/factest @@ -0,0 +1,7128 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +import os +import sys +import signal +import time +import threading +import xml.etree.ElementTree as ET +import hashlib +import re +import datetime +import syslog +import fcntl +import logging +import subprocess +import json +import unicodedata +import tty +import glob +import mmap +from tabulate import tabulate +import traceback +from faclib.all import * + +MAILBOX_DIR = "/sys/bus/i2c/devices/" # sysfs Top-level directory +PORTS_DIR = "/sys/class/net/" +from scapy.all import sendp, Ether, ARP +# from monitor import status +import ConfigParser + +GRTD_BROADCAST_RETRY_SLEEP_TIME = 3 +''' +from ragileutil import * +import grtd_test as gt +from tabulate import tabulate +from faclib.rest import HttpRest + +fan_check = gt.fan_check +get_sysfs_value = gt.get_sysfs_value +test_port = gt.test_port +test_port_prbs = gt.test_port_prbs +test_port_portframe = gt.test_port_portframe +stopFanctrol = gt.stopFanctrol +startFanctrol = gt.startFanctrol +test_ports_prbs_new = gt.test_ports_prbs_new +''' +def upper_input(tips): + sys.stdout.write(tips) + sys.stdout.flush() + passwd = [] + while True: + ch = getrawch().upper() + if ch == "\r" or ch == "\n": + print + tmp = "".join(passwd) + ret_t = tmp.strip().strip(b'\x00'.decode()) + return str(ret_t) + elif ch == '\b' or ord(ch) == 127: + if passwd: + del passwd[-1] + sys.stdout.write('\b \b') + else: + sys.stdout.write(ch) + passwd.append(ch) + +def getrawch(): + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + +TLV_INFO_ID_STRING = "TlvInfo\x00" +TLV_INFO_VERSION = 0x01 +TLV_INFO_LENGTH = 0x00 +TLV_INFO_LENGTH_VALUE = 0xba + + +def getTLV_BODY(type, productname): + x = [] + temp_t = "" + if type == TLV_CODE_MAC_BASE: + arr = productname.split(':') + for tt in arr: + temp_t += chr(int(tt, 16)) + elif type == TLV_CODE_DEVICE_VERSION: + temp_t = chr(productname) + elif type == TLV_CODE_MAC_SIZE: + temp_t = chr(productname >> 8) + chr(productname & 0x00ff) + else: + temp_t = productname + x.append(chr(type)) + x.append(chr(len(temp_t))) + for i in temp_t: + x.append(i) + return x + +def _crc32(v): + return '0x%08x' % (binascii.crc32(v) & 0xffffffff) # Take the octet data %x of CRC32 to return hexadecimal + + +def util_setmac(eth, mac): + rulefile = "/etc/udev/rules.d/70-persistent-net.rules" + if isValidMac(mac) == False: + return False, "MAC非法" + cmd = "ethtool -e %s | grep 0x0010 | awk '{print \"0x\"$13$12$15$14}'" % eth + ret, log = rj_os_system(cmd) + log_debug(log) + magic = "" + if ret == 0 and len(log): + magic = log + macs = mac.upper().split(":") + + # Temporarily change the local ETH0 to the value after setMAC + ifconfigcmd = "ifconfig %s hw ether %s" % (eth,mac) + log_debug(ifconfigcmd) + ret, status = rj_os_system(ifconfigcmd) + if ret: + raise SETMACException("软件设置网卡MAC出错") + if ret: + return False + index = 0 + for item in macs: + cmd = "ethtool -E %s magic %s offset %d value 0x%s" % ( + eth, magic, index, item) + log_debug(cmd) + index += 1 + ret, log = rj_os_system(cmd) + if ret != 0: + raise SETMACException("设置硬件网卡MAC出错") + return False + # Gets the return value of the setting + cmd_t = "ethtool -e %s offset 0 length 6" % eth + ret, log = rj_os_system(cmd_t) + m = re.split(':', log)[-1].strip().upper() + mac_result = m.upper().split(" ") + + for ind, s in enumerate(macs): + if s != mac_result[ind]: + RJPRINTERR("MAC比较出错") + if os.path.exists(rulefile): + os.remove(rulefile) # Delete the file + print ("MGMT MAC【%s】" % mac) + return True + +def test_bmc_i2c_open(): + switch_ctrol = TESTCASE.get("switchcontrol",None) + if switch_ctrol is None: + return True, "" + if switch_ctrol.get('needopen') != 0: + test_stop_fanctrol() + time.sleep(1) + for item in switch_ctrol.get('switchctrl',[]): + if item.get('gettype') == 'io': + addr = item.get('io_addr') + val = item.get('switchbmc') + io_wr(addr, val) + else: + # maybe i2c + pass + return True,"" + +def test_bmc_i2c_close(): + switch_ctrol = TESTCASE.get("switchcontrol",None) + if switch_ctrol is None: + return True, "" + if switch_ctrol.get('needopen') != 0: + for item in switch_ctrol.get('switchctrl',[]): + if item.get('gettype') == 'io': + addr = item.get('io_addr') + val = item.get('switchcpu') + io_wr(addr, val) + else: + # maybe i2c + pass + test_start_fanctrol() + return True,"" + +def writeToBMCEEprom(rst_arr, loc, ep_param): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + params = {} + try: + params["value"] = [] + params["loc"] = loc + params.update(ep_param) + for item in rst_arr: # Item is a character, converted to ASCII + params["value"].append(ord(item)) + func = "test_bmc_write_eeprom" + RET = test_bmc_func(func,params) + if RET[RETURN_KEY1] < 0: + return RET + except Exception as e: + RET[RETURN_KEY2] = str(e) + RET[RETURN_KEY1] = -1 + return RET + +def sync_bmc_tlv_e2(rst_arr): + tmp = TESTCASE.get('bmctlve2sync') + if tmp.__contains__("BMC_access") and tmp.get("BMC_access") == 1: # If BMC_access is 1, the E2 synchronization is performed on the BMC + loc = tmp.get('BMC_E2_LOC') + ep_param = tmp.get('BMC_E2_PROTECT') + writeToBMCEEprom(rst_arr, loc, ep_param) + return + e2_protect = tmp.get('BMC_E2_PROTECT',None) + if e2_protect is not None: + dealtype = e2_protect.get('gettype', None) + if dealtype is None: + rji2cset(e2_protect["bus"], e2_protect["devno"], + e2_protect["addr"], e2_protect["open"]) + elif dealtype == "io": + io_wr(e2_protect["io_addr"], e2_protect["open"]) + index = 0 + e2_loc = tmp.get('BMC_E2_LOC',None) + for item in rst_arr: + rji2cset(e2_loc["bus"], e2_loc["devno"], index, ord(item)) + index += 1 + + if e2_protect is not None: + if dealtype is None: + rji2cset(e2_protect["bus"], e2_protect["devno"], + e2_protect["addr"], e2_protect["close"]) + elif dealtype == "io": + io_wr(e2_protect["io_addr"], e2_protect["close"]) + +def writeToEEprom(rst_arr): + dealtype = E2_PROTECT.get('gettype',None) + if dealtype is None: + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["open"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["open"]) + index = 0 + for item in rst_arr: + rji2cset(E2_LOC["bus"], E2_LOC["devno"], index, ord(item)) + index += 1 + if TESTCASE.__contains__('bmctlve2sync'): + sync_bmc_tlv_e2(rst_arr) + func = 'bmc_log_os_system' + cmd = "systemctl restart read-uboot-mac.service" # Modify the BMC eth0 MAC + ret = test_bmc_func(func, cmd) + if ret[RETURN_KEY1] != 0: + RJPRINT("set BMC eth0 fail") + if dealtype is None: + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["close"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["close"]) + # Finally, the system driver is dealt with + os.system("rmmod at24 ") + os.system("modprobe at24 ") + os.system("rm -f /var/cache/sonic/decode-syseeprom/syseeprom_cache") + + +def changeTypeValue(_value, type1, tips, example): + if type1 == TLV_CODE_PRODUCT_NAME: + while True: + print ("请确认 (1)前后进风/(2)后前进风:",) + option = raw_input() + if option == "1": + _value[type1] = example + "-F-RJ" + print ("确认该产品为前后进风设备,产品名称:%s"%_value[type1]) + break + elif option == "2": + _value[type1] = example + "-R-RJ" + print ("确认该产品为后前进风设备,产品名称:%s"%_value[type1]) + break + else: + print ("输入错误,请认真核对") + return True + print ("请输入【%s】如(%s):" % (tips, example),) + name = upper_input("") + if type1 == TLV_CODE_MAC_BASE: + if len(name) != 12: + raise SETMACException("MAC地址长度不对(12位),请认真核对") + return False + release_mac = "" + for i in range(len(name) / 2): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + _value[type1] = release_mac + else: + raise SETMACException("MAC地址非法,请认真核对") + return False + elif type1 == TLV_CODE_DEVICE_VERSION: + if not name.isdigit(): + raise SETMACException("版本号非数字,请认真核对") + elif int(name) > 255: + raise SETMACException("版本号超出范围(0-255),请认真核对") + else: + _value[type1] = int(name) + elif type1 == TLV_CODE_MAC_SIZE: + if name.isdigit(): + _value[type1] = int(name, 16) + else: + raise SETMACException("版本号非数字,请认真核对") + elif type1 == TLV_CODE_SERIAL_NUMBER: + if name.isalnum() == False: + raise SETMACException("序列号非法字符串,请认真核对") + elif len(name) != 13: + raise SETMACException("序列号长度不对(13位),请认真核对") + else: + _value[type1] = name + elif type1 == TLV_CODE_VENDOR_EXT: + _value[type1] = name + else: + _value[type1] = name + return True + + + +class SETMACException(Exception): + def __init__(self, param='错误', errno="-1"): + err = "setmac出错[%s]: %s" % (errno, param) + Exception.__init__(self, err) + self.param = param + self.errno = errno +def getPid(name): + ret = [] + for dirname in os.listdir('/proc'): + if dirname == 'curproc': + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='rb') as fd: + content = fd.read() + except Exception: + continue + if name in content: + ret.append(dirname) + return ret + +def getsysmeminfo_detail(): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t 17 | grep -A21 \"Memory Device\"" # 17 + # 先获取总数 + ret1, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + result_t = log1.split("--") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets + +def getsysbios(): + return getDmiSysByType(0) + +def getDmiSysByType(type_t): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t %s" % type_t + # Get the total first + ret1, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + its = log1.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].strip() + value = it.split(":")[1].strip() + ret[key] = value + return True, ret + + + +def gethwsys(): + return getDmiSysByType(1) + +TLV_CODE_PRODUCT_NAME = 0x21 +TLV_CODE_PART_NUMBER = 0x22 +TLV_CODE_SERIAL_NUMBER = 0x23 +TLV_CODE_MAC_BASE = 0x24 +TLV_CODE_MANUF_DATE = 0x25 +TLV_CODE_DEVICE_VERSION = 0x26 +TLV_CODE_LABEL_REVISION = 0x27 +TLV_CODE_PLATFORM_NAME = 0x28 +TLV_CODE_ONIE_VERSION = 0x29 +TLV_CODE_MAC_SIZE = 0x2A +TLV_CODE_MANUF_NAME = 0x2B +TLV_CODE_MANUF_COUNTRY = 0x2C +TLV_CODE_VENDOR_NAME = 0x2D +TLV_CODE_DIAG_VERSION = 0x2E +TLV_CODE_SERVICE_TAG = 0x2F +TLV_CODE_VENDOR_EXT = 0xFD +TLV_CODE_CRC_32 = 0xFE +_TLV_DISPLAY_VENDOR_EXT = 1 +TLV_CODE_RJ_CARID = 0x01 +_TLV_INFO_HDR_LEN = 11 + + + +def decoder(s, t): + if ord(t[0]) == TLV_CODE_PRODUCT_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + elif ord(t[0]) == TLV_CODE_PART_NUMBER: + name = "Part Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERIAL_NUMBER: + name = "Serial Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_BASE: + name = "Base MAC Address" + value = ":".join([binascii.b2a_hex(T) for T in t[2:8]]).upper() + elif ord(t[0]) == TLV_CODE_MANUF_DATE: + name = "Manufacture Date" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DEVICE_VERSION: + name = "Device Version" + value = str(ord(t[2])) + elif ord(t[0]) == TLV_CODE_LABEL_REVISION: + name = "Label Revision" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_PLATFORM_NAME: + name = "Platform Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_ONIE_VERSION: + name = "ONIE Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_SIZE: + name = "MAC Addresses" + value = str((ord(t[2]) << 8) | ord(t[3])) + elif ord(t[0]) == TLV_CODE_MANUF_NAME: + name = "Manufacturer" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MANUF_COUNTRY: + name = "Manufacture Country" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_NAME: + name = "Vendor Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DIAG_VERSION: + name = "Diag Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERVICE_TAG: + name = "Service Tag" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_EXT: + name = "Vendor Extension" + value = "" + if _TLV_DISPLAY_VENDOR_EXT: + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_CRC_32 and len(t) == 6: + name = "CRC-32" + value = "0x%08X" % (((ord(t[2]) << 24) | ( + ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) + elif ord(t[0]) == TLV_CODE_RJ_CARID: + name = "rj_cardid" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + else: + name = "Unknown" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "0x%02X " % (ord(c),) + return {"name": name, "code": ord(t[0]), "value": value} + + +def wide_chars(s): + if isinstance(s, str): + s = s.decode('utf-8') + return sum(unicodedata.east_asian_width(x) in ('F', 'W') for x in s) + +grtdlog_dir= "/var/grtd" +grtdlog_name = grtdlog_dir +"/grtdtest.log" +kjlogmaxshow = 10 + + +def get_pmc_register(reg_name): + retval = 'ERR' + if reg_name[0:4] == "/rif" or reg_name[0:4] == "/ma1" or reg_name[0:4] == "/eth": + mb_reg_file = PORTS_DIR + reg_name + else: + mb_reg_file = MAILBOX_DIR + reg_name + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + try: + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + log_error("Unable to open " + mb_reg_file + "file !") + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + # log_debug(retval) + return retval + + +def get_sysfs_value(location): + pos_t = str(location) + name = get_pmc_register(pos_t) + return name + +def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + + +def get_cpu_info(): + cmd = "cat /proc/cpuinfo |grep processor -A18" # 17 + + ret, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + result_t = log1.split("--") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets + + +def getch(msg): + ret = "" + fd = sys.stdin.fileno() + old_ttyinfo = termios.tcgetattr(fd) + new_ttyinfo = old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + sys.stdout.write(msg) + sys.stdout.flush() + try: + termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo) + ret = os.read(fd, 1) + finally: + # print "try to setting" + termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo) + return ret + +def root_check(): + if os.geteuid() != 0: + click.echo("请在Root权限下执行!") + sys.exit(1) + +if not os.path.exists(grtdlog_dir): + os.makedirs(grtdlog_dir) + +SYSLOG_IDENTIFIER = "FACTEST" + +g_info_tmp = "" +def print_temp(str,cache = True): + if cache: + global g_info_tmp + g_info_tmp += str+"\n" + else: + print (str) + +def print_temp_flush(): + global g_info_tmp + if g_info_tmp != "": + print (g_info_tmp) + g_info_tmp = "" + +def print_clean(): + global g_info_tmp + g_info_tmp = "" + + +def log_info(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + if also_print_to_console: + click.echo(msg) + + +def log_debug(msg, also_print_to_console=False): + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + except Exception as e: + pass + + +def log_warning(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + + +def log_error(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +LOGERROR = False +DEBUG = False +KAOJILOGPATH = "/var/grtd/" +KAOJILOGFILE = KAOJILOGPATH + "kjlog.log" +KAOJISTATUS = 1 +ISKAOJI = 0 +# CONFIG_NAME = "apptest.xml" +RTC_WAIT_TIME = 3 +RTC_THRESHOLD_LOWER = 3 +RTC_THRESHOLD_UPPER = 4 +SUCCESS_TIPS = "PASS" + +RETURN_KEY1 = "code" +RETURN_KEY2 = "msg" +ERROR_RETURN = {RETURN_KEY1 : -1, RETURN_KEY2 : "init error"} +SUCCESS_RETURN = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} +ERROR_RETURN_DETAIL = {RETURN_KEY1 : -1, RETURN_KEY2 : []} + +kj_result =[] +MENUID = "menuid" +MENUPARENT = "parentid" +MENUVALUE = "value" +CHILDID = "childid" +MENUITEMNAME = "name" +MENUITEMDEAL = "deal" +GOBACK = "goBack" +GOQUIT = "quit" +ITEMBEFORE = 'before' +ITEMAFTER = 'after' + +listindex=['1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'] +formatStringLevel1 = "%s.%s" +SYSINFOTIPS_FORMAT = "%30s : %s" +nosetrtc = 1 + +DIAGTEST = False +SAVE_STDOUT = None +INSP_RESULT = "" + +def keep_message(RET, x, newline = True): + if newline == True: + RET[RETURN_KEY2] += (str)(x) + "\n" + else: + RET[RETURN_KEY2] += (str)(x) + +def RJPRINTLINE(x): + '''Keep the function and adapt later 3.x''' + print (x,) + +def RJPRINT(x,newline = True): + '''Keep the function and adapt later 3.x''' + if newline == True: + print (x) + else: + print (x,) + +def force_abort_cpu_stress(): + log_os_system("ps -ef | grep \"stress -c 4\" | grep -v grep | awk '{print $2}' | xargs kill -9 ", 0) + +def quit(): + force_abort_cpu_stress() + force_abort_ddr_stress() + sys.exit(0) + +def test_sys_halt(): + log_os_system("sync", 0) + log_os_system("halt -f", 0) + +def test_sys_reload(): + log_os_system("sync", 0) + log_os_system("reboot -f", 0) + +def getInputValue(title, tips): + print ("请输入【%s】如(%s):" % (title, tips),) + name = raw_input() + return name + +# Backport Python 3.4's regular expression "fullmatch()" to Python 2 +def fullmatch(regex, string, flags=0): + """Emulate python-3.4 re.fullmatch().""" + return re.match("(?:" + regex + r")\Z", string, flags=flags) + +def test_set_rtc(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + time = getInputValue("RTC时间","20180816 11:43:22") + ret = fullmatch("[0-9]{8} [0-9]{2}:[0-9]{2}:[0-9]{2}", time) + if ret: + cmd = "date -s '%s' &&hwclock --systohc" % time + ret, log = rj_os_system(cmd) + else: + RET[RETURN_KEY1] = -1 + RJPRINT("输入错误") + return RET + if ret != 0: + RJPRINTERR("\n\n!!!.设置RTC时间失败\n\n") + return {RETURN_KEY1 : -1, RETURN_KEY2 : []} + systimecmd = "date -R" + ret , log = rj_os_system(systimecmd) + RJPRINT("当前时间: %s" % log) + return RET + +# Menu Prints a menu item with a numeric prompt in front +def printList(_list, id): + try: + RJPRINT("****************************************") + for index in range(len(_list)): + RJPRINT(formatStringLevel1 %( listindex[index] , _list[index]["name"])) + if id != STARTMENUID: + RJPRINT("q.返回上一层") + else: + RJPRINT("q.退出") + RJPRINT("****************************************") + except Exception as e: + log_error(str(e)) + sys.exit(-1) + +def test_kr(): + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : ""} + packetcount = 10000 + RJPRINT("packets %d" % packetcount) + + returnstr = '' + ind = False + + for i in range(0 , 3): + returnstr = '' + try: + pk = PortKrTest() + error = 0 + errmsg = "" + for i in [1,2]: + eth = "eth%d"%i + xe_port = pk.get_mgmt_bcmport(eth) + cmd = "bcmcmd \"port %s en=1\"" % xe_port + ret, output = rj_os_system(cmd) + if(ret != 0): + log_debug("cmd %s fail, output %s" % (cmd, output)) + pk.clear_port_packets() + time.sleep(1) + ret, result = pk.start_send_port_packets(eth, count=packetcount, vlan = 2000) + time.sleep(4) + ret, log = pk.check_port_packets(eth, count=packetcount) + if ret: + returnstr += "%s : PASS \n" % eth + else: + error -= 1 + returnstr += "%s : FAILED reason[%s] \n" % (eth, str(log)) + for i in [1,2]: + eth = "eth%d"%i + xe_port = pk.get_mgmt_bcmport(eth) + cmd = "bcmcmd \"port %s en=0\"" % xe_port + ret, output = rj_os_system(cmd) + if(ret != 0): + log_debug("cmd %s fail, output %s" % (cmd, output)) + if error < 0: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = returnstr + continue + else: + RET[RETURN_KEY1] = 0 + RET[RETURN_KEY2] = returnstr + break + except Exception as e: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = returnstr + RJPRINT(RET[RETURN_KEY2]) + return RET + +def test_all_tmp(test_items): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + global INSP_RESULT + totalerr = 0 + sum_pass_info_tmp = "" + sum_fail_info_tmp = "" + sum_fail_cont = 0 + sum_pass_cont = 0 + time1 = time.time(); + timeArraystart = time.localtime(time1) + test_start_time = time.strftime("%Y-%m-%d %H:%M:%S", timeArraystart) + + for item in test_items: + RJPRINT("") + RJPRINT("=" * 12 + item[MENUITEMNAME] + "=" *12) + RET = dealchoosefunc(item) + RJPRINT("\n") + formatstr = "======%%-%ds ======:%%-10s\n"%((40+wide_chars(item["name"]))) + if RET[RETURN_KEY1] == 0: + RJPRINT("[%s]测试结果:" % item[MENUITEMNAME] + 'Pass') + log_debug("[%s]测试结果:" % item[MENUITEMNAME] + SUCCESS_TIPS) + sum_pass_cont += 1 + sum_pass_info_tmp += formatstr%(item["name"], "PASS") + elif RET[RETURN_KEY1] == 1: + pass + else: + totalerr -= 1 + RJPRINT("[%s]测试结果:" % item[MENUITEMNAME] + 'Fail') + log_debug("[%s]测试结果:" % item[MENUITEMNAME] + 'error') + sum_fail_cont += 1 + sum_fail_info_tmp += formatstr%(item["name"], "FAIL") + + time2 = time.time(); + timeArraystart = time.localtime(time2) + test_end_time = time.strftime("%Y-%m-%d %H:%M:%S", timeArraystart) + + RJPRINT("\n汇总:") + RJPRINT(sum_pass_info_tmp) + RJPRINT(sum_fail_info_tmp) + RJPRINT("测试开始时间:%s"% test_start_time) + RJPRINT("测试结束时间:%s"% test_end_time) + RJPRINT("总共测试项数:%d"%(sum_pass_cont+sum_fail_cont)) + RJPRINT("PASS测试项数:%d"%sum_pass_cont) + RJPRINT("FAIL测试项数:%d"%sum_fail_cont) + sn = getsyseeprombyId(TLV_CODE_SERIAL_NUMBER).get('value') + RJPRINTLINE(" 产品序列号 : %s," % sn) + if (sum_fail_cont > 0): + RJPRINT("Test Result: Fail") + INSP_RESULT = "FAIL" + else: + RJPRINT("Test Result: Pass") + INSP_RESULT = "PASS" + return {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + + +def test_all(): + return test_all_tmp(alltest) + +def test_diag_all(): + return test_all_tmp(diagtestall) + +def test_insp_led_ctl(led_list): + for item in led_list: + bus = item["bus"] + loc = item["loc"] + reg = item["reg"] + val = item["val"] + rji2cset(bus,loc,reg,val) + +class Logger(object): + def __init__(self, fileN="/tmp/out.log"): + self.terminal = sys.stdout + self.log = open(fileN, "w") + + def write(self, message): + self.terminal.write(message) + self.log.write(message) + + def flush(self): + pass + + def close(self): + self.log.close() + + + +def test_stdout_redirect(): + global SAVE_STDOUT + SAVE_STDOUT = sys.stdout # Save the standard output stream + sys.stdout = Logger() # Output redirection + +def test_stdout_resume(): + global SAVE_STDOUT + if SAVE_STDOUT is not None: + sys.stdout.close() + sys.stdout = SAVE_STDOUT + SAVE_STDOUT = None + + +def test_save_insp_result(dst,src = '/tmp/out.log'): + '''Saving inspection Results''' + global INSP_RESULT + if not os.path.exists(src): + return False + time1 = time.time(); + timeArraystart = time.localtime(time1) + test_start_time = time.strftime("%Y-%m-%d-%H-%M-%S", timeArraystart) + sn = getsyseeprombyId(TLV_CODE_SERIAL_NUMBER).get('value') + file_name = "%s_%s_%s.log" % (test_start_time,sn,INSP_RESULT) + if not os.path.exists(dst): + os.makedirs(dst) + cmd = "mv %s %s/%s" % (src,dst,file_name) + status, output = rj_os_system(cmd) + if status: + return False + return True + +def test_inspection_pre(): + '''Pre-inspection process''' + # Test path inspection + ret, msg = test_bmc_channel() + if ret == False: + return ret, msg + inspection_conf = TESTCASE.get("inspection_config",None) + if inspection_conf is None: + return True, '' + # Mount a USB flash drive Save the inspection result to the USB flash drive + if inspection_conf.get("mount_usb",0) == 1: + pass + led_init_list = inspection_conf.get("led_init",[]) + test_insp_led_ctl(led_init_list) + test_stdout_redirect() # Output is directed to the console and files + return True, '' + +def test_inspection_after(): + '''Inspection after the process''' + global INSP_RESULT + inspection_conf = TESTCASE.get("inspection_config",None) + if inspection_conf is None: + return True + # Restore standard output + test_stdout_resume() + # Saving inspection Results + dst_path = inspection_conf.get("log_path") + test_save_insp_result(dst_path) + # The USB flash drive needs to be uninstalled + if inspection_conf.get("mount_usb",0) == 1: + pass + # lamps tip + if INSP_RESULT == "PASS": # inspection OK + func = inspection_conf.get("bmc_led_ctl",None) + if func is not None: # BMC side light + url_path = getRealUrl(func) + cmd = "curl -m 3 %s" % url_path + rj_os_system(cmd) + else: + pass + if inspection_conf.get('halt_flag',0) == 1: # To turn it off + stopFanctrol() + fac_sensors_kill() + test_sys_halt() + return True + led_alarm = inspection_conf.get("led_alarm",[]) # inspection fails, and an alarm is generated when the indicator is on + test_insp_led_ctl(led_alarm) + return True + + +def test_kr_pre(): + return True,"" + +def test_kr_after(): + return True,"" + +# Menu: Single test +def test_signal(id): + startMenu(id) + +def dealfunc(func): + msg = "" + for i in range(0, 3): + ret, msg = func() + if ret == True: + return True + else: + continue + raise Exception(msg) + return False + + +def dealchoosefunc(list): + '''Real menu processing items''' + RET = ERROR_RETURN + funcbefore = None + functest = None + funcafter = None + param_tt = None + param_val = None + funcbeforestr = list.get(ITEMBEFORE, None) + functeststr = list.get(MENUITEMDEAL, None) + funcafterstr = list.get(ITEMAFTER, None) + param_tt = list.get(CHILDID, None) + param_val = list.get('param', None) + + if funcbeforestr is not None: + funcbefore = eval(funcbeforestr) + if functeststr is not None: + functest = eval(functeststr) + if funcafterstr is not None: + funcafter = eval(funcafterstr) + try: + if funcbefore is not None: + log_debug(" 测试项前置:%s " % (funcbefore)) + dealfunc(funcbefore) + if functest is not None: + log_debug(" 测试项 :%s " % (functest)) + if param_tt is not None: + RET = functest(param_tt) + else: + if param_val is not None: + RET = functest(param_val) + else: + RET = functest() + else: + raise Exception("fun test is none") + except Exception as e: + msg = traceback.format_exc() + log_error(msg) + RJPRINT(msg) + RJPRINT("error\n\n") + finally: + if funcafter is not None: + log_debug(" 测试项后置:%s " % (funcafter)) + for i in range(0, 3): + ret, _ = funcafter() + if ret == True: + break + elif i == 2: + log_debug(" 测试项后置:%s run fail 3 times" % (funcafter)) + return RET + + +# Menu to print +# printMenu +# param: list_t Menu item list +# id Menu id + +def printMenu(list_t, id): + global nosetrtc + while True: + try: + printList(list_t, id) + test = "请选择:" + str= getch(test) + RJPRINT(" %s" % str) + log_debug("选择:%s" % str) + str = str.lstrip().lower() + if str == "q": + if id == STARTMENUID: # Top level directory. There's no way back + log_debug("wait subprocess exit") + subprocess_case.shutdown_bgtest() + quit() + else: + break + if str not in listindex: + log_debug("%s 不在菜单项中" % str); + RJPRINT("\n\n") + continue + else: + RJPRINT("=======================> %s <======================="%list_t[listindex.index(str)][MENUITEMNAME]) + log_debug("选择的测试项为:%s id:%d" % (list_t[listindex.index(str)][MENUITEMNAME], id)) + + if list_t[listindex.index(str)].get('lock', False) and (subprocess_case.is_running() + or subprocess_case.is_stopping()):# Some test items cannot be entered during background execution + RJPRINT("后台测试中 %s 不可执行" % list_t[listindex.index(str)][MENUITEMNAME]); + RJPRINT("\n\n") + continue + RET = dealchoosefunc(list_t[listindex.index(str)]) + if RET == None: + RJPRINT("\n\n") + continue + RJPRINT(" ") + if RET[RETURN_KEY1] == 0: + RJPRINT("Test Result: Pass") + log_debug("菜单测试结果:" + SUCCESS_TIPS) + elif RET[RETURN_KEY1] == 1: + pass + else: + RJPRINT("Test Result: Fail") + log_debug("[%s]测试结果:" % list_t[listindex.index(str)][MENUITEMNAME] + 'error') + RJPRINT("\n\n") + except IndexError as d: + RJPRINT("\n\n非法输入\n\n") + except Exception as e: + RJPRINT(e) + RJPRINTERR("\n\n 异常\n\n" ) + +def getMenuFromList(list, id): + for key in list: + if key[MENUID] == id: + return key[MENUVALUE],True + return 0, False + +def getParentIdMenuFromList(list, id): + for key in list: + if key[MENUID] == id: + return key[MENUPARENT],True + return -1, False + +def getDriverFromGlobal(name): + for key in testdriver: + if key["name"] == name: + return key,True + return "-1", False + +def i2ccheckValue(ret1 , ret2, type): + if type == 1 and ret1 == ret2: + return True + elif type == 2 and ret1 == "SUCCESS": + return True + else: + return False + +def test_i2c_scan(scan_list): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + errtotal = 0 + errmsg = "" + for i2cdev in scan_list: + STATE = "FAILED" + formatstr = " %%-%ds %%-10s"%((40+wide_chars(i2cdev['name']))) + ret, log = rji2cget(i2cdev["bus"], i2cdev["addr"], 0) + if ret == False or "Error" in log: + STATE = "FAILED" + errtotal -= 1 + errmsg = "%s %s\n" % (errmsg,formatstr%(i2cdev['name'],log)) + else: + STATE = "PASS" + RJPRINT(formatstr%(i2cdev['name'],STATE)) + if errtotal < 0: + RET[RETURN_KEY1] = errtotal + RET[RETURN_KEY2] = errmsg + return RET + +def test_i2c_new(): + return test_i2c_scan(TESTCASE["I2CSCAN"]) + +def test_diag_i2c(): + return test_i2c_scan(TESTCASE["DIAGI2CSCAN"]) + + +# Menu: Test I2C +def test_i2c(): + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : []} + result_key = 0 + for i2c in TESTCASE["I2C"]: + testerror ={} + RJPRINT("测试项[%s] " % i2c["name"]) + log_debug("测试项[%s] " %i2c["name"]) + testerror["name"] = i2c["name"] + caseerror =[] + if "cases" not in i2c: + RJPRINT("没有测试项") + log_debug("没有测试项") + continue + for case in i2c["cases"]: + # Gets the command invoked + cmd_t = case["cmd"].lstrip() + cmd = cmd_t[0 : cmd_t.index(" ")] + ret_t, log = log_os_system("which " + cmd, 0) + if len(log): + cmd = "cmd find " + else: + result_key -= 1 + caseerror.append({"name":case["name"] ,"error":"cmd not find"}) + continue + ret_t, log = log_os_system(case["cmd"], 0) + if ret_t or ("Error" in log ): + status = "[FAILED]" + result_key -= 1 + caseerror.append({"name":case["name"] ,"error":log}) + log_debug("case: %s [%s] %s" % (case["name"] , case["cmd"],"fail")) + else: + value = " " + if "value" not in case: + value = " " + else: + value = case["value"] + if i2ccheckValue(log, value, case["deal_type"]): + status = "[ok]" + log_debug("case: %s [%s] %s" % (case["name"] , case["cmd"],"ok")) + else: + status = "[FAILED]" + log_debug("case: %s [%s] %s" % (case["name"] , case["cmd"],"fail")) + result_key -= 1 + caseerror.append({"name":case["name"] ,"error": log}) + formatstr = " %%-%ds %%-10s"%((40+wide_chars(case["name"]))) + RJPRINT(formatstr%(case["name"],status)) + testerror['errmsg'] = caseerror + RET[RETURN_KEY2].append(testerror) + if result_key <= 0: + RET[RETURN_KEY1] = result_key + # log_debug(RET) + return RET + +# Compare strings regardless of size +def astrcmp(str1,str2): + return str1.lower()==str2.lower() + +def makesure(info, default = True ,echo = False): + while True: + print (info,) + if echo: + str = raw_input() + else: + str = get_raw_input() + if astrcmp(str, ""): + return default + if astrcmp(str, "y") or astrcmp(str, "ye") or astrcmp(str, "yes"): + return True + elif astrcmp(str, "n") or astrcmp(str, "no"): + return False + else: + RJPRINT("输入无效,请重新输入,") + +# led check Input validation +def get_led_inputcheck(): + err = 0; + str = raw_input("确认状态灯是否正确切换[Yes/no]:") + if astrcmp(str, "y") or astrcmp(str, "ye") or astrcmp(str, "yes") or astrcmp(str, ""): + return True + else: + return False + +def test_mgmtled(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + lb_with_Plug = TESTCASE.get('mgmt').get('100M') + resetphy = TESTCASE.get('mgmt').get('clear') + lenon = TESTCASE.get("mgmt",{}).get("ledon",None) + ledoff = TESTCASE.get("mgmt",{}).get("ledoff",None) + ind = 0 + try: + ret = test_bmc_func(resetphy.get('case'), resetphy.get('param')) + if ret is None: + raise Exception('初始phy失败') + ret = test_bmc_func(lb_with_Plug.get('case'), lb_with_Plug.get('param')) + if ret is None: + raise Exception('设置100回环失败') + time.sleep(0.5) + key = "(link灯:橙色)" + if makesure("确认切换到%s(Yes/No):"%key ,echo = 1) == True: + ret = test_bmc_func(resetphy.get('case'), resetphy.get('param')) + time.sleep(0.5) + else: + ind = -1 + cmd = lenon.get("cmd",None) + func = lenon.get("bmc_interface",None) + ret = test_bmc_func(func,cmd) + key = "(link灯:绿 、act灯:绿)" + if makesure("确认切换到%s(Yes/No):"%key ,echo = 1) == True: + ret = test_bmc_func(resetphy.get('case'), resetphy.get('param')) + time.sleep(0.5) + else: + ind = -2 + key = "(link灯:灭 、act灯:灭)" + cmd = ledoff.get("cmd",None) + func = ledoff.get("bmc_interface",None) + ret = test_bmc_func(func,cmd) + if makesure("确认切换到%s(Yes/No):"%key ,echo = 1) == True: + ret = test_bmc_func(resetphy.get('case'), resetphy.get('param')) + time.sleep(0.5) + else: + ind = -3 + except Exception as e: + ind = -999 + RET[RETURN_KEY2] = str(e) + print (str(e)) + finally: + ret = test_bmc_func(resetphy.get('case'), resetphy.get('param')) + time.sleep(0.5) + RET[RETURN_KEY1] = ind + return RET + + +def test_led_new(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + led_param = TESTCASE["LED_NEWS"] + total_err = 0 + rest_status = 0 + + for item_keys in sorted(led_param.keys()): + item_led = led_param.get(item_keys) + try: + ''' New logic to determine whether the front register needs to be closed before port lights ''' + led_control = item_led.get('LED_CONTROL', None) + if led_control is not None: + ind = led_control.get("open", 0) + if ind == 1: + regs = led_control.get("regs", []) + for item in regs: + rji2cset(item["bus"], item["devno"], item["addr"], item["open"]) + else: + pass + else: + pass + + attrs = item_led.get('attrs') + device = item_led.get('device') + RJPRINT(item_led.get('name')) + + for key, val in attrs.items(): + for item in device: + gettype = item.get("gettype",'i2c') + if gettype == 'i2c': # i2c + rji2cset(item.get('bus'),item.get('addr'),item.get('reg'), val) + elif gettype == 'io': + io_wr(item.get('io_addr'), val) + elif gettype == 'cmd': + cmd = item.get('cmd') % val + rj_os_system(cmd) + elif gettype == 'pcie': + pcibus = item.get('pcibus') + slot = item.get('slot') + bar = item.get('bar') + fn = item.get('fn') + offset = item.get('offset') + rjpciwr(pcibus, slot, fn, bar, offset, val) + elif gettype == 'restful': + returncode, msg = test_bmc_channel() + if returncode == False: + total_err -= 1 + rest_status = -1 + RJPRINT(msg) + break + func = item.get('func') + param = item.get('param') + param['value'] = val + ret = test_bmc_func(func,param) + if rest_status < 0: + rest_status = 0 + break + if makesure("确认切换到%s(Yes/No):"%key ,echo = 1) == True: + continue + else: + total_err -=1 + except Exception as e: + total_err = -999 + RET[RETURN_KEY2] = str(e) + finally: + ''' Add new logic to determine whether the front register needs to be closed after the port lights ''' + led_control = item_led.get('LED_CONTROL', None) + if led_control is not None: + ind = led_control.get("open", 0) + if ind == 1: + regs = led_control.get("regs", []) + for item in regs: + rji2cset(item["bus"], item["devno"], item["addr"], item["close"]) + else: + pass + else: + pass + + + RET[RETURN_KEY1] = total_err + # Take before and after + return RET + +# System light test +def test_led(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + try: + stopFanctrol() + for led in TESTCASE["LED"]: + RJPRINT("测试项: %s" % led["name"]) + if "cases" not in led: + RJPRINT("没有测试项") + continue + for case in led["cases"]: + RJPRINT(case["name"]) + # Gets the command invoked + if "cmd" in case.keys(): + cmd_t = case["cmd"].lstrip() + cmd = cmd_t[0 : cmd_t.index(" ")] + ret, log = log_os_system("which " + cmd, 0) + if len(log): + cmd = "cmd find " + else: + RET[RETURN_KEY2] = "no " + cmd +" found" + log_debug(RET[RETURN_KEY2]) + RJPRINT(RET[RETURN_KEY2]) + RET[RETURN_KEY1] = -1 + return RET + log_debug(case["cmd"]) + ret, log = log_os_system(case["cmd"], 0) + if ret or ("Error" in log ): + RJPRINT("[ERROR]") + totalerr -= 1 + else: + if get_led_inputcheck(): + RJPRINT("[PASS]") + else: + RJPRINT("[FAIL]") + totalerr -= 1 + elif "deal_bmc_led" in case.keys(): + returncode, msg = test_bmc_channel() + if returncode == False: + totalerr -= 1 + RJPRINT(msg) + continue + func = case["deal_bmc_led"] + param = case["param"] + ret = test_bmc_func(func,param) + if ret[RETURN_KEY1] != 0: + RJPRINT("[ERROR]") + totalerr -= 1 + else: + if get_led_inputcheck(): + RJPRINT("[PASS]") + else: + RJPRINT("[FAIL]") + totalerr -= 1 + except Exception as e: + RJPRINT(e) + totalerr -= 1 + finally: + startFanctrol() + RET[RETURN_KEY1] = totalerr + return RET + + +# Setting the Debug Level +def test_setdebug(): + global DEBUG + DEBUG = not DEBUG + if DEBUG == False: + RJPRINT("调试开关关闭") + else: + RJPRINT("调试开关打开") + return SUCCESS_RETURN + +# Get the menu by ID +def startMenu(id): + list,code = getMenuFromList(menuList, id) + if code == False: + log_error("错误的文件结构") + RJPRINT("无此菜单,请确认") + sys.exit(1) + log_debug("根据ID获取到相应的菜单列表") + printMenu(list, id) + +def keyboardTest(): + while True: + log_debug("123") + +def startThread(): + thread = threading.Thread(target=keyboardTest) + thread.setDaemon(True) + thread.start() + +def rji2cset(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + +def rjpcird(pcibus , slot , fn, bar, offset): + '''read pci register''' + if offset % 4 != 0: + return + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + size = os.path.getsize(filename) + with open(filename, "r+") as file: + data = mmap.mmap(file.fileno(), size) + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + data.close() + return "0x%08x" % val + +def inttostr(vl,len): # Convert int to string , 0x3030 = 00 + if type(vl) != int: + raise Exception(" type error") + index = 0 + ret_t = "" + while index < len: + ret = 0xff & (vl >> index * 8) + ret_t += chr(ret) + index += 1; + return ret_t + +def rjpciwr(pcibus , slot ,fn, bar, offset, data): + '''write pci register''' + ret = inttostr(data, 4) + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + size = os.path.getsize(filename) + with open(filename, "r+") as file: + data = mmap.mmap(file.fileno(), size) + data[offset: offset + 4] = ret + data.close() + +# start +def start(): + # menuid = if vars().__contains__('STARTMENUID') else 0 + # print menuid + # print STARTMENUID + global STARTMENUID + if STARTMENUID is None: + STARTMENUID = 0 + startMenu(STARTMENUID) + +def test_cpu_stress_show(): + ret, log = log_os_system("top -bi -n2 -d 0.2 | grep '%Cpu(s)' | tail -n1", 0) + if ret: + print ("获取CPU信息失败") + else: + value , times = re.subn("[\S\s]*,\s*([\.\d]+)\sid[\S\s]*","\g<1>", log) + if times != 1: + print (log) + print ("获取CPU利用率失败") + else: + print ("当前cpu利用率为%.1f%%"%(100 - float(value))) + return {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + +def process_cpu_stress_test(interval): + # print("The time is {0}".format(time.ctime())) + # Generate four processes, each of which computes the square root of a random number generated by rand () over and over again + cmd = "stress -c 4" + ret, log = log_os_system(cmd, 0) + +cpu_stress_test = False +def test_cpu_stress(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : "已启动后台执行"} + global cpu_stress_test + if cpu_stress_test : + RJPRINT(RET[RETURN_KEY2]) + return RET + ret, log = log_os_system("which stress", 0) + if len(log): + p = multiprocessing.Process(target = process_cpu_stress_test, args = (3,)) + p.daemon = True + p.start() + # global cpu_stress_test + cpu_stress_test = True + else: + RET[RETURN_KEY2] = "no stress cmd" + RJPRINT(RET[RETURN_KEY2]) + return RET + + +# Obtaining Memory Information +def memory_stat(): + mem = {} + f = open("/proc/meminfo") + lines = f.readlines() + f.close() + for line in lines: + if len(line) < 2: continue + name = line.split(':')[0] + var = line.split(':')[1].split()[0] + mem[name] = long(var) * 1024.0 + mem['MemUsed'] = mem['MemTotal'] - mem['MemFree'] - mem['Buffers'] - mem['Cached'] + return mem + +def get_sdk_version(): + cmdstr = "bcmcmd 'version' < /dev/null | grep Release" + ret, log = rj_os_system(cmdstr) + version_temp = re.subn("( \r\n)|( \r\n\r\r\ndrivshell>)|(version\r\r)","",log)[0] + version_clean = re.subn("\n","\n\t",version_temp)[0] + + return version_clean + +def get_cpu_message(): + cpu_ret = getDmiSysByType("processor") + return cpu_ret + +def get_phypcie_version(): + cmd = 'bcmcmd -t 1 "pciephy fw version" < /dev/null' + ret , log = rj_os_system(cmd) + if ret != 0: + print ("get version failed: pciephy fw") + version_clean = "" + # print log + else: + version_temp = re.subn("( \r\n)|( \r\n\r\r\ndrivshell>)|(version\r\r)","",log)[0] + version_clean = re.subn("(pciephy fw \n)|(\r\r\ndrivshell>)","",version_temp)[0] + # print version_temp + return version_clean + + +def get_sonic_version(): + VERSION_TEMPLATE_CONTENTS = "SONiC.{build_version}" + tmp_t ={} + try: + for line in open("/etc/sonic/sonic_version.yml"): + swploca=line.index(':') + tmp_t[line[0:swploca].replace("'","")] = line[swploca + 1: len(line)].replace("'","").replace(" ","").strip() + s = VERSION_TEMPLATE_CONTENTS.format(**tmp_t) + return s + except Exception as e: + ret -= 1 + return "" + +def getFormatHead(HEAD): + len_t = len(HEAD) + formatstr = " " + headtip = formatstr + septips = formatstr + for i in range(len_t): + formatstr += "%-20s " + headtip += "%%-%ds "%(20+wide_chars(HEAD[i])) + septips +="%-20s " + headtip = headtip % HEAD[i] + septips = septips % ("-"*20) + print (headtip) + print (septips) + return formatstr + + +def rji2cgetWord(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x w" % (bus, devno, address) + retrytime = 3 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + +def rji2cget(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + + +def get_mgmt_version(): + cmd = "ethtool -i eth0" + valstr = "" + ret , log = rj_os_system(cmd) + if ret != 0: + return "get version failed: 210 fw" + else: + version_temp = log.split('\n') + for i in version_temp: + valstr = "%s %s \n" %(valstr, '%s' % i) + return valstr + + +def get_harddisk_info(sddev): + ret = {} + cmd = "smartctl -i /dev/%s |grep Device -A13" % sddev + ret1, log1 = rj_os_system(cmd) + if ret1 != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + its = log1.replace("\t", "").strip().split("\n") + for it in its: + if ":" in it: + key = it.split(":", 1)[0].lstrip() + value = it.split(":", 1)[1].lstrip() + ret[key] = value + return True, ret + +def show_harddisk_info(): + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : ""} + cmd = "ls -l /sys/block/sda" + ind = None + val = None + ret, output = log_os_system(cmd, 0) + sata_key, times = re.subn(".*/(ata.)/*","\g<1>",output.lower()) + ret, log = log_os_system("which smartctl", 0) + if len(log): + ind, val =get_harddisk_info("sda") + else: + RET[RETURN_KEY2] = "no smartctl cmd" + return RET + # print val + valtemp = " 序列号 :{Serial Number} \n"\ + " 型号 :{Device Model} \n"\ + " 版本号 :{SATA Version is} \n"\ + " 空间 :{User Capacity} \n"\ + " 固件版本号:{Firmware Version} \n" + + s = valtemp.format(**val) + if TESTCASE.get("ssd_slot_num", 1) == 2: + if sata_key[0:4] == "ata1" : + RJPRINT(" SATA slot: 1") + RJPRINT(s) + RJPRINT("\n SATA slot: 2 (Not present)") + else: + RJPRINT(" SATA slot: 1 (Not present)") + + RJPRINT("\n SATA slot: 2") + RJPRINT(s) + else: + RJPRINT(s) + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + return RET + +def get_cpld_version(): + # header = ["名称","日期","版本"] + # formatstr = getFormatHead(header) + result = [] + totalerr = 0 + for cpld in CPLDVERSIONS: + dict = {} + gettype = cpld.get("gettype",None) + bus = cpld.get("bus",None) + devno = cpld.get("devno",None) + url = cpld.get("url",None) + io_addr = cpld.get("io_addr",None) + data = "" + t = True + ret = None + if gettype == "lpc": + for i in range(4): + ret = lpc_cpld_rd(i) + if ret == None: + t = False + break; + data += chr(int(ret,16)) + elif gettype == "io": + for i in range(4): + ret = io_rd(io_addr + i) + if ret == None: + t = False + break; + data += chr(int(ret,16)) + elif gettype == "restful": + ret = cpld_version_restful(url) + if ret == None: + continue + data_1 = ret.replace("\""," ").strip().split(" ") + for item in data_1: + data += chr(int(item,16)) + else: + for i in range(4): + ind, ret = rji2cget(bus, devno, i) + if ind == False: + t = False + break; + data += chr(int(ret,16)) + if data == "": + totalerr -= 1 + result.append([ cpld.get('name',None),"NA","NA" ]) + else: + result.append([ cpld.get('name',None),"%02x%02x%02x" % (ord(data[1]) ,ord(data[2]) ,ord(data[3])),"%02x" % (ord(data[0]))]) + # for item in result: + # formatstr = " %%-%ds %%-20s %%-20s "%((20+wide_chars(item[0]))) + # print (formatstr%(item[0],item[1],item[2])) + return totalerr,result + +def show_81724_version(): + str1 = "phy control ce fw_get" + cmd ='bcmcmd "%s" < /dev/null' % str1 + totalerr = 0 + version = None + ind, log = rj_os_system(cmd) + if ind == 0: + for line in log.splitlines(): + if "fw_version" in line: + if "success" not in line: + totalerr -= 1 + RJPRINT(line) + else: + versiontmp = re.findall(r"fw_version=(.+?) ", line)[0] + if version is None: + version = versiontmp + else: + if version != versiontmp: + RJPRINT(line) + else: + pass + else: + RJPRINT(" 命令执行失败(%s) %s" % (cmd, log)) + if totalerr == 0: + RJPRINT(" %s" % version) + +def show_fpga_version(): + RJPRINT("") + RJPRINT("%s " % "FPGA版本检测") + fpgastatus = TESTCASE.get("FPGA_INFO", None) + totalerr = 0 + for item in fpgastatus: + if item.get("gettype",None) == 'pci': + pcibus = item.get("pcibus",None) + slot = item.get("slot",None) + fn = item.get("fn",None) + bar = item.get("bar",None) + offset = item.get("offset",None) + ret = rjpcird(pcibus, slot, fn, bar, offset) + if ret is None: + totalerr = -1 + RJPRINT("\tget %s failed: fpga"% item.get("name", "error para")) + continue + RJPRINT(" %-19s: %s" % (item.get("name", "error para"), ret)) + else: + pass + return totalerr + +def check_cpu_mac(): + # print "CPU,BMC,TLV,FRU的MAC和录入的MAC进行比较" + log1 = getsyseeprombyId(TLV_CODE_MAC_BASE).get('value') + # cmd="ifconfig eth0 |grep HWaddr |awk '{print $5}'" + cmd = "ifconfig eth0" + ret, log2 = log_os_system(cmd, 0) + if ret != 0: + log_debug("\n ifconfig eth0 failed") + return {RETURN_KEY1: -1, RETURN_KEY2: "ifconfig eth0 failed"} + str_eth_tmp = re.subn('[\r\n\t]', ' ', log2.lower()) + cpu_mac = re.sub(".*(([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}).*", "\g<1>", str_eth_tmp[0]) + if len(cpu_mac) != 17: + log_debug("获取CPU MAC失败") + return {RETURN_KEY1: -1, RETURN_KEY2: "获取CPU MAC失败"} + log_debug("cpu_mac = %s, e2_mac = %s" % (cpu_mac.lower(), log1.lower())) + if cpu_mac.lower() == log1.lower(): + return {RETURN_KEY1: 0, RETURN_KEY2: cpu_mac.lower()} + else: + log_debug("cpu_mac与e2_mac不相等") + return {RETURN_KEY1: -1, RETURN_KEY2: "cpu_mac与e2_mac不相等"} + +def show_bmc_mac(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret, msg = test_bmc_channel() + if ret == False: + log_debug("show_bmc_mac bmc channel error:%s" % msg) + RET[RETURN_KEY1] = -1 + return RET + + cmd = "ifconfig eth0 |grep HWaddr |awk '{print $5}'" + func = 'bmc_log_os_system' + ret = test_bmc_func(func,cmd) + if ret.get(RETURN_KEY1) == -1 or len(ret.get(RETURN_KEY2)) == 0: + RET[RETURN_KEY1] = -1 + log_debug("BMC MAC 获取失败\nmessage:%s" % (ret.get(RETURN_KEY2))) + else: + RET = ret + log_debug("BMC MAC 获取成功") + return RET + +def add_mac_num(list_mac,n): + str_mac_lower=list(list_mac.lower()) + for j in range(int(n)): + add_n=1 + for i in range(17): + if str_mac_lower[16-i] ==':': + continue + else: + if add_n==1: + if str_mac_lower[16-i]=='f': + str_mac_lower[16-i]='0' + elif str_mac_lower[16-i]=='9': + str_mac_lower[16-i]='a' + add_n=0 + else: + int_mac=ord(str_mac_lower[16-i])+1 + str_mac_lower[16-i]=chr(int_mac) + add_n=0 + else: + break + return ''.join(str_mac_lower) + +def show_device_mac(): + RJPRINT("%s " % "MAC地址:") + RET = {RETURN_KEY1: 0, RETURN_KEY2: ""} + RET = check_cpu_mac() + result = 0 + if RET[RETURN_KEY1] < 0: + RJPRINT(" CPU:fail %s" % RET[RETURN_KEY2]) + result = -1 + else: + RJPRINT(" CPU:%s" % RET[RETURN_KEY2]) + if FACTESTMODULE.__contains__("bmcsetmac") and FACTESTMODULE['bmcsetmac'] == 1 and bmc_presence_check(): + bmc_right_macaddr = add_mac_num(RET[RETURN_KEY2], 2) + RET = show_bmc_mac() + if RET[RETURN_KEY1] < 0: + RJPRINT(" BMC:fail %s" % RET[RETURN_KEY2]) + result = -1 + elif RET[RETURN_KEY2].lower() != bmc_right_macaddr.lower(): + result = -1 + RJPRINT(" BMC:%s" % RET[RETURN_KEY2]) + log_debug("bmc mac != cpu mac add 2") + else: + RJPRINT(" BMC:%s" % RET[RETURN_KEY2]) + RJPRINT("") + return result + +# Obtaining System Information +def test_sysinfo(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + errmsg = "" + totalerr = 0 + + RJPRINT("%-20s: %s"% ("ONIE版本", get_onie_full_version())) + RJPRINT("%-20s: %s"% ("SONiC版本", get_sonic_version())) + RJPRINT("%-20s: %s"% ("SDK版本", get_sdk_version())) + + RET1 = test_bios_flash() + RJPRINT("%-21s: %s" % ('主BIOS版本',"%s"%(RET1["master"]))) + RJPRINT("%-21s: %s" % ('备BIOS版本',"%s"%(RET1["slave"]))) + if RET1[RETURN_KEY1] < 0 : + totalerr -= 1 + RET[RETURN_KEY2] += RET1[RETURN_KEY2] + log = get_bios_info() + RJPRINT("%-20s: %s" % ('当前BIOS',"%s"%(log))) + + + log_debug("正在获取软件版本信息") + RJPRINT("") + RJPRINT("%s "% "CPU") + ret , biosmsg = get_cpu_message() + if ret == True: + # RJPRINT(" 供应商 : %s" % (biosmsg["Manufacturer"])) + RJPRINT(" 版本 : %s" % (biosmsg["Version"])) + RJPRINT(" Core Count : %s" % (biosmsg["Core Count"])) + RJPRINT(" Thread Count : %s" % (biosmsg["Thread Count"])) + else: + totalerr -= 1 + RJPRINT("") + if FACTESTMODULE.get("show_device_mac", 0) == 1: + totalerr += show_device_mac() + if FACTESTMODULE.get("mac_pcie", 1) == 1: + RJPRINT("%s "% "PCIE") + ver = get_phypcie_version() + RJPRINT(ver) + if "version" not in ver or "error" in ver.lower(): + RJPRINT("PCIE 固件版本获取异常") + totalerr -= 1 + + if FACTESTMODULE.get("81724firmware", 0) == 1: + RJPRINT("%s "% "81724版本") + show_81724_version() + RJPRINT("") + + RJPRINT("%s "% "I210版本") + RJPRINT(get_mgmt_version()) + + if FACTESTMODULE.get("sata", 1) == 1: + RJPRINT("%s "% "SATA") + show_harddisk_info() + + RJPRINT("") + log_debug("正在获内存信息") + # print "%s "% "内存" + RJPRINT("%s "% "内存条:") + ret ,log = getsysmeminfo_detail() + if ret == True: + for item in log: + if(len(MEM_SLOTS) == len(log)): + RJPRINT(" 槽位【%s】/【%s】" % (item["Locator"], MEM_SLOTS[log.index(item)])) + else: + RJPRINT(" 槽位【%s】" % (item["Locator"])) + RJPRINT(" 序列号: %s" % (item["Serial Number"])) + RJPRINT(" 容量 : %s" % (item["Size"])) + RJPRINT(" 速度 : %s" % (item["Speed"])) + else: + totalerr -= 1 + + if FACTESTMODULE.get("sysinfo_showhw", 1) == 1: + RJPRINT("") + RJPRINT("%s "% "硬件系统") + ret ,sysmsg = gethwsys() + if ret == True: + RJPRINT(" 产品名称 : %s" % (sysmsg["Product Name"])) + RJPRINT(" 版本 : %s" % (sysmsg["Version"])) + RJPRINT(" 序列号 : %s" % (sysmsg["Serial Number"])) + RJPRINT(" 产商 : %s" % (sysmsg["Manufacturer"])) + RJPRINT(" SKU : %s" % (sysmsg["SKU Number"])) + RJPRINT(" UUID : %s" % (sysmsg["UUID"])) + RJPRINT(" Family : %s" % (sysmsg["Family"])) + RJPRINT(" Wake-up Type : %s" % (sysmsg["Wake-up Type"])) + else: + totalerr -= 1 + else: + pass + + RJPRINT("") + RJPRINT("%s "% "CPLD版本检测") + ind, val = get_cpld_version() + for item in val: + formatstr = " %-20s: %s%s" + RJPRINT(formatstr%(item[0],item[2],item[1])) + totalerr += ind + + if FACTESTMODULE.get("fpga_show", 0) == 1: + totalerr += show_fpga_version() + + if totalerr <= 0: + RET[RETURN_KEY1] += totalerr + RET[RETURN_KEY2] += errmsg + + return RET + +def test_diag_sysinfo(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + errmsg = "" + totalerr = 0 + + RJPRINT("%-20s: %s"% ("ONIE版本", get_onie_full_version())) + RJPRINT("%-20s: %s"% ("SONiC版本", get_sonic_version())) + RJPRINT("%-20s: %s"% ("SDK版本", get_sdk_version())) + + log = get_bios_info() + RJPRINT("%-20s: %s" % ('当前BIOS',"%s"%(log))) + + RET1 = test_bios_flash() + RJPRINT("%-20s: %s" % ('BIOS版本',"%s"%(RET1.get(log)))) + + log_debug("正在获取软件版本信息") + RJPRINT("") + RJPRINT("%s "% "CPU") + ret , biosmsg = get_cpu_message() + if ret == True: + # RJPRINT(" 供应商 : %s" % (biosmsg["Manufacturer"])) + RJPRINT(" 版本 : %s" % (biosmsg["Version"])) + RJPRINT(" Core Count : %s" % (biosmsg["Core Count"])) + RJPRINT(" Thread Count : %s" % (biosmsg["Thread Count"])) + else: + totalerr -= 1 + RJPRINT("") + if FACTESTMODULE.get("mac_pcie", 1) == 1: + RJPRINT("%s "% "PCIE") + RJPRINT(get_phypcie_version()) + + if FACTESTMODULE.get("81724firmware", 0) == 1: + RJPRINT("%s "% "81724版本") + show_81724_version() + RJPRINT("") + + RJPRINT("%s "% "I210版本") + RJPRINT(get_mgmt_version()) + + RJPRINT("%s "% "SATA") + show_harddisk_info() + + RJPRINT("") + log_debug("正在获内存信息") + # print "%s "% "内存" + RJPRINT("%s "% "内存条:") + ret ,log = getsysmeminfo_detail() + if ret == True: + for item in log: + if(len(MEM_SLOTS) == len(log)): + RJPRINT(" 槽位【%s】/【%s】" % (item["Locator"], MEM_SLOTS[log.index(item)])) + else: + RJPRINT(" 槽位【%s】" % (item["Locator"])) + RJPRINT(" 序列号: %s" % (item["Serial Number"])) + RJPRINT(" 容量 : %s" % (item["Size"])) + RJPRINT(" 速度 : %s" % (item["Speed"])) + else: + totalerr -= 1 + + if FACTESTMODULE.get("sysinfo_showhw", 1) == 1: + RJPRINT("") + RJPRINT("%s "% "硬件系统") + ret ,sysmsg = gethwsys() + if ret == True: + RJPRINT(" 产品名称 : %s" % (sysmsg["Product Name"])) + RJPRINT(" 版本 : %s" % (sysmsg["Version"])) + RJPRINT(" 序列号 : %s" % (sysmsg["Serial Number"])) + RJPRINT(" 产商 : %s" % (sysmsg["Manufacturer"])) + RJPRINT(" SKU : %s" % (sysmsg["SKU Number"])) + RJPRINT(" UUID : %s" % (sysmsg["UUID"])) + RJPRINT(" Family : %s" % (sysmsg["Family"])) + RJPRINT(" Wake-up Type : %s" % (sysmsg["Wake-up Type"])) + else: + totalerr -= 1 + else: + pass + + RJPRINT("") + RJPRINT("%s "% "CPLD版本检测") + ind, val = get_cpld_version() + for item in val: + formatstr = " %-20s: %s%s" + RJPRINT(formatstr%(item[0],item[2],item[1])) + totalerr += ind + + + if totalerr <= 0: + RET[RETURN_KEY1] += totalerr + RET[RETURN_KEY2] += errmsg + + return RET + +# ==================================== +# test item:RTC +# ==================================== +def test_rtc(): + RET = ERROR_RETURN + time1 = time.time(); + timeArraystart = time.localtime(time1) + my_log("start time:" + str(time1)) + otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArraystart) + RJPRINT("开始时间:%s" % otherStyleTime) + time.sleep(RTC_WAIT_TIME) + time2 = time.time(); + timeArrayend = time.localtime(time2) + otherStyleTime1 = time.strftime("%Y-%m-%d %H:%M:%S", timeArrayend) + RJPRINT("结束时间:%s" % otherStyleTime1) + my_log("end time:" + str(time2)) + timeCompare = time2 - time1 + my_log("time difference:" + str(timeCompare)) + if timeCompare < RTC_THRESHOLD_LOWER or timeCompare > RTC_THRESHOLD_UPPER: + log_debug("RTC 测试失败") + RET = {RETURN_KEY1: -1 , RETURN_KEY2 : "Error:RTC测试失败"} + else: + log_debug("RTC 测试成功") + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + return RET + +# ==================================== +# Executing shell commands +# ==================================== +def get_sys_execute(str): + # function 1 + result = os.popen(str) + res = result.read() + for line in res.splitlines(): + RJPRINT(line) + ''' + #function 2 + output = subprocess.getstatusoutput(str) + print output + + + #function 3 + p = subprocess.Popen('ps aux',shell=True,stdout=subprocess.PIPE) + out,err = p.communicate() + for line in out.splitlines(): + print line + ''' +# mylog +def my_log(txt): + if DEBUG == True: + RJPRINT("[RAGILE]:",) + RJPRINT(txt) + return +# ==================================== +# Executing shell commands +# ==================================== +def log_os_system(cmd, show): + my_log (' Run :'+ cmd) + status, output = subprocess.getstatusoutput(cmd) + my_log (" with result :" + str(status)) + my_log (" output :" + output) + if status: + log_error('Failed :'+cmd) + if show: + RJPRINT('Failed :'+ cmd) + return status, output +# ==================================== +# Copy machine initialization +# ==================================== +def kj_init(): + global KAOJILOGFILE + time1 = time.time() + timeArraystart = time.localtime(time1) + otherStyleTime = time.strftime("%Y%m%d_%H%M", timeArraystart) + KAOJILOGFILE = "/var/grtd/kjlog_%s.log" % otherStyleTime + log_debug("创建的拷机日志:" + KAOJILOGFILE) + file = open(KAOJILOGFILE,'w') + file.close() + +# ==================================== +# Copy machine results save +# ==================================== +def KJERSULT(log): + global KAOJILOGFILE + strval = json.dumps(log, ensure_ascii = False,indent=4) + with open(KAOJILOGFILE, 'w') as f: + f.write(strval) + +# ==================================== +# Whether the test item exists in the copier error array +# ==================================== +def kj_isexit(name, result): + for item in result: + #log_debug(item) + if name == item["name"]: +# log_debug(name + " in result") + return True + return False + +# ==================================== +# Returns information about the test items that exist in the error array +# ==================================== +def kj_find_result(name , result): + for item in result: + if name == item["name"]: +# log_debug(name + "exist") + return item + return None + + +# ==================================== +# loop test +# ==================================== +def test_loop(): + global kj_result + global KAOJISTATUS + global ISKAOJI + kj_result = [] + real_kj_result ={"starttime":"","endtime":"","result":[] ,"loop":0} + KAOJISTATUS = 1 + kj_init() + # Create loop test file + loop = 1 + isloopprint = True + try: + time1 = time.time(); + timeArraystart = time.localtime(time1) + otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArraystart) + real_kj_result["starttime"] = otherStyleTime + while True: + ISKAOJI = 1 + time1 = time.time(); + timetemp_t = time.localtime(time1) + casestarttime = time.strftime("%Y-%m-%d %H:%M:%S", timetemp_t) + RJPRINT("\n==================> 生测第%d轮拷机测试开始 <===================" %loop) + log_debug("==========生测第%d轮拷机测试开始(%s)============" % (loop, casestarttime)) + for item in looptest: + kj_itemresult = {"name":"test", "loop":[], "error":[]} + RJPRINT("\n\n %s" % item[MENUITEMNAME]) + RJPRINT("=" * 60) + log_debug(" ") + log_debug("==========%s 开始============" % item[MENUITEMNAME]) + RET = dealchoosefunc(item) # eval(item[MENUITEMDEAL])() + # log_debug(RET) + if RET[RETURN_KEY1] != 0: + RJPRINT("[%s]测试结果:" % item[MENUITEMNAME] + 'Fail') + val_tmp = RET[RETURN_KEY2] + if kj_isexit(item[MENUITEMNAME], kj_result): + it = kj_find_result(item[MENUITEMNAME], kj_result) + # log_debug(it) + it["loop"].append(loop) + it["error"].append(val_tmp) + else: + kj_itemresult["name"] = item[MENUITEMNAME] + kj_itemresult["loop"].append(loop) + kj_itemresult["error"].append(val_tmp) + kj_result.append(kj_itemresult) + else: + RJPRINT("[%s]测试结果:" % item[MENUITEMNAME] + 'Pass') + log_debug("==========%s 结束============" % item[MENUITEMNAME]) + time2 = time.time(); + timeArrayend = time.localtime(time2) + otherStyleTime1 = time.strftime("%Y-%m-%d %H:%M:%S", timeArrayend) + real_kj_result["endtime"] = otherStyleTime1 + real_kj_result["result"] = kj_result + real_kj_result["loop"] = loop + # Write files + KJERSULT(real_kj_result) + RJPRINT("\n==================> 生测第%d轮拷机测试结束 <===================\n" %loop) + log_debug("==========生测第%d轮拷机测试结束(%s)============" % (loop,otherStyleTime1)) + loop += 1 + # isloopprint = True + # time.sleep(5) + if KAOJISTATUS == 0: + break + ISKAOJI = 0 + except Exception as e: + RJPRINT(e) + log_error(str(e)) + return {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + +def file_name(file_dir): + L=[] + for dirpath, dirnames, filenames in os.walk(file_dir): + for file in filenames : + if file.startswith("kjlog"): + L.append(os.path.join(dirpath, file)) + datas =sorted(L,reverse=True) + return datas + + +def readKjLog(filename): + str1 ="" + try: + with open(filename, 'r') as f: + str1 = f.read() + if str1 == "": + raise Exception("文件内容为空") + val_t = eval(str1) + ret = val_t["result"] + RJPRINT("=====================================拷机结果=========================================================") + RJPRINT("开始时间: %s \r\n结束时间: %s \r\n总轮数 :【%d】"% (val_t["starttime"], val_t["endtime"], val_t["loop"])) + + if len(ret) > 0: + RJPRINT(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>失败测试项:") + else: + RJPRINT("本次拷机无失败测试项") + for item in ret: + RJPRINT("%s 【%s】 "% ("测试项:", item["name"])) + loopstr = "" + for loop in item["loop"]: + loopstr += " %d " % loop + RJPRINT("失败的轮数: %s" % loopstr), + for loop in item["loop"]: + RJPRINT("第【%d】轮数错误:" % loop) + index = item["loop"].index(loop) + errmsg = item["error"][index] + if isinstance(errmsg, list): + for test in errmsg: + RJPRINT(" %s : " % test["name"]) + for case_ret in test["errmsg"]: + RJPRINT(" {name} {error}".format(**case_ret) ) + elif isinstance(errmsg, str): + RJPRINT("{0} \n{1}".format(item["name"] , errmsg)) + RJPRINT("\n") + except Exception as e: + RJPRINTERR(str(e)) + + RJPRINT("\n\n\n\n") +# ==================================== +# Copy machine log array selection +# ==================================== +def printKJList(): + readtips = True + L = file_name(KAOJILOGPATH) + if len(L) <= 0: + RJPRINT("\n\n没有拷机日志\n\n"); + return + while(readtips): + index = 0 + for x in L: + RJPRINT("%d. %s"%(index, os.path.basename(x))) + index += 1 + if (index >= kjlogmaxshow): + break + RJPRINT("q. %s"%("返回上一层")) + test = "请选择:" + str= getch(test) + RJPRINT(" %s" % str) + if str.isalnum() == False: + RJPRINT("") + continue + # log_debug("选择:%s" % str) + str = str.lstrip().lower() + if str == "q": + readtips = False + elif (int(str) >= 0 and int(str) <= index): + readKjLog(L[int(str)]) + else: + log_debug("异常输入项") + +# ================================================== +# Copy machine result deleted +# ================================================== +def test_loop_delete(): + L = file_name(KAOJILOGPATH) + if len(L) <=0: + RJPRINT("没有拷机记录") + return {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + for file in L: + os.remove(file) # Delete the file + return {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + +# ==================================== +# Copy machine results to view +# ==================================== +def test_loop_read(): + printKJList(); + return {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + +def getRealUrl(case, param=None): + http = TESTCASE.get('BMC').get('requesthttp') + realurl = "" + if param is None: + realurl = "%scase=%s" %(http, case) + else: + realurl = "%scase=%s¶m=%s"% (http, case, param) + return realurl + +def test_bmc_func(func,param=None): + if param is None: + ret = HttpRest().Get(getRealUrl(func)) + else: + ret = HttpRest().Get(getRealUrl(func,json.dumps(param))) + return ret + +def test_bmc_testcase(param_t): + ret = test_bmc_func(param_t) + RJPRINT(ret.get(RETURN_KEY2)) + return ret + +def uploadfile(filename): + http = TESTCASE.get('BMC').get('uploadfilehttp') + return HttpRest().uploadfile(http, filename) + +def test_cpld_new(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + ermsg = "" + # dealtype = E2_PROTECT.get('gettype',None) + vals = TESTCASE["CPLDTEST"] + # vals = "123" + if type(vals) == list: + for item in vals: + dealtype = item.get('gettype',None) + if dealtype is not None and dealtype == "io": + for wr_tmp in item.get('testval'): + io_wr(item.get('io_addr') + item.get('addr'), wr_tmp) + rets = io_rd(item.get('io_addr') + item.get('addr')) + if int(rets, 16) == wr_tmp: + RJPRINT("%-30s 0x%02x %s" % (item.get('name'), wr_tmp, 'OK')) + else: + totalerr -= 1 + ermsg = "%s %-30s io_addr: 0x%0x addr:0x%02x val:0x%02x rd:0x%02x \n" % (ermsg, item.get('name'),item.get('io_addr'), item.get('addr'),wr_tmp, int(rets, 16) ) + else: + for wr_tmp1 in item.get('testval'): + rji2cset(item.get('bus'), item.get('devno'),item.get('addr'),wr_tmp1) + ret,ind = rji2cget(item.get('bus'), item.get('devno'),item.get('addr')) + if wr_tmp1 == int(ind, 16): + RJPRINT("%-30s 0x%02x %s" % (item.get('name'), wr_tmp1, 'OK')) + else: + totalerr -= 1 + ermsg = "%s %-30s bus:%3d devno:0x%02x addr:0x%02x 0x%02x rd:%s \n" % (ermsg, item.get('name'),item.get('bus'), item.get('devno'),item.get('addr'), wr_tmp1, ind) + else: + totalerr -= 1 + ermsg = '参数错误' + if totalerr < 0: + RJPRINTERR("\nerrmsg:") + RJPRINTERR(ermsg) + RET[RETURN_KEY1] = totalerr + RET[RETURN_KEY2] = ermsg + return RET + + + +# ==================================== +# cpld test +# ==================================== +def test_cpld(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + for cpld in TESTCASE["CPLD"]: + RJPRINT("测试项: %s" % cpld["name"]) + if "cases" not in cpld: + RJPRINT("没有测试项") + continue + for case in cpld["cases"]: + RJPRINTLINE(case["name"]) + # Gets the command invoked + cmd_t = case["cmd"].lstrip() + cmd = cmd_t[0 : cmd_t.index(" ")] + ret, log = log_os_system("which " + cmd, 0) + if len(log): + cmd = "cmd find " + else: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "no" + cmd +" found" + return RET + log_debug(case["cmd"]) + ret, log = log_os_system(case["cmd"], 0) + log_debug(log) + if ret or ("Error" in log ): + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + RJPRINT("[FAILED]") + else: + RJPRINT("[OK]") + return RET + + +def test_voltage_getValue(item_r): + gettype = item_r.get('gettype') + len = item_r.get('len') + address = item_r.get('io_addr') + calcuvol = item_r.get('formula') + min = item_r.get('minThread') + max = item_r.get('maxThread') + name = item_r.get('name') + bus = item_r.get('bus') + devno = item_r.get('devno') + offset = item_r.get('addr') + select = item_r.get('select') + slectvalue = item_r.get('slectvalue') + val = None + if gettype == 'pagei2c': + rji2cset(bus,devno, select, slectvalue) + ret, ind = rji2cget(bus,devno, offset) + if ret == False: + val = None + else: + val = ind.replace("0x","").replace("0X","") + elif gettype == 'pagei2cword': + rji2cset(bus,devno, select, slectvalue) + ret, ind = rji2cgetWord(bus,devno, offset) + if ret == False: + val = None + else: + val = ind.replace("0x","").replace("0X","") + elif gettype == 'io': + val = io_rd(address, len) + val = "%0x" %(int(val, 16) >> 4) + elif gettype == 'i2c': + i2ctmp = '' + for i in range(0,len): + ret, ind = rji2cget(bus,devno, offset+i) + if ret == False: + i2ctmp = None + break + i2ctmp += ind.replace("0x","").replace("0X","") + if i2ctmp == None: + val = None + else: + val = "%0x" %(int(i2ctmp, 16) >> 4) + return val + + +def test_voltage(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + errmsg ="" + resultval = [] + + voldef = TESTCASE.get("voltagesensors",None) + if voldef is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'config error' + return RET + + # Find the reference value + calu = voldef.get("voltagecal",None) + if calu is None: + RET[RETURN_KEY1] = -997 + RET[RETURN_KEY2] = 'config error' + return RET + + boardtemps = voldef.get('voltages',None) + if boardtemps is None: + RET[RETURN_KEY1] = -998 + RET[RETURN_KEY2] = 'config error' + return RET + try: + for key in boardtemps.keys(): + voltage_tmp = boardtemps.get(key) + reference = None + referenceitem = None + + for item in voltage_tmp: + if item.get('reference',0)==1: + referenceitem = item + if referenceitem is None: + totalerr -= 1 + errmsg += "%s not find config\n" % key + RJPRINT(errmsg) + continue + + val = test_voltage_getValue(referenceitem) + if val is None: + totalerr -= 1 + errmsg += "%s read reference error\n" % key + RJPRINT(errmsg) + continue + result = calu % val + reference = eval(result) + + + if type(val) == str: + log_debug(" %s reference name:%s val type:0x%s val:%f"% (key, referenceitem.get('name'),val, reference)) + if reference is None: + totalerr -= 1 + errmsg += "%s reference cal error\n" % key + else: + for item_r in voltage_tmp: + val_calc = test_voltage_getValue(item_r) + gettype = item_r.get('gettype') + calcuvol = item_r.get('formula') + min = item_r.get('minThread') + max = item_r.get('maxThread') + name = item_r.get('name') + statusmsg = 'N/A' + + if val_calc is None: + totalerr -= 1 + resultval.append([("%s_%s"%(key,name)),'N/A' , min, max, statusmsg]) + continue + if gettype == 'pagei2c': + pagei2c_tmp = calcuvol %(val_calc, val_calc) + val_tmp = eval(pagei2c_tmp) + if gettype == 'pagei2cword': + pagei2c_tmp = calcuvol %(val_calc) + val_tmp = eval(pagei2c_tmp) + elif gettype == 'io' or gettype == 'i2c': + result_curr_tmp = calu % val_calc + result_curr = eval(result_curr_tmp) + result = calcuvol % (result_curr, reference) + val_tmp = eval(result) + if min < val_tmp nowspeed: + RJPRINT(" %s %s : %s"%(fanstatus["name"],speedmsg, "[PASS]")) + else: + RJPRINT(" %s %s : %s"%(fanstatus["name"],speedmsg, "[FAILED]")) + caseerror.append({"name": ("%s %s" %(item_fan.get('name'),fanstatus["name"])) ,"error":"不在转速范围内 [nowspeed: %d low_speed:%d high:%d]" % ( nowspeed ,lowspeed,highspeed)}) + ret_t -= 1 + testind -= 1 + else: + RJPRINT(" %s : %s"%(fanstatus["name"], "[FAILED]")) + caseerror.append({"name": ("%s %s" %(item_fan.get('name'),fanstatus["name"])) ,"error":"获取转速为空"}) + ret_t -= 1 + testind -= 1 + if len(caseerror) > 0: + testerror["name"] = "转速等级:[%s]0x%02x "% (levelpolicy["tips"][ind], level) + testerror['errmsg'] = caseerror + if testind < 0: + errt_t.append(testerror) + except Exception as e: + print (e) + log_error(e.message) + return False + finally: + startFanctrol() + if ret_t < 0: + return ret_t + return ret_t + +def write_sysfs_value(reg_name, value): + retval = 'ERR' + fileLoc = MAILBOX_DIR + reg_name + try: + if not os.path.isfile(fileLoc): + print (fileLoc, 'not found !') + return False + with open(fileLoc, 'w') as fd: + fd.write(value) + except Exception as error: + log_error("Unable to open " + fileLoc + "file !") + return False + return True + + +def get_config_file(filename): + if not os.path.isfile(filename): + return "" + machine_vars = {} + with open(filename) as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + +def get_onie_full_version(): + machine_vars = get_config_file('/host/machine.conf') + return "%s_%s" % (machine_vars.get("onie_version"),machine_vars.get("onie_build_date")) + +def getonieversion(): + if not os.path.isfile('/host/machine.conf'): + return "" + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars.get("onie_version") + + +def fac_board_setmac(): + _value = {} + + try: + onie = onie_tlv() + # default value + _value[onie.TLV_CODE_VENDOR_EXT] = generate_ext(RAGILE_CARDID) # Generates an ID unique to RAGILE + _value[onie.TLV_CODE_PRODUCT_NAME] = RAGILE_PRODUCTNAME + _value[onie.TLV_CODE_PART_NUMBER] = RAGILE_PART_NUMBER + _value[onie.TLV_CODE_LABEL_REVISION] = RAGILE_LABEL_REVISION + _value[onie.TLV_CODE_PLATFORM_NAME] = platform + _value[onie.TLV_CODE_ONIE_VERSION] = getonieversion() + _value[onie.TLV_CODE_MAC_SIZE] = RAGILE_MAC_SIZE + _value[onie.TLV_CODE_MANUF_NAME] = RAGILE_MANUF_NAME + _value[onie.TLV_CODE_MANUF_COUNTRY] = RAGILE_MANUF_COUNTRY + _value[onie.TLV_CODE_VENDOR_NAME] = RAGILE_VENDOR_NAME + _value[onie.TLV_CODE_DIAG_VERSION] = RAGILE_DIAG_VERSION + _value[onie.TLV_CODE_SERVICE_TAG] = RAGILE_SERVICE_TAG + if 0x00004052 == RAGILE_CARDID: + _value[TLV_CODE_PRODUCT_NAME] = RAGILE_PRODUCTNAME + "-RJ" + elif 0x00004051 == RAGILE_CARDID or 0x00004050 == RAGILE_CARDID: + changeTypeValue(_value, TLV_CODE_PRODUCT_NAME, + "产品名称",RAGILE_PRODUCTNAME) + + changeTypeValue(_value, TLV_CODE_SERIAL_NUMBER, + "SN", "0000000000000") # Add serial number + changeTypeValue(_value, TLV_CODE_DEVICE_VERSION, + "硬件版本号", "101") # Hardware Version number + changeTypeValue(_value, TLV_CODE_MAC_BASE, + "MAC地址", "58696cfb2108") # MAC address + _value[TLV_CODE_MANUF_DATE] = time.strftime( + '%m/%d/%Y %H:%M:%S', time.localtime()) # Automatically add setMAC time + rst, ret = onie.generate_value(_value) + if util_setmac("eth0", _value[TLV_CODE_MAC_BASE]) == True: # Setting the NIC IP Address + writeToEEprom(rst) # Write the value to e2 + else: + return False + except SETMACException as e: + # print e + RJPRINTERR("\n\n%s\n\n" % e) + return False + except ValueError as e: + return False + return True + +def generate_ext(cardid): + s = "%08x" % cardid + ret = "" + for t in range(0, 4): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + ret = chr(0x01) + chr(len(ret)) + ret + return ret + + +def test_stop_fanctrol(): + stopFanctrol() + return True,"" + +def test_start_fanctrol(): + startFanctrol() + return True,"" + +def test_power_pmbus_msg(): + '''Obtain PMBUS information about power supplies''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + errmsg = "" + fanstatus = TESTCASE.get("frustatus",None) + if fanstatus is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'config error' + return RET + + psu_pmbus = fanstatus.get('psupmbus', None) + if psu_pmbus is None: + RET[RETURN_KEY1] = -998 + RET[RETURN_KEY2] = 'config error' + return RET + + for item in psu_pmbus: + print (item.get('name')) + loc = item.get('values') + for lo in loc: + retval = "" + rval = None + name = lo.get('displayname') + unit = lo.get('unit') + location = lo.get('location') + min_value = lo.get('min',-999999) + max_value = lo.get('max',999999) + try: + locations = glob.glob(location) + with open(locations[0], 'r') as fd1: + retval = fd1.read() + if unit == 'A' or unit == 'V' or unit == 'C': + rval = float(retval)/1000 + elif unit == 'W': + rval = float(retval)/1000/1000 + else: + rval = float(retval) + if rval >= max_value or rval <= min_value: + totalerr -= 1 + RJPRINT(" %-10s: %.2f %s" %(name, rval, unit)) + except Exception as e: + totalerr -= 1 + errmsg = " %s %s" % (errmsg, str(e)) + RJPRINT(" %-10s: error" %(name)) + RET[RETURN_KEY1] = totalerr + RET[RETURN_KEY2] = errmsg + return RET + +def test_power_status(): + '''Test power supply status''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + fanstatusdecode = TESTCASE.get("frustatusdecode",None) + fanstatus = TESTCASE.get("frustatus",None) + errmsg = "" + + if fanstatus is None or fanstatusdecode is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'config error' + return RET + + psu_conf = fanstatus.get('psus', None) + if psu_conf is None: + RET[RETURN_KEY1] = -998 + RET[RETURN_KEY2] = 'config error' + return RET + + psupresent = fanstatusdecode.get('psupresent') + psuoutput = fanstatusdecode.get('psuoutput') + psualert = fanstatusdecode.get('psualert') + + for item_fan in psu_conf: + retval = None + gettype = item_fan.get('gettype',None) + statusbit = item_fan.get('statusbit') + presentbit = item_fan.get('presentbit') + alertbit = item_fan.get('alertbit') + if gettype is not None and gettype == "io": + io_addr = item_fan.get('io_addr') + val = io_rd(io_addr) + if val is not None: + retval = val + else: + totalerr -=1 + errmsg = " %s %s" % (errmsg, "lpc读取失败") + pass + else: + i2c_addr = item_fan.get('i2c_addr') + bus = i2c_addr['bus'] + devno = i2c_addr['devno'] + reg_offset = i2c_addr['reg_offset'] + ind, val = rji2cget(bus, devno,reg_offset) + if ind == True: + retval = val + else: + totalerr -=1 + errmsg = " %s %s" % (errmsg, "i2c读取失败") + pass + if retval is None: + continue + val_t = (int(retval,16) & (1<< presentbit)) >> presentbit + val_status = (int(retval,16) & (1<< statusbit)) >> statusbit + val_alert = (int(retval,16) & (1<< alertbit)) >> alertbit + msg = "%s \n" \ + " 在位状态: %s\n"\ + " 输出状态: %s \n"\ + " 告警状态: %s \n"% (item_fan.get('name'),psupresent.get(val_t),psuoutput.get(val_status),psualert.get(val_alert)) + RJPRINT(msg) + if val_t != psupresent.get('okval') or val_status != psuoutput.get('okval') or val_alert != psualert.get('okval'): + errmsg += msg + totalerr -=1 + else: + pass + + RET[RETURN_KEY1] = totalerr + RET[RETURN_KEY2] = errmsg + return RET + +def test_fan_speed_average(loc,read_cnt=5,critical_speed=None): + speedlist = [] + max_cnt = read_cnt + 5 # Redundant 5 times + for i in range(0,max_cnt): + real_value = get_pmc_register(loc) + if real_value.isdigit(): + speedlist.append(int(real_value)) + else: + log_debug("fan speed read error,times:%d,loc:%s"%(i,loc)) + if len(speedlist) == read_cnt: + break + time.sleep(0.01) + if len(speedlist) == read_cnt: + log_debug("风扇转速排序前: %s" % speedlist) + speedlist.sort() + log_debug("风扇转速排序后: %s" % speedlist) + if critical_speed is not None and speedlist[read_cnt-1] >= critical_speed: + return speedlist[read_cnt-1] + return speedlist[int((read_cnt -1)/2)] # Take the median + return -1 + + +def test_fan_speed(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret_t = 0 + errmsg ="" + low_speed = fanlevel.get('low_speed')[0] + high_speed = fanlevel.get('high_speed')[2] + for item_fan in fanloc: + RJPRINT(item_fan.get('name')) + for fanstatus in item_fan["childfans"]: + nowspeed = test_fan_speed_average(fanstatus["location"]) + if nowspeed == -1: + RJPRINT(" %s : %s"%(fanstatus["name"], "[FAILED]")) + ret_t -= 1 + continue + if nowspeed not in range(low_speed, high_speed): + ret_t -= 1 + speedmsg = "(%d) not in [%d, %d] failed"% ( nowspeed, low_speed, high_speed) + errmsg = " %s %s %s\n" % (errmsg, fanstatus["name"],speedmsg) + else: + speedmsg = "(%d)"% (nowspeed) + RJPRINT(" %s %s"%(fanstatus["name"],speedmsg)) + RET[RETURN_KEY1] = ret_t + RET[RETURN_KEY2] = errmsg + return RET + +def test_M6510_fan_speed(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + fanspeedcheck = TESTCASE.get("fanspeedcheck",None) + printmsg = "" + speedmsg = "" + errmsg = "" + + if fanspeedcheck is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'config error' + return RET + + low_speed = fanspeedcheck.get("low_speed") + high_speed = fanspeedcheck.get("high_speed") + critical_speed = fanspeedcheck.get("critical_speed") + fanloc = fanspeedcheck.get("fanloc") + speed_read_times = fanspeedcheck.get("speed_read_times") + retry = fanspeedcheck.get("retry") # Retry count + + for item_fan in fanloc: + try: + fan_name = item_fan.get('name') + retry_cnt = 0 + while retry_cnt < retry: # Retry for each fan + nowspeed = test_fan_speed_average(item_fan["speed_loc"],speed_read_times,critical_speed) + log_debug("%s speed:%d retry:%d" % (fan_name,nowspeed,retry_cnt)) + if nowspeed == -1 or nowspeed >= critical_speed: + speedmsg = "%s (%d) not in [%d, %d] failed"% (fan_name, nowspeed, low_speed, high_speed) + totalerr -= 1 + break + if nowspeed <= high_speed and nowspeed >= low_speed: + speedmsg = "%s (%d)"% (fan_name, nowspeed) + break + speedmsg = "%s (%d) not in [%d, %d] failed"% (fan_name, nowspeed, low_speed, high_speed) + retry_cnt += 1 + RJPRINT(" %s"% speedmsg) + if retry_cnt == retry: + totalerr -= 1 + errmsg += (speedmsg + "\n") + except Exception as e: + totalerr -= 1 + errmsg += (srt(e) + "\n") + RET[RETURN_KEY1] = totalerr + RET[RETURN_KEY2] = errmsg + return RET + +def test_fan_status(): + '''Test the fan status online and running''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + fanstatusdecode = TESTCASE.get("frustatusdecode",None) + fanstatus = TESTCASE.get("frustatus",None) + + if fanstatus is None or fanstatusdecode is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'config error' + return RET + + fans_conf = fanstatus.get('fans', None) + if fans_conf is None: + RET[RETURN_KEY1] = -998 + RET[RETURN_KEY2] = 'config error' + return RET + + fanpresent = fanstatusdecode.get('fanpresent') + fanroll = fanstatusdecode.get('fanroll') + + for item_fan in fans_conf: + RJPRINTLINE(item_fan.get('name')) + presentbus = item_fan.get('bus') + presentaddr = item_fan.get('presentloc') + presentbit = item_fan.get('presentbit') + loc = item_fan.get('loc') + childs = item_fan.get('childfans') + ind, val = rji2cget(presentbus, loc,presentaddr) + if ind == True: + val_t = (int(val,16) & (1<< presentbit)) >> presentbit + RJPRINT(fanpresent.get(val_t)) + if val_t != fanpresent.get('okval'): + totalerr -=1 + else: + pass + else: + totalerr -=1 + RJPRINT("在位状态获取失败") + + for child in childs: + RJPRINTLINE(" %s" % child.get('name')) + statusloc = child.get('statusloc', None) + statusbit = child.get('statusbit', None) + ind, val = rji2cget(presentbus, loc, statusloc) + if ind == True: + val_t = (int(val,16) & (1<< statusbit)) >> statusbit + RJPRINT(fanroll.get(val_t)) + if val_t != fanroll.get('okval'): + totalerr -=1 + else: + pass + else: + totalerr -=1 + RJPRINT("状态获取失败") + RET[RETURN_KEY1] = totalerr + return RET + + +def test_fan_speed_new(param=None): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + try: + ret_t = 0 + if param is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'param err' + return RET + param_t = json.loads(param) + speedval = param_t.get('levelval', None) + lowspeed = param_t.get('low', None) + highspeed = param_t.get('high', None) + sleeptime = param_t.get('sleep', None) + + if sleeptime is None or isinstance(sleeptime,int) == False: + RET[RETURN_KEY1] = -998 + RET[RETURN_KEY2] = 'sleeptime param err' + return RET + + if speedval is None or lowspeed is None or highspeed is None: + RET[RETURN_KEY1] = -998 + RET[RETURN_KEY2] = 'speedval/lowspeed/highspeed param err' + return RET + + strtmp = "写入cpld值:0x%02x 阈值: [%d , %d]"% (speedval, lowspeed, highspeed) + RJPRINT(strtmp) + log_debug(strtmp) + + for item in fanloc: + loc = item.get('location') + write_sysfs_value(loc, "0x%02x"% speedval ) + ret_val = get_sysfs_value(loc) + log_debug("写入的值为%s" % ret_val) + time.sleep(sleeptime) + + caseerror = "" + for item_fan in fanloc: + RJPRINT(item_fan.get('name')) + for fanstatus in item_fan["childfans"]: + real_value = get_pmc_register(fanstatus["location"]) + if real_value.isdigit(): + nowspeed = int(real_value) + log_debug("%s (now: %d low:%d high:%d)"% (fanstatus["name"], nowspeed ,lowspeed,highspeed)) + speedmsg = "(%d)"% ( nowspeed) + if lowspeed < nowspeed and highspeed > nowspeed: + RJPRINT(" %s %s : %s"%(fanstatus["name"],speedmsg, "[PASS]")) + else: + RJPRINT(" %s %s : %s"%(fanstatus["name"],speedmsg, "[FAILED]")) + caseerror += "name:%s %s 不在转速范围内 [nowspeed: %d low_speed:%d high:%d] \n" % (item_fan.get('name'),fanstatus["name"], nowspeed ,lowspeed,highspeed) + ret_t -= 1 + else: + RJPRINT(" %s : %s"%(fanstatus["name"], "[FAILED]")) + caseerror += "name: %s %s 获取转速为空 \n" % (item_fan.get('name'),fanstatus["name"]) + ret_t -= 1 + RET[RETURN_KEY1] = ret_t + RET[RETURN_KEY2] = caseerror + except Exception as e: + RET[RETURN_KEY1] = -9999 + RET[RETURN_KEY2] = str(e) + RJPRINT(str(e)) + return RET + +# ==================================== +# Fan Status Detection +# ==================================== +def test_fan(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + log = [] + #sysinfo_showfanmsg_ind = factest_module.get('sysinfo_showfanmsg', 1) + #if sysinfo_showfanmsg_ind == 1: + # log_debug("正在获取风扇信息") + # RJPRINT('%s '% "风扇状态获取") + # totalfanstatus = [] + # status.checkFan(totalfanstatus) + # for fanstatus in totalfanstatus: + # RJPRINT('%s%s: %s'% (fanstatus["id"], "状态 ", fanstatus["errmsg"])) + # RJPRINT('') + + RJPRINT('%s '% "风扇转速设置") + ret = fan_check1(fanloc, fanlevel, log) + if ret == 0: + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + else: + RET[RETURN_KEY1] = ret + RET[RETURN_KEY2] = log + return RET + + +def M6510_check(fanlevelcheck): + RET = {"status" : "", "printmsg":"","errmsg" : ""} + errcnt = 0 + failcnt = 0 + printmsg = "" + speedmsg = "" + errmsg = "" + + fanlevel = fanlevelcheck.get("fanlevel") + level_loc = fanlevelcheck.get("level_loc") + fanloc = fanlevelcheck.get("fanloc") + critical_speed = fanlevelcheck.get("critical_speed") + sleep_time = fanlevelcheck.get("sleep") + speed_read_times = fanlevelcheck.get("speed_read_times") + + try: + for level in fanlevel: + tips = level.get("tips") + fan_level = level.get("level") + lowspeed = level.get("low_speed") + highspeed = level.get("high_speed") + strtmp = "风扇转速等级: 【%s】 写入cpld值:0x%02x 阈值: [%d , %d]\n"% (tips, fan_level,lowspeed,highspeed) + log_debug(strtmp) + errmsg += strtmp + printmsg += strtmp + + write_sysfs_value(level_loc, "0x%02x"% fan_level ) + ret_val = get_sysfs_value(level_loc) + log_debug("写入的值为%s" % ret_val) + time.sleep(sleep_time) + + for fan_item in fanloc: + name = fan_item.get("name") + speed_loc = fan_item.get("speed_loc") + nowspeed = test_fan_speed_average(speed_loc,speed_read_times,critical_speed) + speedmsg = "(%d)"% ( nowspeed) + log_debug("%s (now: %d low:%d high:%d)"% (name, nowspeed ,lowspeed,highspeed)) + if nowspeed != -1 and nowspeed < critical_speed: + if nowspeed >= lowspeed and nowspeed <= highspeed: + strtmp = " %s %s : %s\n"%(name,speedmsg, "[PASS]") + else: + strtmp = " %s %s : %s\n"%(name,speedmsg, "[FAILED]") + errmsg += "%s 不在转速范围内 [nowspeed: %d low_speed:%d high:%d]\n" % (name,nowspeed ,lowspeed,highspeed) + failcnt -= 1 + else: + strtmp = " %s %s : %s" % (name,speedmsg, "[FAILED]") + errmsg += "%s 不在转速范围内 [nowspeed: %d low_speed:%d high:%d]\n" % (name,nowspeed ,lowspeed,highspeed) + errcnt -= 1 + printmsg += strtmp + RET["printmsg"] = printmsg + RET["errmsg"] = errmsg + if errcnt < 0: + RET["status"] = "error" + elif failcnt < 0: + RET["status"] = "fail" + else: + RET["status"] = "pass" + except Exception as e: + RET["status"] = "fail" + RET["printmsg"] = str(e) + RET["errmsg"] = str(e) + log_error(e.message) + return RET + +# ==================================== +# M6510 Fan Status Detection +# ==================================== +def test_M6510_fan(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + fanlevelcheck = TESTCASE.get("fanlevelcheck",None) + printmsg = "" + speedmsg = "" + errmsg = "" + + if fanlevelcheck is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'config error' + return RET + retry = fanlevelcheck.get("retry") # Retry count + + RJPRINT('%s '% "风扇转速设置") + for i in range(retry): + try: + ret = M6510_check(fanlevelcheck) + if ret.get("status") == "pass": + RET[RETURN_KEY1] = 0 + break + elif ret.get("status") == "error": + RET[RETURN_KEY1] = -1 + break + else : + RET[RETURN_KEY1] = -1 + except Exception as e: + log = traceback.format_exc() + log_error(log) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + RJPRINT(ret.get("printmsg")) + RET[RETURN_KEY2] = ret.get("errmsg") + return RET + + +# ==================================== +# CPU memory test +# ==================================== +def test_cpumemoryinfo(): + RET = ERROR_RETURN + cmd = "" + ret, log = log_os_system("which memtester", 0) + if len(log): + cmd = "memtester " + else: + RET[RETURN_KEY2] = "no memtester cmd" + return RET + for case in TESTCASE["MEMTORY"]["cases"]: + RJPRINT("测试项: %s" %case["name"]) + log_debug("case: %s [%s]" % (case["name"] , case["cmd"])) + os.system(case["cmd"]) + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + return RET + +ddr_test_result_file = "/tmp/ddr_test_result" +thread_test_ddr = None; + +def test_ddr_stress_with_result(): + test_ddr_stress() + print_temp("后台执行测试,等待100s", False) + time.sleep(100) + return test_ddr_stress_result() + +def test_ddr_stress(): + global thread_test_ddr + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + ret, log = log_os_system("which stressapptest", 0) + if len(log): + if thread_test_ddr != None: + RET[RETURN_KEY2] = "已有DDR后台执行任务,请首先查看测试结果或终止上次测试任务" + RJPRINT(RET[RETURN_KEY2]) + return RET + RET[RETURN_KEY2] = "已启动后台执行" + cmd = "free -m|grep Mem" + ret, log = rj_os_system(cmd) + if "Mem" not in log: + RJPRINT("Memory info get fail.log=%s, cmd=%s" % (log, cmd)) + RET[RETURN_KEY1] = -1 + return RET + tmp = log.split() + mem_test_size = int(tmp[1]) - int(tmp[2]) - 350 # tmp[1]total,tmp[2] used,200 reserve + ''' + total used free shared buffers cached +Mem: 7896 1247 6649 58 188 343 + ''' + cmd = "stressapptest -M %d -m 1 -s 3600" % mem_test_size + with open(ddr_test_result_file, "w+") as f: + # thread_test_ddr = subprocess.Popen("stressapptest -M 512 -m 1 -s 86400",shell=True,stdout=subprocess.PIPE) + thread_test_ddr = subprocess.Popen(cmd, shell=True, stdout=f) + else: + RET[RETURN_KEY2] = "no stressapptest cmd" + RJPRINT(RET[RETURN_KEY2]) + return RET + + +def test_ddr_stress_stop(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + global thread_test_ddr + if thread_test_ddr == None: + RET[RETURN_KEY2] = "未启动后台测试" + RJPRINT(RET[RETURN_KEY2]) + return RET + if not makesure("强行结束将无法查看结果,是否继续?[Yes/No]:",echo = True): + RET[RETURN_KEY2] = "已撤销" + RJPRINT(RET[RETURN_KEY2]) + return RET + thread_test_ddr.terminate() + + cmd = "kill -9 %d"%(thread_test_ddr.pid + 1) + # Regardless of the output + ret, log = log_os_system(cmd, 0) + RET[RETURN_KEY2] = "该后台测试已被终止" + thread_test_ddr = None + RJPRINT(RET[RETURN_KEY2]) + return RET + +def force_abort_ddr_stress(): + log_os_system("ps -ef | grep stressapptest | grep -v grep | awk '{print $2}' | xargs kill -9 ", 0) + +def test_ddr_stress_result(): + global thread_test_ddr + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + if thread_test_ddr == None: + RJPRINT("未启动后台测试,没有测试结果") + return RET + + ret, log = log_os_system("ps -ef | grep stressapptest | grep -v grep | awk '{print $2}'", 0) + if len(log): + RJPRINT("测试还未结束,测试时长60mins, 请稍后查看结果") + return RET + thread_test_ddr = None + bufferSize = 50000 + input = "" + resuult = "" + + try: + file = os.open(ddr_test_result_file, os.O_RDONLY | os.O_NONBLOCK); + input = os.read(file, bufferSize); + resuult = input + os.close(file) + except OSError as err: + if err.errno == 11:# Zero, with a small probability + resuult = "没有数据" + os.close(file) + + if "Status: PASS" not in resuult: + RET[RETURN_KEY1] = -1 + else: + RET[RETURN_KEY1] = 0 + RET[RETURN_KEY2] = resuult + RJPRINT(RET[RETURN_KEY2]) + return RET + +# ==================================== +# hard disk test +# ==================================== +def test_hard(): + RET = ERROR_RETURN + cmd = "" + ret, log = log_os_system("which smartctl", 0) + if len(log): + cmd = "smartctl " + else: + RET[RETURN_KEY2] = "no smartctl cmd" + return RET + for case in TESTCASE["SMARTCTLCMDS"]["cases"]: + RJPRINT("测试项: %s" %case["name"]) + log_debug("case: %s [%s]" % (case["name"] , case["cmd"])) + os.system(case["cmd"]) + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + return RET + +# ==================================== +# Setting a Log Level +# ==================================== +def test_log_setlevel(name): + logger = logging.getLogger() # initialize logging class + logger.setLevel(levelNames[name]) # default log level + +def test_log_critical(): + test_log_setlevel("CRITICAL") +def test_log_debug(): + test_log_setlevel("DEBUG") +def test_log_error(): + test_log_setlevel("ERROR") +def test_log_info(): + test_log_setlevel("INFO") +def test_log_notset(): + test_log_setlevel("NOTSET") +def test_log_warning(): + test_log_setlevel("WARNING") + +# Log output level menu +def test_loginfolevel(): + logger = logging.getLogger() # initialize logging class + RJPRINT("当前调试等级为: %s" % levelNames[logger.level]) + startMenu(3) + +# Signal processing: No processing ctrl + N +def sigint_handler(signum, frame): + global KAOJISTATUS + KAOJISTATUS = 0 + if ISKAOJI == 1: + RJPRINT("\n\n已经输入ctrl+c 请等待本轮执行结束") + else: + RJPRINT("\n\n不接收ctrl+c退出") + +signal.signal(signal.SIGINT, sigint_handler) +signal.signal(signal.SIGHUP, sigint_handler) +signal.signal(signal.SIGTERM, sigint_handler) + +# configuration +def test_config(): + if load_CONFIG() == False: + sys.exit(1) + +# ==================================== +# Test item: Verify file MD5 +# ==================================== +def checkFileMD5(filename): + if not os.path.isfile(filename): + return + myhash = hashlib.md5() + f = file(filename,'rb') + while True: + b = f.read(8096) + if not b : + break + myhash.update(b) + f.close() + return myhash.hexdigest() + +# ==================================== +# Test item: Port broadcast +# ==================================== +def test_portbroadcast(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + for i in range(3): + try: + ret, log = test_port() + if ret: + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : log} + break + else : + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + except Exception as e: + log = traceback.format_exc() + log_error(log) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + RJPRINT(log) + return RET + +# ==================================== +# Test item:prbs +# ==================================== +def test_prbs(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + for i in range(3): + try: + ret, log = test_port_prbs() + if ret: + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : log} + break + else : + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + except Exception as e: + log = traceback.format_exc() + log_error(log) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + RJPRINT(log) + return RET + +def test_prbs_new(): + '''PRBS new method to test add 20190411''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret, log = test_ports_prbs_new() + if ret: + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + else : + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + return RET + +def test_bmc_channel(): + '''Testing the BMC Path''' + ip = TESTCASE.get('BMC').get('ip') + port = TESTCASE.get('BMC').get('port') + msg = '' + returncode = False + import socket + try: + sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sk.settimeout(10) + sk.connect((ip,port)) + returncode = True + except Exception: + msg = '到BMC通路失败,请确认' + returncode = False + finally: + sk.close() + return returncode, msg + +# =================================================================== +# Test item:Load CPU side GPIO analog MDIO driver, disable BMC side MDIO +# =================================================================== +def test_modprobe_cpu_gpio_mdio(): + ret, msg = test_bmc_channel() + if ret is False: + return ret, msg + func = 'bmc_log_os_system' + cmd = "devmem 0x1e6e2090 32 0x087f0009" # disable bmc mdio + ret = test_bmc_func(func,cmd) + if ret[RETURN_KEY1] != 0: + return ret, msg + " disable bmc mdio fail" + cmd = "modprobe rg_gpio_mdio" + ret, msg = log_os_system(cmd, 0) + if ret != 0: + return ret, msg + " modprobe rg_gpio_mdio fail" + time.sleep(1) + return True, '' + +# =================================================================== +# Test item: Unmount the GPIO analog MDIO driver on the CPU and enable the MDIO on the BMC +# =================================================================== +def test_rmmod_cpu_gpio_mdio(): + ret, msg = test_bmc_channel() + if ret is False: + return ret, msg + func = 'bmc_log_os_system' + cmd = "devmem 0x1e6e2090 32 0x087F000D" # enable bmc mdio + ret = test_bmc_func(func,cmd) + if ret[RETURN_KEY1] != 0: + return False, msg + " enable bmc mdio fail" + cmd = "rmmod rg_gpio_mdio" + ret, msg = log_os_system(cmd, 0) + if ret != 0: + return ret, msg + " rmmod rg_gpio_mdio fail" + return True, '' + +# =================================================================== +# Test item :CPU side MDIO test +# =================================================================== +def test_cpu_gpio_mdio(): + RET = {RETURN_KEY1: 0, RETURN_KEY2: ""} + errtotal = 0 + MDIO_dev_dict = { + "BMC-54616 ": ["11"], + "MGMT-54616": ["18"], + "5387 ": ["00", "01", "02", "03", "04", "05", "06", "07"], + } + + for dev in MDIO_dev_dict.keys(): + check_log = "" + dev_errtotal = 0 + for i in MDIO_dev_dict[dev]: + cmd = "cat /sys/bus/mdio_bus/devices/gpio-0:%s/hw_test*" % i + ret, log = log_os_system(cmd, 0) + if "reg" in log: + check_log += i + ": PASS\n" + else: + check_log += i + ": FAILD\n" + dev_errtotal -= 1 + errtotal += dev_errtotal + if dev_errtotal < 0: + log_debug(dev + " : FAILED") + log_debug(check_log) # Prints detailed error information + else: + log_debug(dev + " : PASS") + + if errtotal < 0: + RET[RETURN_KEY1] = -1 + return RET + +# =================================================================== +# Test item :CPU side MDIO pressure test +# =================================================================== +def cpu_test_MDIO_stress(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 :""} + totalerr = 0 + test_times = 10 + for i in range(0, test_times): + log_debug("\n\n第 %d/%d 次测试"%(i+1, test_times)) + RET1 = test_cpu_gpio_mdio() + totalerr += RET1[RETURN_KEY1] + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +# ==================================== +# Test item: port sending and receiving frames +# ==================================== +def test_portframe(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + for i in range(3): + try: + ret, log = test_port_portframe() + if ret: + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : log} + break + else : + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + except Exception as e: + log = traceback.format_exc() + log_error(log) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + RJPRINT(log) + return RET + + +def get_raw_input(): + ret="" + fd=sys.stdin.fileno() + old_ttyinfo=termios.tcgetattr(fd) + new_ttyinfo=old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + try: + termios.tcsetattr(fd,termios.TCSANOW,new_ttyinfo) + ret=raw_input("") + except Exception as e: + print (e) + finally: + termios.tcsetattr(fd,termios.TCSANOW,old_ttyinfo) + return ret + + +def test_port_portframe(): + '''Port frame''' + framenum = 10000 + porttest = PortTest() + len_t = len(porttest.bcm_ports) + upports = [] + ret_t = 0 + errt_t = [] + testerror ={} + caseerror=[] + testerror["name"] = "端口收发帧" + successport=[] + updownerrport=[] + errorport = [] + try: + # All values UP Port PRBS + for i in range(len_t): + status = porttest.get_port_status(i + 1) + if status == "up": + upports.append(i + 1) + else: + updownerrport.append(i+1) + if len(updownerrport) > 0: + ret_t -= 1 + pass + else: + porttest.init_port_cpu() + porttest.clear_port_packets() + for i in range(len(porttest.bcm_ports)): + if (i + 1) in upports : + porttest.start_send_port_packets(i + 1, framenum, 1024) + log_debug("%d:正在发包"%(i+1)) + time.sleep(5) + for i in range(len(porttest.bcm_ports)): + if (i + 1) in upports : + ret, log = porttest.check_port_packets(i + 1, framenum, "rx") + log_debug(ret) + if ret == True: + successport.append(i + 1) + else: + errorport.append(i + 1) + ret_t -= 1 + caseerror.append({"name":"端口%d"%(i + 1), "error":"端口收发帧失败"}) + log_debug(log) + else: + ret_t -= 1 + caseerror.append({"name":"端口%d"%(i + 1), "error":"up/down状态异常"}) + updownerrport.append(i+1) + except Exception as e: + msg = traceback.format_exc() + log_error(msg) + ret_t = -1 + return False , msg + finally: + porttest.reset_port_cpu() + result_str = '' + result_str += print_to_str(successport, "OK") + result_str += print_to_str(updownerrport, "up/down error") + result_str += print_to_str(errorport, "failed") + testerror['errmsg'] = caseerror + errt_t.append(testerror) + if ret_t < 0: + return False , result_str + return True , result_str + + +def test_ports_prbs_new(): + '''port prbs''' + + result_t = [] + testerror1 = {} + testerror1["name"] = "PRBS测试(phy到mac)" + testerror2 = {} + testerror2["name"] = "PRBS测试(mac到phy)" + testerror3 = {} + testerror3["name"] = "PRBS测试(phy到line)" + retrytime = 0 + total_err = 0 + pr = None + val_ber = TESTCASE.get("PRBS").get("prbsber", None) # 1.0e-8 + totalretrys = TESTCASE.get("PRBS").get("retrytimes", None) # 1.0e-8 + # print val_ber + macprbsresult = {"success":[], "error":[]} + sysprbsresult = {"success":[], "error":[]} + lineprbsresult = {"success":[], "error":[]} + + if val_ber is not None: + pr = PortPrbsTest(val_ber) + else: + pr = PortPrbsTest() + for i in range(len(pr.bcm_ports)): + macprbsresult.get('error').append((i+1)) + sysprbsresult.get('error').append((i+1)) + lineprbsresult.get('error').append((i+1)) + + while len(macprbsresult.get('error'))> 0 or len(sysprbsresult.get('error')) > 0 or len(lineprbsresult.get('error'))> 0: + if retrytime >= totalretrys: + break + else: + ret,log = pr.clear_port_prbs() + if ret == False: + raise Exception("prbs清除 %s" % log) + ret, log = pr.init_port_prbs() + if ret == False: + raise Exception("prbs初始化失败 %s" % log) + + caseerror=[] + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("mac", i + 1) + if ret == True: + if (i+1) in macprbsresult.get('error'): + macprbsresult.get('error').remove((i+1)) + macprbsresult.get('success').append((i+1)) + else: + if retrytime == (totalretrys -1): + total_err -= 1 + caseerror.append({"name":"端口%03d"%(i + 1), "error":str(result)}) + log_debug("mac 端口%03d error:%s" % ((i + 1), str(result))) + if retrytime == (totalretrys -1): + testerror1['errmsg'] = caseerror + + + caseerror=[] + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("sys", i + 1) + if ret == True: + if (i+1) in sysprbsresult.get('error'): + sysprbsresult.get('error').remove((i+1)) + sysprbsresult.get('success').append((i+1)) + else: + if retrytime == (totalretrys -1): + total_err -= 1 + caseerror.append({"name":"端口%03d"%(i + 1), "error":str(result)}) + log_debug("sys 端口%03d error:%s" % ((i + 1), str(result))) + if retrytime == (totalretrys -1): + testerror2['errmsg'] = caseerror + + + caseerror=[] + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("line", i + 1) + if ret == True: + if (i+1) in lineprbsresult.get('error'): + lineprbsresult.get('error').remove((i+1)) + lineprbsresult.get('success').append((i+1)) + else: + if retrytime == (totalretrys -1): + total_err -= 1 + caseerror.append({"name":"端口%03d"%(i + 1), "error":str(result)}) + log_debug("line 端口%03d error:%s" % ((i + 1), str(result))) + if retrytime == (totalretrys -1): + testerror3['errmsg'] = caseerror + + ret,log = pr.clear_port_prbs() + if ret == False: + raise Exception("prbs清除 %s" % log) + time.sleep(10) + + if retrytime == (totalretrys -1): + result_t.append(testerror1) + result_t.append(testerror2) + result_t.append(testerror3) + retrytime += 1 + + if len(macprbsresult.get('error')) == 0: + RJPRINT("mac prbs测试结果: PASS") + else: + RJPRINT("mac prbs测试结果: FAIL") + port_totalprint(macprbsresult.get('error'),"failed") + + if len(sysprbsresult.get('error')) == 0: + RJPRINT("sys prbs测试结果: PASS") + else: + RJPRINT("sys prbs测试结果: FAIL") + port_totalprint(sysprbsresult.get('error'),"failed") + + if len(lineprbsresult.get('error')) == 0: + RJPRINT("line prbs测试结果: PASS") + else: + RJPRINT("line prbs测试结果: FAIL") + port_totalprint(lineprbsresult.get('error'),"failed") + + if total_err < 0: + return False , result_t + return True ,"" + +# port prbs +def test_port_prbs(): + ret_t = 0 + # Take port + porttest = PortTest() + len_t = len(porttest.bcm_ports) + errmsg = [] + upports = [] + successport=[] + updownerrport=[] + errorport = [] + try: + # Obtain the UP/DOWN status of the port + for i in range(len_t): + status = porttest.get_port_status(i + 1) + if status == "up": + upports.append(i + 1) + else: + updownerrport.append(i+1) + log_debug(",".join(str(index) for index in upports)) + if len(updownerrport) > 0: + ret_t -= 1 + pass + else: + porttest.init_port_prbs() + for i in range(len_t): + porttest.set_port_prbs(i + 1, 1) + time.sleep(5) + # get values + for i in range(len_t): + log_debug("端口prbs校验:%d"% (i + 1)) + ret = porttest.get_port_prbs_result(i + 1) + if ret == 0: + successport.append(i + 1) + else: + errorport.append(i + 1) + ret_t -= 1 + # All values UP Port PRBS + except Exception as e: + msg = traceback.format_exc() + log_error(msg) + ret_t = -1 + return False , msg + finally: + for i in range(len_t): + porttest.set_port_prbs(i + 1, 0) + porttest.reset_port_prbs() + time.sleep(5) + result_str = '' + result_str += print_to_str(successport, "OK") + result_str += print_to_str(updownerrport, "up/down error") + result_str += print_to_str(errorport, "failed") + if ret_t < 0: + return False , result_str + return True ,result_str + + +# Port broadcast test +def test_port(): + # errt_t = [] + ret_t = 0 + porttest = PortTest() + # Take port + len_t = len(porttest.bcm_ports) + + successport=[] + updownerrport=[] + errorport = [] + upports = [] + try: + # Obtain the UP/DOWN status of the port + for i in range(len_t): + status = porttest.get_port_status(i + 1) + if status == "up": + upports.append(i + 1) + else: + updownerrport.append(i+1) + if len(updownerrport) > 0: + ret_t -= 1 + pass + else: + # All ports must be up before testing, and broadcast packets are sent through the first port + log_debug("发送广播报文...") + ret = porttest.start_send_port_packets(1, 10000) + # Waiting time + time.sleep(GRTD_BROADCAST_RETRY_SLEEP_TIME) + log_debug("等待结果......") + for i in range(len_t): + ret , fcs = porttest.get_port_fcs_status(i + 1) + if ret == True and fcs[0] == 0 and fcs[1] == 0: + successport.append(i + 1) + else: + ret_t -= 1 + errorport.append(i + 1) + log_debug("error: 端口%d 发送校验:%d 接收校验 %d" %( (i + 1), fcs[0], fcs[1]) ) + except Exception as e: + msg = traceback.format_exc() + log_error(msg) + ret_t = -1 + return False , msg + finally: + # Close the radio + sta = porttest.stop_send_port_packets() + time.sleep(5) + result_str = '' + result_str += print_to_str(successport, "OK") + result_str += print_to_str(updownerrport, "up/down error") + result_str += print_to_str(errorport, "failed") + if ret_t < 0: + return False , result_str + return True ,result_str + +def startFanctrol(): + if STARTMODULE['fancontrol'] == 1: + cmd = "nohup fancontrol.py start >/dev/null 2>&1 &" + rets = getPid("fancontrol.py") + if len(rets) == 0: + os.system(cmd) + + +def getUsbLocation(): + dir = "/sys/block/" + spect = "sd" + usbpath = "" + result = searchDirByName(spect, dir) + if len(result) <= 0: + return False + for item in result: + with open(os.path.join(item, "removable"), 'r') as fd: + value = fd.read() + if value.strip() == "1": # USB flash drive is found + usbpath = item + break + if usbpath == "": # No flash drive was found + log_debug("no usb found") + return False, usbpath + return True, usbpath + +def searchDirByName(name, dir): + result = [] + try: + files = os.listdir(dir) + for file in files: + if name in file: + result.append(os.path.join(dir, file)) + except Exception as e: + pass + return result + + + +def getusbinfo(): + ret, path = getUsbLocation() + if ret == False: + return False, "not usb exists" + str = os.path.join(path, "size") + ret, value = getfilevalue(str) + if ret == True: + return True, {"id": os.path.basename(path), "size": float(value) * 512 / 1024 / 1024 / 1024} + else: + return False, "Err" + + +def stopFanctrol(): + '''Disable the fan timing service''' + if STARTMODULE['fancontrol'] == 1: + rets = getPid("fancontrol.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + time.sleep(3) + return True + + +# ==================================== +# Test item: Check the CPLD version +# ==================================== +def test_cpldversion(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret, log = log_os_system("which grtd_test.py", 0) + if len(log): + cmd = "cmd find " + else: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = " [FAILED]:no grtd_test.py found" + RJPRINT(RET[RETURN_KEY2]) + return RET + ret, log = log_os_system("grtd_test.py sys cpld_version", 0) + log_debug(log) + if ret or ("Error" in log ): + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + RJPRINT(" [FAILED]:CPLD版本读取失败") + else: + RJPRINT(log) + return RET + + +def test_cpu_stress_stop(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + global cpu_stress_test + if cpu_stress_test: + ret, log = log_os_system("ps -ef | grep \"stress -c 4\" | grep -v grep | awk '{print $2}' | xargs kill -9 ", 0) + if ret or len(log): + RET[RETURN_KEY2] = "取消压力测试异常:%s"%log + else: + RET[RETURN_KEY2] = "该后台测试已被终止" + cpu_stress_test = False + else: + RET[RETURN_KEY2] = "未启动后台测试" + RJPRINT(RET[RETURN_KEY2]) + return RET + +# ==================================== +# Test item :USB test +# ==================================== +def test_usb(): + ret , info = getusbinfo(); + if ret == True: + RJPRINT("%s %s"%("-"*6,"-"*20)) + RJPRINT("{id} {size}G".format(**info)) + return {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + else: + log_debug(info) + RJPRINT("读取USB信息失败") + return {RETURN_KEY1 : -1, RETURN_KEY2 : "读取USB信息失败"} + + + +def test_usb2(test_times = 1): + totalerr = 0 + errmsg = "" + RET = test_usb() + if RET[RETURN_KEY1] == -1: + return RET + # print_clean()# Prevents printing the contents of test_USB + ret,info = getusbinfo() + usb_dev = info["id"] + cmd = "fdisk -l |grep '%s'|grep 'Disk' -v|sort -k4 |tail -n1|awk '{print $1;}'"%usb_dev + ret, usb_disk = log_os_system(cmd,0) + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + # Generate test files + ret, log = log_os_system("dd if=/dev/random of=/tmp/file.txt bs=1M count=10", 0) + ret, log = log_os_system("mkdir /tmp/usb_stress_test && mount %s /tmp/usb_stress_test/"%usb_disk, 0) + if ret != 0 or len(log) > 0: + RJPRINT(log) + RJPRINT("挂载U盘 FAILED") + totalerr -= 1 + else: + for i in range(0, test_times): + if test_times != 1: + RJPRINT("\n\n第 %d/%d 次测试"%(i+1, test_times)) + + cmd = 'cp -rf /tmp/file.txt /tmp/usb_stress_test/file.txt' + ret, log = log_os_system(cmd,0) + if ret != 0 or len(log) > 0: + RJPRINT( log) + RJPRINT( "拷贝文件 FAILED") + totalerr -= 1 + else: + RJPRINT( "拷贝文件 PASS") + + cmd = 'diff /tmp/file.txt /tmp/usb_stress_test/file.txt' + ret, log = log_os_system(cmd,0) + if ret != 0 or len(log) > 0: + RJPRINT( "校验文件 FAILED") + totalerr -= 1 + else: + RJPRINT( "校验文件 PASS") + + cmd = 'rm -rf /tmp/usb_stress_test/file.txt' + ret, log = log_os_system(cmd,0) + if ret != 0 or len(log) > 0: + RJPRINT( log) + RJPRINT( "删除文件 FAILED") + totalerr -= 1 + else: + RJPRINT( "删除文件 PASS") + + ret, log = log_os_system("umount /tmp/usb_stress_test", 0) + ret, log = log_os_system("rm /tmp/usb_stress_test -r", 0) + ret, log = log_os_system("rm /tmp/file.txt", 0) + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def test_usb_stress(): + return test_usb2(10) + + +def test_bmc_setmac(): + while bmc_setmac() == False: + pass + return {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + +def test_e2_setmac(): + while fac_board_setmac() == False: + pass + return {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + +# ==================================== +# Test item: fan SETMAC +# ==================================== +def test_fan_setmac(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + try: + stopFanctrol() + if(fac_fans_setmac() == False): + totalerr -= 1 + except Exception as e: + RJPRINTERR(e) + totalerr -= 1 + finally: + startFanctrol() + RET[RETURN_KEY1] = totalerr + return RET + +pidfile = 0 +############################################################################################ +## File lock +############################################################################################ +def ApplicationInstance(): + global pidfile + pidfile = open(os.path.realpath(__file__), "r") + try: + fcntl.flock(pidfile, fcntl.LOCK_EX | fcntl.LOCK_NB) #创建一个排他锁,并且所被锁住其他进程不会阻塞 + except: + RJPRINT("已有一个程序在运行...." ) + sys.exit(1) + +def fac_init_setmac(): + if getsyseeprombyId(TLV_CODE_PRODUCT_NAME) == None or getsyseeprombyId(TLV_CODE_SERIAL_NUMBER) == None or\ + getsyseeprombyId(TLV_CODE_MAC_BASE) == None or getsyseeprombyId(TLV_CODE_DEVICE_VERSION) == None : + log_debug("需要重新setmac") + return False + return True + +def fac_sensors_kill(): + cmdstr = "docker exec pmon ps -ef | grep sensord | grep -v grep | cut -c 9-15 | xargs docker exec pmon kill -s 9" + try: + log_debug("正在停止sensord服务") + ret, status = rj_os_system(cmdstr) + if ret != 0: + RJPRINT("停止sensord服务异常,请确认") + except: + pass + +def fac_init(): + global DIAGTEST + firmware_check() # firmware testing + if DIAGTEST == False: # Enter the menu setMac by ATE itself to maintain consistency + fac_setmac_check() # setmac check + waitForSDK() # wait SDK + closeProtocol() # Close the deal + if FACTESTMODULE.get("sensord",0)==1: # sensord Background processes + fac_sensors_kill() + if FACTESTMODULE.get("firmware_init",0)==1: # Firmware initialization + fac_firmware_init() + if FACTESTMODULE.get("usb0_config",0)==1 and bmc_presence_check(): # USB0 IP configuration + ret_t = usb0_init() + if ret_t == False: + RJPRINT("配置SONIC端USB网口失败,请手动配置") + + RJPRINT("") + +def fac_init_check_ipmi(): + if not os.path.exists("/dev/ipmi0"): + ret, log = log_os_system("rmmod ipmi_watchdog; rmmod ipmi_si; modprobe ipmi_msghandler; modprobe ipmi_si trydefaults=1 tryacpi=1;modprobe ipmi_devintf", 0) + if not os.path.exists("/dev/ipmi0"): + msg =" 无/dev/ipmi0设备,请检查" + RJPRINT(msg) + return False + return True + +def fac_setmac_check(): + # Check the CARD ID + if fac_init_cardidcheck() == False: + RJPRINTERR("\n\n板卡ID检测失败,请确认!\n\n") + sys.exit(-1); + + # setmac check + if fac_init_setmac() is False: + RJPRINT("未检测到SETMAC信息, 请先进入系统配置执行E2SETMAC") + +def io_rd(reg_addr, len =1): + '''io read''' + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str = os.read(fd, len) + return "".join(["%02x"% ord(item) for item in str]) + except ValueError: + return None + except Exception as e: + print (e) + return None + finally: + os.close(fd) + return None + + +def io_wr(reg_addr, reg_data): + '''io write''' + try: + regdata = 0 + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + if type(reg_data) == int: + regdata = reg_data + else: + regdata = int(reg_data, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + ret = os.write(fd, chr(regdata)) + return True + except ValueError as e: + print (e) + return False + except Exception as e: + print (e) + return False + finally: + os.close(fd) + return False + +def getBMCMAC(): + cmd = "ipmitool lan print 1 | grep 'MAC Address'" + ret , status = rj_os_system(cmd) + if ret == 0: + return status[status.index(":") + 1:len(status)].strip().upper() + else: + RJPRINTERR("获取BMC MAC失败[%s]" % status) + return None + +def checkkallsyms(name): + symsisexistcmd = "cat /proc/kallsyms | grep %s | wc -l" % name + status, output = log_os_system(symsisexistcmd, 0) + # System execution error + if status: + return False + if output.isdigit() and int(output) > 0: # symbol + return True + else: + return False + +def checksignaldriver(name): + modisexistcmd = "lsmod | grep %s | wc -l" % name + status, output = log_os_system(modisexistcmd, 0) + # System execution error + if status: + return False + if output.isdigit() and int(output) > 0: + return True + else: + return False + +def adddriver(name, delay): + cmd = "modprobe %s" % name + if checksignaldriver(name) != True: + log_os_system(cmd, 0) + if delay != 0: + time.sleep(delay) + log_debug('%s sleep %d second!' %(name,delay)) + +def removedriver(name, delay): + realname = name.lstrip().split(" ")[0]; + cmd = "rmmod -f %s" % realname + if checksignaldriver(realname): + log_os_system(cmd, 0) + if delay != 0: + time.sleep(delay) + log_debug('%s sleep %d second!' %(name,delay)) +''' +# Select the packet sending mode during the rate switching test of the management port +def test_mgmt_packet_send(issonic = True,packet_count = 2000): + if issonic: + sendp(Ether(dst='FF:FF:FF:FF:FF:FF',src='00:00:00:00:00:03')/ARP(op=1), iface='eth0', count=packet_count) + else: + cmd = "ssh root@240.1.1.1 'export %s && ftg100_tool tx %d'"%(BMC_PATH,packet_count) + ret, log = password_command(cmd,OPENBMC_PASSWORD) + if "packet" not in log: + raise Exception,"发送数据包出错:\n"+log + time.sleep(3) +''' + +def print_to_str(arr, tips): + return_str = '' + alias = TESTCASE.get('port_alias',None) + if len(arr) <= 0: + return_str += "\n" + return return_str + return_str += "%-20s" % tips + for index in range(len(arr)): + if alias is not None: + return_str += ("%s" % alias.get(arr[index],"unkowned")) + else: + return_str += ("%03d" % arr[index]) + return_str +=(" ") # Add a space + if (index + 1) % 8 == 0: + return_str += "\n" + return_str += (" " * 20) + return_str += "\n" + return return_str + +def port_totalprint(arr, tips): + '''Print out in format (with transcoding)''' + alias = TESTCASE.get('port_alias',None) + if len(arr) <= 0: + return + RJPRINTLINE("%-20s" % tips) + for index in range(len(arr)): + if alias is not None: + RJPRINTLINE("%s" % alias.get(arr[index],"unkowned")) + else: + RJPRINTLINE("%03d" % arr[index]) + if (index + 1) % 8 == 0: + RJPRINT("") + RJPRINTLINE(" " * 20) + RJPRINT("") + +def getmgmtrx(): + mgmtrxloc = "/eth0/statistics/rx_packets" + value_t = get_pmc_register(mgmtrxloc) + return int(value_t,10) + + +# ============================================== +# MGMT Network Port Test +# ============================================== +def test_mgmt_speed(speed , bmctest ): + MGMT_LPBK_CMD = ("ethtool -s eth0 speed %d duplex full autoneg on" % speed) # MGMT Command for setting the self-loop network port + MGMT_LINK_CHK_CMD = "mii-tool eth0" # MGMT Command to check whether the self-loophead connection of the network port is successful + LINK_CHK_KEY = "link ok" # MGMT Log Indicates the keyword for checking whether the self-loophead connection of the network port is successful + MGMT_LPBK_1000M_EN_CMD = "echo 1 > /sys/class/lpbk_1000m/enable" # Enable the MGMT self-ring network port configuration:1000M + MGMT_LPBK_1000M_DIS_CMD = "echo 0 > /sys/class/lpbk_1000m/enable" # Enable the MGMT self-ring network port configuration:1000M + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + try: + PACKET_NUM = TESTCASE.get('mgmt').get("packetcount") + retrytimes = TESTCASE.get('mgmt').get("retrytimes",5) + # MGMT:Set the self-loop network port + if speed == 1000: + ret, log = log_os_system(MGMT_LPBK_1000M_EN_CMD, 0) + if ret != 0: + RJPRINT("1000m: %s 命令运行错误 [Fail]" % MGMT_LPBK_1000M_EN_CMD) + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : "Error: 1000M自环网口设置命令出错\n"} + return RET + else: + ret, log = log_os_system(MGMT_LPBK_CMD, 0) + if ret != 0: + RJPRINT("%dM: %s 命令运行错误 [Fail]" % (speed,MGMT_LPBK_CMD)) + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : ("Error: %dM自环网口设置命令出错\n" % speed)} + return RET + # MGMT Verify that the self-loophead connection of the network port is successful + time.sleep(1) + for i in range(10): + ret, log = log_os_system(MGMT_LINK_CHK_CMD, 0) + if ret != 0: + RJPRINT("%dM: %s 命令运行错误 [Fail]" % (speed,MGMT_LINK_CHK_CMD)) + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : ("Error: %dM自环头连接成功命令出错\n" % speed)} + return RET + if LINK_CHK_KEY not in log: + time.sleep(1) + continue + # MGMT After the loop head is successfully connected to the UP state, packets are sent and the port sending and receiving information is obtained + RJPRINT("MGMT测试 speed:%dM" % speed) + # X86 receiving and sending test + for i in range(retrytimes): + message = '' + totalerr = 0 + RXstart,TXstart = get_frame_count() + test_mgmt_packet_send(packet_count = PACKET_NUM) + RXend,TXend = get_frame_count() + Tx_total = TXend - TXstart + Rx_total = RXend - RXstart + if Rx_total >= PACKET_NUM: # Consider that other processes may send packets to the MGMT port + message += "X86端确认: MGMT网口测试 [OK]\n" + else: + totalerr -= 1 + message += "X86端确认: [Fail](packets=%d Tx_total=%d Rx_total=%d)\n" % (PACKET_NUM, Tx_total, Rx_total) + # Receiving and sending packets test on the BMC + if bmctest == True: + ret, log = bmc_test_mgmt_speed() + totalerr += ret + message += log + RET[RETURN_KEY2] += message + if totalerr == 0: + RJPRINT(message) + return RET + RJPRINT(message) + RET[RETURN_KEY1] = -1 + return RET + RJPRINT("%dM: MGMT自环头连接 up 失败 [Fail]" % speed) + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : ("Fail: %dM自环头连接 up 失败\n" % speed)} + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + finally: + if speed == 1000: + log_os_system(MGMT_LPBK_1000M_DIS_CMD, 0) + return RET + +def bmc_test_mgmt_speed(): + # Receiving and sending packets test on the BMC + totalerr = 0 + message = '' + bmccheck = TESTCASE.get('mgmt').get("bmccheck") + try: + ret = test_bmc_func(bmccheck.get('case'), bmccheck.get('param')) + if ret.get(RETURN_KEY1) == 0: + message += "BMC端确认: MGMT网口测试 [OK]" + else: + totalerr -= 1 + message += "BMC端确认: [Fail]%s \n" % ret.get(RETURN_KEY2) + + except Exception as e: + message += str(e) + "\n" + totalerr -= 1 + finally: + return totalerr, message + +def test_mgmt_loopback_new_noconfirm(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret_t = test_mgmt_loop_new_real('10M') + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + ret_t = test_mgmt_loop_new_real('100M') + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + ret_t = test_mgmt_loop_new_real('1000M') + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + return RET + +def test_mgmt_loopback_new(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret = makesure(" !!!请确保登入的是串口终端!!! 自环工装是否插入[Yes/no]:", echo = 1) + if ret != True: + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : "Fail"} + return RET + + return test_mgmt_loopback_new_noconfirm() + +def test_mgmt_packet_send(iface1='eth0', packet_count = 2000): + sendp(Ether(dst='FF:FF:FF:FF:FF:FF',src='00:00:00:00:00:03')/ARP(op=1), iface=iface1, count=packet_count,verbose=0) + +def test_check_cpu_loopback(iface, packet_count, pktthread): + ''' + iface: such as eth0 + packet_count: 2000 + pktthread: 1.0 + ''' + RXstart,TXstart = get_frame_count(iface) + test_mgmt_packet_send(iface1 = iface, packet_count = packet_count) # Contract first + RXend,TXend = get_frame_count(iface) + Tx_total = TXend - TXstart + Rx_total = RXend - RXstart + log_debug("发送帧计数:%d,接收帧计数:%d"%(Tx_total,Rx_total)) + packet_rate = float(Rx_total)/float(Tx_total) + if Rx_total >= packet_count and Tx_total >= packet_count and packet_rate >= pktthread: + return True,"" + return False, "发送帧计数:%d,接收帧计数:%d"%(Tx_total,Rx_total) + + +def get_frame_count(iface ='eth0'): + txcmd = "ifconfig %s |grep -E 'TX packets'" % iface + rxcmd = "ifconfig %s |grep -E 'RX packets'" % iface + ret, txlog = log_os_system(txcmd, 0) + ret, rxlog = log_os_system(rxcmd, 0) + tx = re.findall(r"\d+\.?\d*",txlog)[0] + rx = re.findall(r"\d+\.?\d*",rxlog)[0] + return int(rx), int(tx) + +def test_mgmt_loop_new_real(speed): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + http = TESTCASE.get('mgmt').get(speed) + http2 = TESTCASE.get('mgmt').get('clear') + bcmcheckk = TESTCASE.get('mgmt').get('bmccheck') + iface = TESTCASE.get('mgmt').get('iface') + pk_count = TESTCASE.get('mgmt').get('packetcount') + pktthread = TESTCASE.get('mgmt').get('pktpassthread') + retrytimes = TESTCASE.get('mgmt').get('retrytimes', 1) + + RJPRINT("MGMT测试 speed:%s" % speed) + RJPRINT("----------------------") + for i in range(retrytimes): + totalerr = 0 + errmsg = "" + printmsg = "" + try: + ret = test_bmc_func(http2.get('case'),http2.get('param')) + if ret is None: + raise Exception('SONiC reset失败') + time.sleep(0.5) + ret = test_bmc_func(http.get('case'),http.get('param')) + if ret is None: + raise Exception('SONiC设置回环失败') + time.sleep(0.5) + if ret.get(RETURN_KEY1) != 0: + totalerr += ret.get(RETURN_KEY1) + errmsg += ret.get(RETURN_KEY2) + printmsg += errmsg + ' \n' + else: + val_check, errmsg = test_check_cpu_loopback(iface, pk_count, pktthread) + printmsg += "SONiC端确认:" + if val_check == True: + printmsg += " [ok] \n" + else: + printmsg += "[failed] %s \n" % errmsg + if i < (retrytimes -1): + continue + printmsg += "BMC端确认:" + ret = test_bmc_func(bcmcheckk.get('case'),bcmcheckk.get('param')) + if ret is None: + raise Exception('BMC端确认失败') + if ret.get(RETURN_KEY1) == 0: + printmsg +="[ok] \n" + else: + totalerr += ret.get(RETURN_KEY1) + errmsg += ret.get(RETURN_KEY2) + printmsg += "[failed] %s \n" % ret.get(RETURN_KEY2) + if i < (retrytimes -1): + continue + except Exception as e: + totalerr = -998 + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] += str(e) + printmsg += str(e) + ' \n' + finally: + ret = test_bmc_func(http2.get('case'),http2.get('param')) + time.sleep(0.5) + if totalerr >=0: + break + RJPRINT(printmsg) + RET[RETURN_KEY1] = totalerr + RET[RETURN_KEY2] = errmsg + return RET + +# ============================================== +# MGMT Network Port Test +# ============================================== +def test_mgmt(): + bmctest = False + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + + # MGMT Self-loop fixture insertion confirmation + ret = makesure(" !!!请确保登入的是串口终端!!! 自环工装是否插入[Yes/no]:", echo = 1) + if ret != True: + RET = {RETURN_KEY1 : -1, RETURN_KEY2 : "Fail"} + return RET + if FACTESTMODULE.__contains__("mgmttest") and FACTESTMODULE['mgmttest'] == 1: + if checkkallsyms("phy_backup_data") != True: + removedriver("igb",1) + adddriver("igb",2) + log_os_system("ifconfig eth0 up", 0) + adddriver("lpbk_1000m",1) + if bmc_presence_check(): + bmctest = True + ret_t = test_mgmt_speed(10 , bmctest) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + ret_t = test_mgmt_speed(100 , bmctest) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + ret_t = test_mgmt_speed(1000 , bmctest) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + time.sleep(5) + return RET + + +# ============================================== +# MGMT Network port loop test +# ============================================== +def test_mgmt_loop(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + bmctest = True + if FACTESTMODULE.__contains__("mgmttest") and FACTESTMODULE['mgmttest'] == 1: + if checkkallsyms("phy_backup_data") != True: + removedriver("igb",1) + adddriver("igb",2) + log_os_system("ifconfig eth0 up", 0) + adddriver("lpbk_1000m",1) + if bmc_presence_check(): + status, msg = test_bmc_channel() + if status == False: + RJPRINT("到BMC通路异常,无法测试BMC端NCSI通路") + RET[RETURN_KEY1] -= 1 + bmctest = False + else: + bmctest = False + ret_t = test_mgmt_speed(10 , bmctest) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + ret_t = test_mgmt_speed(100 , bmctest) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + ret_t = test_mgmt_speed(1000 , bmctest) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + + time.sleep(5) + return RET + + + +def diff_pcie(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret, log = log_os_system("lspci -n", 0) + pci_list = log.split("\n") + if len(pci_list) != len(PCIe_DEV_LIST): + RET[RETURN_KEY2] = "Error:PCIe设备数量不相等, lspci设备数量:%d, 配置文件设备数量:%d\n" % (len(pci_list),len(PCIe_DEV_LIST)) + log_debug("Error:PCIe设备数量不相等, lspci设备数量:%d, 配置文件设备数量:%d\n" % (len(pci_list),len(PCIe_DEV_LIST))) + pci_dict = {} + for pci in pci_list: + pci_item = pci.split(" ") + pci_dict[pci_item[0]] = pci_item[2] + try: + for dev in PCIe_DEV_LIST: + if dev["pci_addr"] not in pci_dict: + RET[RETURN_KEY2] += "Error:PCIe 设备未找到.PCIe addr = %s,device ID = %s\n" % (dev["pci_addr"],dev["dev_id"]) + log_debug("Error:PCIe 设备未找到.PCIe addr = %s,device ID = %s\n" % (dev["pci_addr"],dev["dev_id"])) + if dev.get("ignore",0) == 1: # Avoiding Baidu BIOS switchover causes two devices fail to scan + pass + else: + RET[RETURN_KEY1] -= 1 + elif dev["dev_id"] != pci_dict[dev["pci_addr"]]: + RET[RETURN_KEY1] -= 1 + RET[RETURN_KEY2] += "Error:PCIe设备ID不一致。PCIe地址:%s,配置文件设备ID:%s,lspci设备ID:%s,\n"% (dev["pci_addr"],dev["dev_id"],pci_dict[dev["pci_addr"]]) + log_debug("Error:PCIe设备ID不一致。PCIe地址:%s,配置文件 设备ID:%s,lspci 设备ID:%s,\n"% (dev["pci_addr"],dev["dev_id"],pci_dict[dev["pci_addr"]])) + del pci_dict[dev["pci_addr"]] + else: + del pci_dict[dev["pci_addr"]] + for pci_addr, dev_id in sorted(pci_dict.items()): + RET[RETURN_KEY1] -= 1 + RET[RETURN_KEY2] += "Error:lspci扫描到的PCIe设备不在配置文件中.PCIe addr = %s,device ID = %s\n" % (pci_addr, dev_id) + log_debug("Error:扫描到的PCIe 设备不在配置文件中.PCIe addr = %s,device ID = %s\n" % (pci_addr, dev_id)) + except Exception as e: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + log_debug(str(e)) + + return RET + +def check_pcie_speed(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + errmsg = "" + try: + for pci in PCIe_SPEED_ITEM: + ret, log = log_os_system("lspci|grep %s"%pci["PCIe_name"], 0) + if pci["PCIe_name"] in log: + result_t = log.split(" ") + vvcmd = "lspci -s %s -vvv | grep LnkSta | grep Width" % result_t[0] + ret2, log2 = log_os_system(vvcmd, 0) + filted_list = re.findall(r".*(speed.*, width.*).*",log2.lower()) + if len(filted_list) > 0 : + value_list = filted_list[0].split(",") + checklist = pci.get("check",None) + if checklist is None: + RJPRINT("%-10s (%-13s, %s): PASS"%(pci["dev_desc"], value_list[0], value_list[1])) + else: + realdata = {"speed":"","width":""} + realdata["speed"] = value_list[0].strip().split(" ")[1].strip() + realdata["width"] = value_list[1].strip().split(" ")[1].strip() + for key,value in checklist.items(): + if realdata[key] != value: + totalerr -= 1 + errmsg += "%s %s check error,correct value is :%s\n" %(pci["dev_desc"],key,value) + if totalerr < 0: + RET[RETURN_KEY1] = -1 + RJPRINT("%-10s (%-13s, %s): FAILED"%(pci["dev_desc"], value_list[0], value_list[1])) + RJPRINT(errmsg) + errmsg = "" + totalerr = 0 + else: + RJPRINT("%-10s (%-13s, %s): PASS"%(pci["dev_desc"], value_list[0], value_list[1])) + else: + RJPRINT("%-10s : PASS"%pci["dev_desc"]) + else: + RJPRINT("%-10s : FAILED"%pci["dev_desc"]) + RET[RETURN_KEY2] += "%-10s : FAILED"%pci["dev_desc"] + RET[RETURN_KEY1] = -1 + except Exception as e: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + log_debug(str(e)) + + return RET + + +def pci_scan(): + # check diff + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + RET1 = diff_pcie() + if RET1[RETURN_KEY1] != 0: + RET[RETURN_KEY1] += RET1[RETURN_KEY1] + RET[RETURN_KEY2] += RET1[RETURN_KEY2] + RJPRINT("PCIe devices scan : FAILED") + else: + RJPRINT("PCIe devices scan : PASS") + + RET1 = check_pcie_speed() + if RET1[RETURN_KEY1] != 0: + RET[RETURN_KEY1] += RET1[RETURN_KEY1] + RET[RETURN_KEY2] += RET1[RETURN_KEY2] + + return RET + +def test_cpu_gpio_6920V2():# C3000CPU does not have chip selection gPIO CPLD Upgrade chip selection through the CPLD register + tolalerr = 0 + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ret, log = log_os_system("which firmware_upgrade", 0) + if len(log): + cmd = "firmware_upgrade cpld test" + else: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "no firmware_upgrade cmd find" + RJPRINT("no firmware_upgrade cmd find") + return RET + commands = TESTCASE.get("cpld_switch", {}).get("SWITCH", None) + clearcmd = TESTCASE.get("cpld_switch", {}).get("CLEAR", None) + for tmp in commands: + ret, log = log_os_system(tmp, 0) + if ret: + tolalerr += -1 + log_error(cmd + "cmd fail") + continue + ret, log = log_os_system(cmd, 0) + if "PASS" not in log or ret: + RET[RETURN_KEY2] += log + log_error(cmd + log) + tolalerr += -1 + ret, log = log_os_system(clearcmd, 0) + if ret: + tolalerr += -1 + log_error(cmd + "clear env fail") + if tolalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def test_cpu_gpio(): + errmsg = "" + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + cmd = "" + ret, log = log_os_system("which firmware_upgrade", 0) + if len(log): + cmd = "firmware_upgrade cpld test" + else: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "no firmware_upgrade cmd find" + RJPRINT("no firmware_upgrade cmd find") + return RET + + ret, log = log_os_system(cmd, 0) + RJPRINT(log) + if "PASS" not in log: + RET[RETURN_KEY2] = log + RET[RETURN_KEY1] = -1 + return RET + +def bmc_get_sensor_info(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + cmd = "" + ret, log = log_os_system("ipmitool sdr list", 0) + RET[RETURN_KEY2] = log + RJPRINT(log) + if "disabled" in log or "failed"in log: + RET[RETURN_KEY1] = -1 + return RET + +def test_bmc_image_force_switch(bmc_info): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + RET = test_bmc_func("bmc_get_flash") + status = False + timeout = TESTCASE.get("SONIC",{}).get("timeout",120) + if RET[RETURN_KEY1]: + RJPRINT(RET[RETURN_KEY2]) + return RET + if bmc_info in RET[RETURN_KEY2]: + RJPRINT("已是%s,无需切换"%bmc_info) + RET[RETURN_KEY1] = 0 + return RET + if makesure("切换会导致BMC重启,是否继续?[Yes/No]:",False,echo = True): + RJPRINT("执行切换中,请等待约90s...") + path = getRealUrl("bmc_test_switch") + cmd = "curl -m 90 %s" % path + ret, log =log_os_system(cmd, 0) + if "timed out" not in log: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "强制切换BMC失败" + return RET + RJPRINT("已成功执行切换操作") + # After the BMC switchover, the USB0 IP address on the X86 terminal will be lost and needs to be reconfigured + ret_t = usb0_init() + while timeout > 0: + if ret_t == False: + ret_t = usb0_init() + status,msg = test_bmc_channel() + if status == True: + break + time.sleep(2) + timeout -= 2 + if timeout < 0: + RJPRINT(msg) + RET[RETURN_KEY1] = -1 + else: + print ("已撤销") + RET[RETURN_KEY1] = -1 + return RET + +def test_bmc_image_force_switch_master(): + return test_bmc_image_force_switch("master") + +def test_bmc_image_force_switch_slave(): + return test_bmc_image_force_switch("slave") + +def generate_value(_t): + ret = [] + for i in TLV_INFO_ID_STRING: + ret.append(i) + ret.append(chr(TLV_INFO_VERSION)) + ret.append(chr(TLV_INFO_LENGTH)) + ret.append(chr(TLV_INFO_LENGTH_VALUE)) + + total_len = 0 + for key in _t: + x = getTLV_BODY(key, _t[key]) + ret += x + total_len += len(x) + ret[10] = chr(total_len + 6) + + ret.append(chr(0xFE)) + ret.append(chr(0x04)) + s = _crc32(''.join(ret)) + for t in range(0, 4): + ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16))) + totallen = len(ret) + if (totallen < 256): + for left_t in range(0, 256 - totallen): + ret.append(chr(0x00)) + return (ret, True) + + + +def isValidMac(mac): + if re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$", mac): + return True + return False + +def RJPRINTERR(str): + print("\033[0;31m%s\033[0m" % str) + + +def test_bmc_ddr_stress_stop(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + if not makesure("强行结束将无法查看结果,是否继续?[Yes/No]:",echo = True): + RET[RETURN_KEY2] = "已撤销" + RJPRINT(RET[RETURN_KEY2]) + return RET + RET = test_bmc_func("bmc_test_ddr_stress_stop_by_sonic") + RJPRINT(RET[RETURN_KEY2]) + return RET + +def test_bmc_emmc_stress_stop(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + if not makesure("强行结束将无法查看结果,是否继续?[Yes/No]:",echo = True): + RET[RETURN_KEY2] = "已撤销" + RJPRINT(RET[RETURN_KEY2]) + return RET + RET = test_bmc_func("bmc_test_emmc_stress_stop") + RJPRINT(RET[RETURN_KEY2]) + return RET + +def bmc_test_ddr_stress_with_result(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + RET = test_bmc_func("bmc_test_ddr_stress") + RJPRINT(RET[RETURN_KEY2]) + if "已启动后台执行" not in RET[RETURN_KEY2]: + return RET + RJPRINT("后台执行测试,等待100s") + time.sleep(100) + RET = test_bmc_func("bmc_test_ddr_stress_result") + RJPRINT(RET[RETURN_KEY2]) + return RET + +def get_fane2_sysfs(bus, loc): + rg_fan_e2 = "%d-%04x/fan" % (bus, loc) + eeprom = get_sysfs_value(rg_fan_e2) + return eeprom + +def checkfansninput(fan_sn, fansntemp): + if fan_sn in fansntemp: + RJPRINTERR("存在相同序列号,请重新输入!") + return False + if fan_sn.isalnum() == False: + RJPRINTERR("序列号非法字符串,请重新输入!") + return False + if(len(fan_sn) != 13): + RJPRINTERR("序列号长度错误(13位),请重新输入!") + return False + return True + +# Check the input hardware version number +def checkfanhwinput(hw): + if len(hw) != 4: + RJPRINTERR("硬件版本号长度不正确,请重新输入!") + return False + if hw.find(".") != 1: + RJPRINTERR("硬件版本号不正确,请重新输入!") + return False + return True + +def util_show_fanse2(fans): + formatstr = "%-8s %-20s %-20s %-20s" + print (formatstr % ("id", "名称", "硬件版本号", "序列号")) + formatstr = "%-8s %-18s %-15s %-15s" + print (formatstr % ("------", "------------", "-----------", "---------------")) + formatstr = "%-10s %-18s %-15s %-15s" + for fan in fans: + # print fan.dstatus + if fan.dstatus < 0: + print "%-8s" % ("风扇%d" % (fans.index(fan) + 1)), + RJPRINTERR(" 解析e2出错") + else: + print (formatstr % ("风扇%d" % (fans.index(fan) + 1), fan.typename.replace(chr(0x00), ""), + fan.typehwinfo.replace(chr(0x00), ""), fan.typesn.replace(chr(0x00), ""))) + +def fac_fan_setmac(item): + + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(item.fanbus, item.fanloc, item.generate_fan_value()) + I2CUTIL.closeFanE2Protect() + + pass + + +def fac_fans_setmac_tlv(ret): + if len(ret) <=0: + return None + fans = [] + fansntemp = [] + for index in range(len(ret)): + item = ret[index] + log_debug(item) + eeprom = get_fane2_sysfs(item["bus"], item["loc"]) + fane2 = fan_tlv() + fane2.decode(eeprom) + fane2.fanbus = item["bus"] + fane2.fanloc = item["loc"] + log_debug("decode eeprom success") + + print ("风扇【%d】-【%s】setmac" % ((index + 1), FANS_DEF[fane2.typedevtype])) + while True: + print ("请输入[%s如(0000000000000)]:" % "序列号",) + fan_sn = raw_input() + if checkfansninput(fan_sn, fansntemp) == False: + continue + fansntemp.append(fan_sn) + fan_sn = fan_sn + chr(0x00) + fane2.typesn = fan_sn + break + while True: + print ("请输入[%s如(1.00)]:" % "硬件版本号",) + hwinfo = raw_input() + if checkfanhwinput(hwinfo) == False: + continue + fan_hwinfo = hwinfo + chr(0x00) + fane2.typehwinfo = fan_hwinfo + break + log_debug(fane2.typedevtype) + fane2.typename = FANS_DEF[fane2.typedevtype] + chr(0x00) + fans.append(fane2) + print ("\n") + print ("\n*******************************\n") + + util_show_fanse2(fans) + if makesure("确认是否输入正确(Yes/No):",echo = 1) == True: + for fan in fans: + log_debug("ouput fan") + fac_fan_setmac(fan) + else: + print ("setmac退出") + return False + +def fac_fans_show_tlv(ret): + totalerr = 0 + fans = ret + for fan in fans: + try: + RJPRINT("===============fan%d ================getmessage" % (fans.index(fan)+1)) + # Check whether the fan module is installed + fanstatus = TESTCASE.get("frustatus",None) + fanstatusdecode = TESTCASE.get("frustatusdecode",None) + fanpresent = fanstatusdecode.get('fanpresent') + fans_conf = fanstatus.get('fans', None) + item_fan = fans_conf[fans.index(fan)] + presentbus = item_fan.get('bus') + presentaddr = item_fan.get('presentloc') + presentbit = item_fan.get('presentbit') + loc = item_fan.get('loc') + ind, val = rji2cget(presentbus, loc,presentaddr) + if ind == True: + val_t = (int(val,16) & (1<< presentbit)) >> presentbit + if val_t != fanpresent.get('okval'):# fan is not detected. + formatstr = "fan%%-%dd:ABSENT"%((17+wide_chars("fan"))) + RJPRINT(formatstr%(fans.index(fan)+1)) + totalerr -= 1 + continue + else: + eeprom = I2CUTIL.dumpValueByI2c(fan.get('bus'), fan.get('loc')) + tlv = fan_tlv() + rets = tlv.decode(eeprom) + if len(rets) == 0: + totalerr -= 1 + RJPRINT("fan E2 read error, please set fan E2 !") + continue + for item in rets: + formatstr = "%%-%ds:%%-20s"%((20+wide_chars(item["name"]))) + RJPRINT(formatstr%(item["name"],item["value"])) + else: + totalerr -= 1 + RJPRINT("get fan present fail!") + except Exception as e: + RJPRINT(str(e)) + totalerr -= 1 + if totalerr < 0: + return False + return True + + + +def fac_fans_show_fru(ret): + fans = ret + totalerr = 0 + for fan in fans: + try: + RJPRINT("===============%s ================getmessage" % fan.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(fan.get('bus'), fan.get('loc'))# getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + + RJPRINT("=================board=================") + RJPRINT(fru.boardInfoArea) + RJPRINT("=================product=================") + RJPRINT(fru.productInfoArea) + except Exception as e: + totalerr -= 1 + if totalerr <0: + return False + return True + +def getfilevalue(location): + try: + with open(location, 'r') as fd: + value = fd.read() + return True, value.strip() + except Exception as e: + return False, "error" + +def test_psu_eeprom(): + return test_get_psu_fru() + +def test_tlv_eeprom(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + errmsg = "" + totalerr = 0 + + RJPRINT("") + RJPRINT("%s "% "系统TLV E2信息:") + ret, log = log_os_system("show platform syseeprom", 0) + RJPRINT(log) + if ret or "TlvInfo" not in log: + RET[RETURN_KEY1] = -1 + totalerr -= 1 + RJPRINT("获取eeprom信息失败") + + RJPRINT("") + RJPRINT("%s "% "硬件TLV E2信息:") + eeprom = get_sysfs_value(rg_eeprom) + onietlv = onie_tlv() + rets = onietlv.decode(eeprom) + for item in rets: + if item["code"] == TLV_CODE_PRODUCT_NAME : + RJPRINT(" %s : %s "%("产品名称 ", item["value"])) + if item["code"] == TLV_CODE_DEVICE_VERSION : + RJPRINT(" %s : V%s "%("硬件版本号", item["value"])) + if item["code"] == TLV_CODE_SERIAL_NUMBER : + RJPRINT(" %s : %s "%("序列号 ", item["value"])) + if item["code"] == TLV_CODE_MAC_BASE : + RJPRINT(" %s : %s "%("MAC ", item["value"])) + if item["code"] == TLV_CODE_PLATFORM_NAME : + RJPRINT(" %s : %s "%("平台名称 ", item["value"])) + if item["code"] == TLV_CODE_ONIE_VERSION : + RJPRINT(" %s : %s "%("ONIE版本 ", item["value"])) + RJPRINT("") + + return RET + +def test_fan_eeprom(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + try: + if (fans_eeprom_show() == False): + totalerr -= 1 + except Exception as e: + RJPRINTERR(e) + totalerr -= 1 + RET[RETURN_KEY1] = totalerr + return RET + +def fans_eeprom_show(): + ret = I2CUTIL.getvaluefromdevice("rg_fan") + if ret is not None and len(ret) > 0: + return fac_fans_show_tlv(ret) + fans = FRULISTS.get('fans', None) + if fans is not None and len(fans)>0: + return fac_fans_show_fru(fans) + return False + +def fac_fan_setmac_fru(ret): + fans = ret + fanfrus = {} + newfrus = {} + # getmsg + try: + for fan in fans: + RJPRINT("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + if eeprom is None: + raise Exception("错误") + fru = ipmifru() + fru.decodeBin(eeprom) + fanfrus[fan.get('name')] = fru + except Exception as e: + RJPRINT(str(e)) + return False + + # setmsg + for fan in fans: + RJPRINT("===============%s ================setmac" % fan.get('name')) + fruold = fanfrus.get(fan.get('name')) + newfru = getInputSetmac(fruold) + newfru.recalcute() + newfrus[fan.get('name')] = newfru + + # writemsg + for fan in fans: + RJPRINT("===============%s ================writeToE2" % fan.get('name')) + ret_t = newfrus.get(fan.get('name')) + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(fan.get('bus'), fan.get('loc'), ret_t.bindata) + I2CUTIL.closeFanE2Protect() + + # check + try: + for fan in fans: + RJPRINT("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + + RJPRINT("=================board=================") + RJPRINT(fru.boardInfoArea) + RJPRINT("=================product=================") + RJPRINT(fru.productInfoArea) + except Exception as e: + RJPRINT(str(e)) + return False + return True + +def fac_fans_setmac(): + ret = I2CUTIL.getvaluefromdevice("rg_fan") + if ret is not None and len(ret) > 0: + return fac_fans_setmac_tlv(ret) + fans = FRULISTS.get('fans', None) + if fans is not None and len(fans)>0: + return fac_fan_setmac_fru(fans) + return False + + +def getinputsetmac_slot(): + slot_info = {} + slot_sn = upper_input("产品序列号:") + if len(slot_sn) != 13: + raise Exception("序列号长度不对") + checkinputproduct(slot_sn) + hw_version = upper_input("硬件版本号:(如1.00)") + slot_info["slot_sn"] = slot_sn + slot_info["hw_version"] = hw_version + return slot_info + +def test_tlv_slot_eeprom(): + + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + slots = FRULISTS.get('slots_tlv', []) + for slot in slots: + try: + RJPRINT("===============%s ================getmessage" % slot.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + if eeprom is None: + raise Exception("错误") + slote2 = fan_tlv() + slote2.decode(eeprom) + RJPRINT(slote2) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] -= 1 + RET[RETURN_KEY2] = str(e) + + return RET + +def test_fru_slot_eeprom(): + + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + slots = FRULISTS.get('slots_fru', []) + for slot in slots: + try: + RJPRINT("===============%s ================getmessage" % slot.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + if eeprom is None: + raise Exception("错误") + slote2 = ipmifru() + slote2.decodeBin(eeprom) + RJPRINT(slote2.boardInfoArea) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] -= 1 + RET[RETURN_KEY2] = str(e) + + return RET + +def fac_tlv_slots_setmac(old_eeprom,setmac_info): + '''TLV subcard setMAC''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + slots_tlv = FRULISTS.get('slots_tlv', []) + protect = TESTCASE.get('tlv_slots_E2protect',[]) + + try: + for item in protect: + rji2cset(item["bus"], item["devno"], item["addr"], item["open"]) + for slot in slots_tlv: + try: + slote2 = old_eeprom.get(slot.get('name')) + slot_info = setmac_info.get(slot.get('name')) + slote2.typesn = slot_info.get("slot_sn") + chr(0x00) + slote2.typehwinfo = slot_info.get("hw_version") + chr(0x00) + + RJPRINT("===============tlv_%s ================writeToE2" % slot.get('name')) + I2CUTIL.writeToE2(slot.get('bus'), slot.get('loc'), slote2.generate_fan_value()) + + RJPRINT("===============tlv_%s ================showmessage" % slot.get('name')) + eeprom_new = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + if eeprom_new is None: + raise Exception("错误") + slote2.decode(eeprom_new) + RJPRINT(slote2) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + finally: + for item in protect: + rji2cset(item["bus"], item["devno"], item["addr"], item["close"]) + + return RET + + +def fac_fru_slots_setmac(old_eeprom,setmac_info): + '''Fru format sub-card setMAC''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + slots_fru = FRULISTS.get('slots_fru', []) + protect = TESTCASE.get('fru_slots_E2protect',[]) + + try: + for item in protect: + rji2cset(item["bus"], item["devno"], item["addr"], item["open"]) + + for slot in slots_fru: + try: + slote2 = old_eeprom.get(slot.get('name')) + slot_info = setmac_info.get(slot.get('name')) + slote2.boardInfoArea.boardSerialNumber = slot_info.get("slot_sn") + slote2.boardInfoArea.boardextra1 = slot_info.get("hw_version") + slote2.recalcute() + # writemsg + RJPRINT("===============fru_%s ================writeToE2" % slot.get('name')) + I2CUTIL.writeToE2(slot.get('bus'), slot.get('loc'), slote2.bindata) + + RJPRINT("===============fru_%s ================showmessage" % slot.get('name')) + eeprom_new = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + if eeprom_new is None: + raise Exception("错误") + slote2.decodeBin(eeprom_new) + RJPRINT(slote2.boardInfoArea) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + finally: + for item in protect: + rji2cset(item["bus"], item["devno"], item["addr"], item["close"]) + + return RET + + +def fac_slots_setmac(): + u"""子卡setmac""" + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + setmac_info = {} + tlv_setmac_flag = FACTESTMODULE.get('tlv_slotsetmac',0) + fru_setmac_flag = FACTESTMODULE.get('fru_slotsetmac',0) + if tlv_setmac_flag == 0 and fru_setmac_flag == 0: + RJPRINT("=============== 无子卡E2 SETMAC信息!================") + return RET + + slots_tlv = FRULISTS.get('slots_tlv', []) + slots_fru = FRULISTS.get('slots_fru', []) + + if tlv_setmac_flag == 1 and len(slots_tlv) == 0 or fru_setmac_flag == 1 and len(slots_fru) == 0: + RET[RETURN_KEY1] -= 1 + if tlv_setmac_flag == fru_setmac_flag and len(slots_tlv) != len(slots_fru): + RET[RETURN_KEY1] -= 1 + if RET[RETURN_KEY1] < 0 : + RJPRINT("===============子卡E2 SETMAC错误,请检查配置文件! ========" ) + RJPRINT("===============tlv_setmac_flag:%d,length:%d ================" %(tlv_setmac_flag,len(slots_tlv))) + RJPRINT("===============fru_setmac_flag:%d,length:%d ================" %(fru_setmac_flag,len(slots_fru))) + return RET + + + tlv_old_eeprom = {} + fru_old_eeprom = {} + if tlv_setmac_flag == 1: + for slot in slots_tlv: + try: + RJPRINT("===============tlv_%s ================getmessage" % slot.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + if eeprom is None: + raise Exception("错误") + slote2 = fan_tlv() + slote2.decode(eeprom) + tlv_old_eeprom[slot.get('name')] = slote2 + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + + if fru_setmac_flag == 1: + for slot in slots_fru: + try: + RJPRINT("===============fru_%s ================getmessage" % slot.get('name')) + eeprom = I2CUTIL.dumpValueByI2c(slot.get('bus'), slot.get('loc')) + if eeprom is None: + raise Exception("错误") + slote2 = ipmifru() + slote2.decodeBin(eeprom) + fru_old_eeprom[slot.get('name')] = slote2 + except Exception as e: + RJPRINT(str(e)) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(e) + if RET[RETURN_KEY1] < 0 : + RJPRINT("=============== 请确认原始烧片是否正常! ================" ) + return RET + + if tlv_setmac_flag == 1: + for slot in slots_tlv: + RJPRINT("=============== %s ================setmac" % slot.get('name')) + slot_info = getinputsetmac_slot() + setmac_info[slot.get('name')] = slot_info + else: + for slot in slots_fru: + RJPRINT("=============== %s ================setmac" % slot.get('name')) + slot_info = getinputsetmac_slot() + setmac_info[slot.get('name')] = slot_info + + # tlv slot setmac + if tlv_setmac_flag == 1: + ret_t = fac_tlv_slots_setmac(tlv_old_eeprom,setmac_info) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + # fru slot setmac + if fru_setmac_flag == 1: + ret_t = fac_fru_slots_setmac(fru_old_eeprom,setmac_info) + RET[RETURN_KEY1] += ret_t.get(RETURN_KEY1) + RET[RETURN_KEY2] += ret_t.get(RETURN_KEY2) + return RET + +def checkinput(b): + if b.isdigit() == False: + raise Exception("非法数字") + if int(b) > 0xff or int(b) < 0: + raise Exception("不在区间内") + +def checkinputproduct(b): + if b.isalnum() ==False: + raise Exception("非法字符串") + + +def getInputSetmac(val): + bia = val.boardInfoArea + pia = val.productInfoArea + if bia != None: + a = upper_input("[板卡区]产品序列号:") + if len(a) != 13: + raise Exception("序列号长度不对") + checkinputproduct(a) + bia.boardSerialNumber = a + b = upper_input("[板卡区]产品版本号:(从1-255)") + checkinput(b) + # b = "%0x" % int(b) + bia.boardextra1 = b.upper() + if pia != None: + a = upper_input("[产品区]产品序列号:") + if len(a) != 13: + raise Exception("序列号长度不对") + checkinputproduct(a) + pia.productSerialNumber = a + b = upper_input("[产品区]产品版本号:(从1-255)") + checkinput(b) + # b = "%0x" % int(b) + pia.productVersion = b.upper() + return val + + + +class I2CUTIL(): + @staticmethod + def getvaluefromdevice(name): + ret = [] + if DEVICE == None: + return None + for item in DEVICE: + if item["name"] == name: + ret.append(item) + return ret + + @staticmethod + def openFanE2Protect(): + if FAN_PROTECT is None or len(FAN_PROTECT) <= 0: + return + if type(FAN_PROTECT) == list: # expand 20190429 + for item in FAN_PROTECT: + rji2cset(item["bus"], item["devno"], + item["addr"], item["open"]) + elif type(FAN_PROTECT) == dict: + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + else: + return + + @staticmethod + def closeFanE2Protect(): + if FAN_PROTECT is None or len(FAN_PROTECT) <= 0: + return + if type(FAN_PROTECT) == list: # expand 20190429 + for item in FAN_PROTECT: + rji2cset(item["bus"], item["devno"], + item["addr"], item["close"]) + elif type(FAN_PROTECT) == dict: + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + else: + return + + @staticmethod + def writeToFanE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def writeToE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def getE2File(bus, loc): + return "/sys/bus/i2c/devices/%d-00%02x/eeprom" % (bus, loc) + + @staticmethod + def dumpValueByI2c(bus, loc): + str = "" + for i in range(256): + ret,val = rji2cget(bus, loc, i) + str += chr(int(val, 16)) + return str + +def getsysvalue(location): + retval = None + mb_reg_file = location + try: + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + log_error("Unable to open " + mb_reg_file + "file !") + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + # log_debug(retval) + return retval + +def waitForDocker(need_restart=False): + time_cnt = 0 + while True: + try: + ret, status = rj_os_system("docker ps |wc -l") + if ret == 0 and int(status) >= 9: + break + else: + sys.stdout.write(".") + sys.stdout.flush() + time_cnt = time_cnt + 1 + time.sleep(1) + if (need_restart == True): + if (time_cnt >= 120 and time_cnt%10 == 0): + if (time_cnt >= 180): + restartDockerService(True) + else: + restartDockerService() + except Exception as e: + continue + +def waitForSDK(): + timeout = 300 + while timeout > 0: + try: + ret, status = rj_os_system("bcmcmd -t 1 ps < /dev/null") + if ret != 0 : + sys.stdout.write(".") + sys.stdout.flush() + timeout -= 1 + time.sleep(1) + else: + break + except Exception as e: + continue + +def closeProtocol(): + # close LLDP + log_info("关闭LLDP") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop lldp.service") + log_info("关闭网关边界服务") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop bgp.service") + log_info("关闭生成树") + sys.stdout.write(".") + sys.stdout.flush() + +def fac_init_cardidcheck(): + rest = getsyseeprombyId(TLV_CODE_RJ_CARID) # Check whether cardId are the same + if rest == None: + print ("需要烧写bin文件") + return False + else: + rest_v = rest['value'] + value = int(rest_v, 16) + if value == RAGILE_CARDID: + log_debug("板卡ID检测通过") + else: + log_debug("板卡ID有误") + return False + return True + +def get_sys_eeprom(): + onietlv = onie_tlv() + eeprom = get_sysfs_value(rg_eeprom) + return onietlv.decode(eeprom) + + +def getsyseeprombyId(id): # Obtain the system system by ID + ret = get_sys_eeprom() + for item in ret: + if item["code"] == id: + return item + return None + +def test_tbd(): + RJPRINT("待实现") + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + return RET + +def set_port_mac_lb(): + bmc_cmd = "port all en=1 lb=mac" + ret, log = log_os_system("bcmcmd \"%s\" < /dev/null"%bmc_cmd, 0) + if ret or bmc_cmd not in log: + RJPRINT("FAILED") + return False, "配置回环失败" + time.sleep(6) + return True, "" + +def cancel_port_mac_lb(): + bmc_cmd = "port all lb=none" + ret, log = log_os_system("bcmcmd \"%s\" < /dev/null"%bmc_cmd, 0) + if ret or bmc_cmd not in log: + RJPRINT("取消配置回环失败") + return False, "取消配置回环失败" + time.sleep(6) + return True, "" + +def test_PCIe_stress(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + ''' old code backup''' + ''' + totalerr = 0 + test_times = 3 + try: + for i in range(0, test_times): + RJPRINT("\n\n第 %d/%d 次测试"%(i+1, test_times)) + RET1 = test_portframe() + totalerr += RET1[RETURN_KEY1] + RET[RETURN_KEY2] += str(RET1[RETURN_KEY2]) + except Exception as e: + totalerr = -999 + RET[RETURN_KEY2] = str(e) + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + ''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + for i in range(3): + ret, log = test_port_portframe() + if ret: + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : log} + break + else : + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + RJPRINT(log) + return RET + +def test_opt_module_present(): + pass_list = [] + failed_list = [] + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + empty_str = " " + ret, log = log_os_system("show interfaces transceiver presence | grep -a -E '^Ethernet'", 0) + if "Traceback" in log: + RJPRINT( "在位检测失败,请确认光模块是否在位") + else: + log,times = re.subn("Ethernet\d{1,3}\s*","",log) + if len(log) == 0: + RET[RETURN_KEY1] = -1 + return RET + dev_list = log.split("\n") + i = 1 + for dev in dev_list: + if "Not present" in dev: + failed_list.append(i) + else: + pass_list.append(i) + i += 1 + if len(pass_list) > 0: + port_totalprint(pass_list, "OK") + if len(failed_list) >0: + port_totalprint(failed_list, "failed") + if ret or "FAILED" in log: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + if ret or "Not" in log or "Unknown" in log: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = log + return RET + +def test_cpu_i2c_stress(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : []} + totalerr = 0 + test_times = 10 + for i in range(0, test_times): + RJPRINT("\n\nCPU端第 %d/%d 次测试"%(i+1, test_times)) + RET1 = test_i2c() + totalerr += RET1[RETURN_KEY1] + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def test_bmc_testcase_new(func, param_t=None, timeout = 600): + if param_t is None: + ret = HttpRest().Get(getRealUrl(func), timeout=timeout) + else: + ret = HttpRest().Get(getRealUrl(func, json.dumps(param_t)), timeout=timeout) + RJPRINT(ret.get(RETURN_KEY2)) + return ret + +def test_bmc_i2c_stress(): + totalerr = 0 + try: + test_bmc_i2c_open() + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + test_times = 10 + returncode, msg = test_bmc_channel() + if returncode == False: + RJPRINT(msg) + return {RETURN_KEY1 : -1, RETURN_KEY2 : msg} + RET1 = test_bmc_testcase_new("bmc_test_i2c_stress") + RET[RETURN_KEY2] += RET1[RETURN_KEY2] + totalerr += RET1[RETURN_KEY1] + except Exception as e: + RJPRINT(str(e)) + finally: + test_bmc_i2c_close() + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def countdown(): + global ssd_status + i = 0 + while True: + time.sleep(1) + i += 1 + if ssd_status == 3: + ssd_status = 0 + return + elif i == 120: + ssd_status = 2 + return + +ssd_status = 0 # 0 undo 1 doing 2 done 3stopping +def test_ssd_stress(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : "已启动后台执行"} + cmd = "smartctl -t long /dev/sda" + global ssd_status + if ssd_status == 1: + RET[RETURN_KEY2] = "已存在后台ssd测试" + RJPRINT(RET[RETURN_KEY2]) + return RET + + ret, log = log_os_system("which smartctl", 0) + if len(log): + # smartctl Built-in background detection + # by to smartctl -l selftest /dev/sda look + os.system(cmd) + ssd_status = 1 + else: + RET[RETURN_KEY2] = "no smartctl cmd" + RJPRINT(RET[RETURN_KEY2]) + thread_tmp = threading.Thread(target=countdown) + thread_tmp.setDaemon(True) + thread_tmp.start() + return RET + +def abort_ssd_stress(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : ""} + cmd = "smartctl -X /dev/sda" + + ret, log = log_os_system("which smartctl", 0) + if len(log): + # smartctl Built-in background detection + # by to smartctl -l selftest /dev/sda look + os.system(cmd) + global ssd_status + ssd_status = 3 + time.sleep(1) + RET[RETURN_KEY2] = "该后台测试已被终止" + else: + RET[RETURN_KEY2] = "no smartctl cmd" + RJPRINT(RET[RETURN_KEY2]) + return RET + +def force_abort_ssd_stress(): + log_os_system("smartctl -X /dev/sda", 0) + +def get_ssd_stress_result(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + cmd = "smartctl -l selftest /dev/sda " + + ret, log = log_os_system("which smartctl", 0) + global ssd_status + if ssd_status == 1: + RET = {RETURN_KEY1: 1, RETURN_KEY2: "后台ssd测试还未结束,请稍等"} + RJPRINT(RET[RETURN_KEY2]) + return RET + elif ssd_status == 0: + RET = {RETURN_KEY1: 1, RETURN_KEY2: "未执行后台ssd测试"} + RJPRINT(RET[RETURN_KEY2]) + return RET + if len(log): + ret, logout = rj_os_system(cmd) + tmpval = '' + for line in logout.splitlines(): + if "# 1" in line: + tmpval = line + break + if tmpval == '' or 'Completed without error' not in tmpval: + RJPRINT(logout) + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = logout + else: + RJPRINT(tmpval) + RET[RETURN_KEY1] = 0 + else: + RET[RETURN_KEY2] = "no smartctl cmd" + # RJPRINT(RET[RETURN_KEY2]) + return RET + + + +def test_kr_stress(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + test_times = 10 + for i in range(0, test_times): + print ("\n\n第 %d/%d 次测试"%(i+1, test_times)) + RET1 = test_kr() + print_temp_flush() + totalerr += RET1[RETURN_KEY1] + RET[RETURN_KEY2] += RET1[RETURN_KEY2] + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def test_subprocess_run(): + RET = {RETURN_KEY1 : 1, RETURN_KEY2 : "开始子进程后台测试"} + if subprocess_case.is_running() or subprocess_case.is_stopping(): + RET[RETURN_KEY2] = "已存在后台测试" + RJPRINT(RET[RETURN_KEY2]) + else: + subprocess_case.start_run_bgtest() + return RET + +def test_subprocess_stop(): + RET = {RETURN_KEY1: 1, RETURN_KEY2: "结束子进程后台测试"} + if subprocess_case.is_running(): + subprocess_case.shutdown_bgtest() + else: + RJPRINT("未进行后台测试") + # exit + return RET + +def test_subprocess_result(): + RET = {RETURN_KEY1: 1, RETURN_KEY2: "查看子进程后台测试结果"} + if subprocess_case.is_undo(): + res = subprocess_case.get_all_message() + if res == "": + RJPRINT("未执行后台测试") + return RET + else: + RJPRINT(res) + if "Fail" in res: + RET[RETURN_KEY1] = -1 + else: + RET[RETURN_KEY1] = 0 + else: + RJPRINT("后台测试正在运行,请稍后查看") + return RET + +class BackgroundOperation(): + UNDO = 0 # Background test items were not executed + DOING = 1 # Tests are running in the background + STOPPING = 2 # Closing background test items + StatusFlag = None # Current status of the child process + lock = None # Shared memory lock + message = None # Store test log + bgmenulist = None # A menu list of background tests + subprocess_obj = None # child process + record_file = "/tmp/out.txt" # Background test output is rerouted + def __init__(self): + self.lock = multiprocessing.Lock() + self.StatusFlag = multiprocessing.Value('i', self.UNDO) # initial undo + self.message = multiprocessing.Queue() + self.bgmenulist = TESTCASE.get("BackgroundMenuList", None) + + @staticmethod + def paren_proce_status(): # child process starts a thread to determine if the parent process exits unexpectedly (taken over by process 1), and then exits + while True: + log_debug("subprocess ppid %d" % os.getppid()) + if os.getppid() == 1: + log_debug("parent process aborted, kill subprocess self") + cmd = "kill -9 %d" % os.getpid() + os.system(cmd) + time.sleep(1) + + def subprocess_real(self): + RET = {RETURN_KEY1: -1, RETURN_KEY2: ""} + thread_tmp = threading.Thread(target=BackgroundOperation.paren_proce_status) + thread_tmp.setDaemon(True) + thread_tmp.start() + data = self.bgmenulist + stdout = sys.stdout + with open(self.record_file, 'w+') as file: + sys.stdout = file + try: + totalresult = "" + if data is None: + RJPRINT("获取后台测试用例错误") + self.turn_undo() + return RET + for item in data: # todo Consider test items before and after + if self.is_stopping(): + formatstr = "======%%-%ds 因用户终止未执行\n" % ((40 + wide_chars(item[MENUITEMNAME]))) + totalresult += formatstr % item[MENUITEMNAME] + continue + RJPRINT(item[MENUITEMNAME]) + RET = eval(item[MENUITEMDEAL])() + if RET[RETURN_KEY1] == 0: + RJPRINT("Test Result: " + SUCCESS_TIPS + '\n\n') + formatstr = "======%%-%ds Test Result: %s\n" % ((40 + wide_chars(item[MENUITEMNAME])), SUCCESS_TIPS) + totalresult += formatstr % (item[MENUITEMNAME]) + elif RET[RETURN_KEY1] == 1: + pass + elif RET[RETURN_KEY1] == -1: + RJPRINT("Test Result: Fail" + '\n\n') + formatstr = "======%%-%ds Test Result: Fail\n" % ((40 + wide_chars(item[MENUITEMNAME]))) + totalresult += formatstr % item[MENUITEMNAME] + RJPRINT("==============================================================") + RJPRINT(totalresult) + except Exception as e: + msg = traceback.format_exc() + RJPRINT(msg) + finally: + self.turn_undo() + sys.stdout = stdout + return RET + + def start_run_bgtest(self): + keep_val = sys.stdin + sys.stdin = subprocess.PIPE + self.turn_doing() + self.subprocess_obj = multiprocessing.Process(target=self.subprocess_real) + self.subprocess_obj.daemon = True + self.subprocess_obj.start() + sys.stdin = keep_val + print ("已开始后台测试,部分测试项不可访问") + + def put_message(self, str, newline = True): + if newline: + self.message.put(str + '\n') + else: + self.message.put(str) + + def get_message(self): + return self.message.get() + + def get_all_message(self): + if os.path.exists(self.record_file) is False: + return "" + with open(self.record_file, 'r') as fd: + return fd.read() + + + def turn_doing(self): + with self.lock: + self.StatusFlag.value = self.DOING + + def turn_undo(self): + with self.lock: + self.StatusFlag.value = self.UNDO + + def turn_stoping(self): + with self.lock: + self.StatusFlag.value = self.STOPPING + + def is_running(self): + with self.lock: + if self.StatusFlag.value == self.DOING: + return True + else: + return False + + def is_undo(self): + with self.lock: + if self.StatusFlag.value == self.UNDO: + return True + else: + return False + + def is_stopping(self): + with self.lock: + if self.StatusFlag.value == self.STOPPING: + return True + else: + return False + + def print_bgtest_name(self, newline =True):# Prints tests that need to be run in the background + tmp = "" + for item in self.bgmenulist: + tmp += item[MENUITEMNAME] + if newline: + tmp += "\n" + return tmp + + def print_result(self, str): + if self.is_undo(): + print (str) + else: + self.put_message(str) + + def shutdown_bgtest(self): + with self.lock: + if self.StatusFlag.value == self.DOING: + print ("正在等待后台进程结束,请稍等") + self.StatusFlag.value = self.STOPPING + while self.is_stopping(): + sys.stdout.write(".") + sys.stdout.flush() + time.sleep(2) +subprocess_case = BackgroundOperation() + +def print_menulist_before_choose(): + RJPRINT("以下测试项将进入后台测试:") + RJPRINT(subprocess_case.print_bgtest_name()) + return True, '' + +def test_opt_module_e2_read(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + pass_list = [] + failed_list = [] + empty_str = " " + ret, log = log_os_system("show interfaces transceiver eeprom | grep -a -E '^Ethernet'", 0) + if ret: + RET[RETURN_KEY1] = -1 + return RET + log,times = re.subn("SFP EEPROM detected","PASS",log) + log,times = re.subn("SFP EEPROM not detected","FAILED",log) + log,times = re.subn("Ethernet\d{1,3}","",log) + + if len(log) == 0: + RET[RETURN_KEY1] = -1 + return RET + + dev_list = log.split("\n") + i = 1 + for dev in dev_list: + if "FAILED" in dev: + failed_list.append(i) + else: + pass_list.append(i) + i += 1 + if len(pass_list) >0: + port_totalprint(pass_list, "OK") + if len(failed_list) > 0: + port_totalprint(failed_list, "failed") + tmpstr = '\nFAILED:\n' + tmpstr += empty_str + for i in range(len(failed_list)): + tmpstr +="%-5s"% failed_list[i] + if((i + 1) %8 == 0): + tmpstr +="\n" + tmpstr += empty_str + tmpstr += "" + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = tmpstr + return RET + + return RET + + +def test_lpc(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + errmsg = '' + + items = [] + for item in CPLDVERSIONS: + if item.get("gettype", None) == 'io': + items.append(item) + + if len(items) > 0: + RJPRINT("LPC读写CPLD测试:") + + for it in items: + addr = it.get('io_addr') + name = it.get('name') + testaddr = 0 + RJPRINT(name) + if name == 'X86_CPLD' or name == 'CPU板CPLD': + testaddr = addr + 0x05 + else: + testaddr = addr + 0xaa + for wr_byte in [0x5a,0xa5]: + ret = io_wr(testaddr, wr_byte) + ret = io_rd(testaddr) + if wr_byte != int(ret,16): + totalerr -= 1 + msg = " 写入%x,读出%x"%(wr_byte, int(ret,16)) + RJPRINT(msg) + RJPRINT(" FAILED") + errmsg += "%s %s \n" % (errmsg, msg) + else: + msg = " 写入%x,读出%x"%(wr_byte, int(ret,16)) + RJPRINT(msg) + RJPRINT(" PASS") + RJPRINT("\r\n") + lpc_item = TESTCASE.get("LPC",[]) + for item in lpc_item: + RJPRINT("LPC读写%s测试:"%item['name']) + addr = item.get('addr') + for wr_byte in [0x5a,0xa5]: + ret = io_wr(addr, wr_byte) + ret = io_rd(addr) + if wr_byte != int(ret,16): + totalerr -= 1 + msg = " 写入%x,读出%x"%(wr_byte, int(ret,16)) + RJPRINT(msg) + RJPRINT(" FAILED") + errmsg += "%s %s \n" % (errmsg, msg) + else: + msg = " 写入%x,读出%x"%(wr_byte, int(ret,16)) + RJPRINT(msg) + RJPRINT(" PASS") + RJPRINT("\r\n") + if bmc_presence_check(): + ret, log = lpc_test_bmc() + totalerr += ret + errmsg += log + + RET[RETURN_KEY1] = totalerr + RET[RETURN_KEY2] = errmsg + return RET + +def lpc_test_bmc(): + totalerr = 0 + Silicon_Revision = 0x1E6E207C # Silicon Revision ID Register + ret, val = LPCTool().read_bmc_reg_32(Silicon_Revision) + RJPRINT("LPC读写BMC测试:") + if ret is False: + RJPRINT(" FAILED") + totalerr -= 1 + else: + RJPRINT(" PASS") + return totalerr, val + +def test_MDIO_stress(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 :""} + totalerr = 0 + test_times = 10 + for i in range(0, test_times): + RJPRINT("\n\n第 %d/%d 次测试"%(i+1, test_times)) + func = "bmc_test_MDIO" + RET1 = test_bmc_testcase(func) + totalerr += RET1[RETURN_KEY1] + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def test_lpc_stress(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + test_times = 10 + for i in range(0, test_times): + RJPRINT("\n\n第 %d/%d 次测试"%(i+1, test_times)) + RET1 = test_lpc() + # print_temp_flush() + totalerr += RET1[RETURN_KEY1] + RET[RETURN_KEY2] += RET1[RETURN_KEY2] + if totalerr < 0: + RET[RETURN_KEY1] = -1 + return RET + +def lpc_test_cpld(retry_times = 1): + items = [] + totalerr = 0 + for item in CPLDVERSIONS: + if item.get("gettype", None) == 'io': + items.append(item) + if len(items) > 0: + RJPRINT("LPC读写CPLD测试:") + for i in range(0, retry_times): + err_flag = False + for it in items: + keep_str = "" + addr = it.get('io_addr') + name = it.get('name') + if i == 0: + it.update({'info': ""}) + it['info'] += " 写入5a,读出5a\n PASS\n" + it['info'] += " 写入a5,读出a5\n PASS\n" + if name == 'X86_CPLD' or name == 'CPU板CPLD': + testaddr = addr + 0x05 + else: + testaddr = addr + 0xaa + for wr_byte in [0x5a,0xa5]: + io_wr(testaddr, wr_byte) + ret = io_rd(testaddr) + if wr_byte != int(ret,16): + keep_str += " 写入%x,读出%x\n"%(wr_byte, int(ret,16)) + keep_str += " FAILED" + keep_str += "\r\n" + err_flag = True + if keep_str != "": + it['info'] = keep_str + if err_flag: + totalerr += 1 + for it in items: + RJPRINT(it.get('name')) + RJPRINT(it['info']) + return totalerr + +def lpc_test_cpu_cpld(retry_times = 1): + totalerr = 0 + lpc_item = list(TESTCASE.get("LPC",[])) + for i in range(0, retry_times): + err_flag = False + for item in lpc_item: + addr = item.get('addr') + keep_str = "" + if i == 0: + item.update({'info':""}) + item['info'] += " 写入5a,读出5a\n PASS\n" + item['info'] += " 写入a5,读出a5\n PASS\n" + for wr_byte in [0x5a, 0xa5]: + io_wr(addr, wr_byte) + ret = io_rd(addr) + if wr_byte != int(ret, 16): + keep_str += " 写入%x,读出%x\n" % (wr_byte, int(ret, 16)) + keep_str += " FAILED" + keep_str += "\r\n" + err_flag = True + if keep_str != "": + item['info'] = keep_str + if err_flag: + totalerr +=1 + for item in lpc_item: + RJPRINT("LPC读写%s测试:" % item['name']) + RJPRINT(item['info']) + return totalerr + +def lpc_test_bmc_new(retry_times = 1): + lcptool = LPCTool() + Silicon_Revision = 0x1E6E207C # Silicon Revision ID Register\ + totalerr = 0 + if bmc_presence_check() is False: + return totalerr + + keep_str = "" + keep_str += "LPC读写BMC测试:\n" + keep_str += " PASS\n" + for i in range(0, retry_times): + ret, val = lcptool.read_bmc_reg_32(Silicon_Revision) + if ret is False: + keep_str = "" + keep_str += "LPC读写BMC测试:\n" + keep_str += " FAILED\n" + totalerr += 1 + RJPRINT(keep_str) + return totalerr + +def test_lpc_stress_new(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + test_times = TESTCASE.get("lpc_test_times", 100) + err1 = lpc_test_cpld(test_times) + err2 = lpc_test_cpu_cpld(test_times) + err3 = lpc_test_bmc_new(test_times) + totalerr = err2 + if err1 > err2: + totalerr = err1 + if totalerr < err3: + totalerr = err3 + RJPRINT("LPC %d次压力测试" % test_times) + RJPRINT("PASS TIMES:%d" % (test_times - totalerr)) + RJPRINT("FAILED TIMES:%d" % totalerr) + if totalerr != 0: + RET[RETURN_KEY1] = -1 + return RET + +def createbmcMac(cpumac , num = 2): + cpumacvalue = int(cpumac.replace(":",""),16) + bmcmacvalue = cpumacvalue + 2 + + len = 6 + s =[''] * len + for i in range(len): + tmpval = bmcmacvalue & 0xff + s[len - i - 1] = "%02x" % tmpval + bmcmacvalue = bmcmacvalue >> 8 + + bmcmac = ":".join(s) + return bmcmac.upper() + +def ipmi_set_mac(mac): + if fac_init_check_ipmi() == True: + macs = mac.split(":") + cmdinit = "ipmitool raw 0x0c 0x01 0x01 0xc2 0x00" + cmdset = "ipmitool raw 0x0c 0x01 0x01 0x05" + for ind in range(len(macs)): + cmdset += " 0x%02x" % int(macs[ind], 16) + rj_os_system(cmdinit) + ret, status = rj_os_system(cmdset) + if ret: + RJPRINTERR("\n\n%s\n\n" % status) + return False + return True + else: + return False + +def test_bios_flash(): + '''Verify this by reading the active and standby BIOS versions''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : "","master":"","slave":""} + file_path = TESTCASE.get("BIOS_INFO",None) + if file_path == None: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "No BIOS flash test case." + return RET + try: + with open(file_path, 'r') as fd: + log = fd.read().strip() + # RJPRINT(log) + if "master" not in log.lower() or "slave" not in log.lower(): + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "No master/slave BIOS version!" + return RET + version = log.split("\n",1) + for version_item in version: + bios_version = version_item.split(":",1) + if len(bios_version) != 2 or len(bios_version[1].strip()) == 0: + RET[RETURN_KEY1] -= 1 + if "master" in bios_version[0]: + RET[RETURN_KEY2] += "master BIOS version read error!\n" + else: + RET[RETURN_KEY2] += "slave BIOS version read error!\n" + continue + if "master" in bios_version[0]: + RET["master"] = bios_version[1].strip() + else: + RET["slave"] = bios_version[1].strip() + except Exception as error: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = str(error) + return RET + +def get_bios_info(): + biosstatusdecode = TESTCASE.get("biosstatusdecode",None) + biosstatus = TESTCASE.get("biosstatus",None) + + if biosstatus is None or biosstatusdecode is None: + return None + + if biosstatus["gettype"] == "i2c": + bus = biosstatus["bus"] + loc = biosstatus["loc"] + reg = biosstatus["reg"] + ind, val = rji2cget(bus, loc,reg) + if ind == False: + val = None + else: + io_addr = biosstatus.get('io_addr') + val = io_rd(io_addr) + if val is not None: + bitmask = biosstatus["bitmask"] + val_t = int(val,16) & bitmask + if val_t not in biosstatusdecode.keys(): + return None + return biosstatusdecode.get(val_t,None) + return None + +def test_bios_force_switch(bios_info, cpu = False): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + log = get_bios_info() + + if log == None: + RET[RETURN_KEY1] = -1 + RJPRINT("获取BIOS信息失败") + return RET + elif bios_info in log: + RJPRINT("已是%s,无需切换"%bios_info,False) + RET[RETURN_KEY1] = 0 + return RET + + if bios_info == "master": + switch_mod = 0 + else: + switch_mod = 1 + + if makesure("切换BIOS会导致X86重启,是否继续?[Yes/No]:",True,echo = True): + func = "test_bmc_bios_switch" + if cpu == False: + ret = test_bmc_func(func,switch_mod) + return ret + else: + test_bios_swtch(switch_mod) + else: + print ("已撤销") + RET[RETURN_KEY1] = -1 + return RET + +def test_bios_force_switch_slave(): + return test_bios_force_switch("slave") + +def test_bios_force_switch_master(): + return test_bios_force_switch("master") + +def test_cpu_bios_force_switch_slave(): + return test_bios_force_switch("slave", True) + +def test_cpu_bios_force_switch_master(): + return test_bios_force_switch("master", True) + +def test_bmc_command(param): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + cmd = param.get("cmd",None) + func = param.get("bmc_interface",None) + if cmd == None or func == None: + RET[RETURN_KEY1] = -88 + RET[RETURN_KEY2] = "获取配置文件错误" + else: + ret = test_bmc_func(func,cmd) + if ret.get(RETURN_KEY1) == -1 or len(ret.get(RETURN_KEY2)) == 0: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "获取固件版本号 测试失败\nmessage:%s" % (ret.get(RETURN_KEY2)) + else: + RET[RETURN_KEY1] = 0 + RET[RETURN_KEY2] = ret.get(RETURN_KEY2) + RJPRINT(RET[RETURN_KEY2]) + return RET + +def test_bmc_5387MD5(): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + cmd = TESTCASE.get("eeprom5387_bmc",{}).get("cmd",None) + func = TESTCASE.get("eeprom5387_bmc",{}).get("bmc_interface",None) + if cmd == None or func == None: + RET[RETURN_KEY1] = -88 + RET[RETURN_KEY2] = "获取配置文件错误" + else: + ret = test_bmc_func(func,cmd) + if ret.get(RETURN_KEY1) == -1 or len(ret.get(RETURN_KEY2)) == 0: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "获取固件版本号 测试失败\nmessage:%s" % (ret.get(RETURN_KEY2)) + else: + RET[RETURN_KEY1] = 0 + RET[RETURN_KEY2] = ret.get(RETURN_KEY2) + RJPRINT(RET[RETURN_KEY2]) + return RET + +def test_bios_swtch(switch_mod): + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + # switch BIOS + BIOS_TEST = TESTCASE.get("BIOS_TEST", None) + if BIOS_TEST is None: + RET = {RETURN_KEY1: -1, RETURN_KEY2: "no find config"} + return RET + if switch_mod == 0: # switch to master BIOS + switch_oplist = BIOS_TEST.get("switch_master",[]) + elif switch_mod == 1: # switch to slave BIOS + switch_oplist = BIOS_TEST.get("switch_slave",[]) + else: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "switch_mod error!" + return RET + for switch_opitem in switch_oplist: + type = switch_opitem.get("gettype", "i2c") + if type == "i2c": + bus = switch_opitem["bus"] + loc = switch_opitem["loc"] + reg = switch_opitem["reg"] + val = switch_opitem["val"] + ret,log = rji2cset(bus,loc,reg,val) + if ret == False: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "switch i2c write failed!" + return RET + elif type == "io": + io_addr = switch_opitem["io_addr"] + val = switch_opitem["val"] + ret = io_wr(io_addr, val) + if ret == False: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "switch i2c write failed!" + return RET + elif type == "func": + funcname = eval(switch_opitem["funcname"]) + ret, msg = funcname() + if ret is False: + RET[RETURN_KEY1] = -1 + log_debug("switch bios func fail %s" % switch_opitem["funcname"]) + return RET + return RET + +def readsysfs(location): + try: + locations = glob.glob(location) + with open(locations[0], 'r') as fd1: + val = fd1.read() + except Exception as e: + return False, (str(e)+" location[%s]" % location) + return True, val + +def test_dcdc(): + RET = {RETURN_KEY1: 0, RETURN_KEY2: ""} + totalerr = 0 + errmsg = "" + resultval = [] + + items = TESTCASE.get("dcdcsensor", None) + if items is None: + RET[RETURN_KEY1] = -999 + RET[RETURN_KEY2] = 'config error' + return RET + + # get dcdcsensor value + for item in items: + Sensor = item.get('Sensor', None) + Address = item.get('Address', None) + min = item.get('CriticalLow', None) + max = item.get('CriticalHigh', None) + Unit = item.get('Unit', "") + format = item.get("format", None) + gettype = item.get("gettype", None) + if gettype == "sysfs": + location = item.get("location", "error_url") + ret,ind = readsysfs(location) + elif gettype == "pagei2cword": + bus = item.get('bus') + devno = item.get('devno') + offset = item.get('addr') + select = item.get('select') + slectvalue = item.get('slectvalue') + rji2cset(bus, devno, select, slectvalue) + ret, ind = rji2cgetWord(bus, devno, offset) + if ret == False: + val = None + else: + val = ind.replace("0x", "").replace("0X", "") + else: + pass + if ret == True: + val = ind.replace("\n", "") + if format is not None: + tmp = format % val + val_tmp = eval(tmp) + else: + val_tmp = int(val, 10) + if min < val_tmp < max: + statusmsg = "OK" + else: + totalerr -= 1 + statusmsg = 'Not OK' + else: + totalerr -= 1 + statusmsg = 'Not OK' + val_tmp = "fail " + Unit = "" + log_debug("get dcdc value fail %s", Sensor) + resultval.append([Sensor, Address, statusmsg, "%s%s"%(val_tmp, Unit), "%s%s"%(min, Unit), "%s%s"%(max, Unit)]) + + # print + header = ['Sensor', 'Address', 'State', 'Value', 'CriticalLow', 'CriticalHigh'] + result = tabulate(resultval, header, tablefmt='simple') + RJPRINT(result) + if totalerr < 0: + errmsg += str(result) + + RET[RETURN_KEY1] = totalerr + RET[RETURN_KEY2] = errmsg + return RET + +def test_bmc_sol(): + '''Serial Port (SOL) test between the CPU and BMC''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + cur_time = time.time(); + timeArray = time.localtime(cur_time) + otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray) + teststr = 'SOL test,current time:%s' % otherStyleTime + cmd = "echo '%s' > /dev/ttyS0" % teststr + log_os_system(cmd,0) + time.sleep(1) + + func = 'bmc_log_os_system' + cmd = "cat /var/log/obmc-console.log | grep '%s'" % teststr + ret = test_bmc_func(func,cmd) + if ret.get(RETURN_KEY1) == -1 or len(ret.get(RETURN_KEY2)) == 0: + RET[RETURN_KEY1] = -1 + RET[RETURN_KEY2] = "SOL 测试失败\nmessage:%s" % (ret.get(RETURN_KEY2)) + else: + RET[RETURN_KEY1] = 0 + RET[RETURN_KEY2] = "SOL 测试成功" + RJPRINT(RET[RETURN_KEY2]) + return RET + + +def fac_check_eth_mac(): + '''Check whether I210 and MAC can be detected''' + totalerr = 0 + errmsg = "" + for pci in PCIe_SPEED_ITEM: + try: + status, output = log_os_system("lspci|grep %s | wc -l"%pci["PCIe_name"], 0) + if output.isdigit() and int(output) == 0: + totalerr -= 1 + RJPRINT("%s can't find!" % pci["PCIe_name"]) + except Exception as error: + totalerr -= 1 + errmsg = str(error) + RJPRINT("errmsg") + if totalerr < 0: + quit() + +def cpld_init(): + '''Write the CPLD register to initialize the CPLD''' + items = TESTCASE.get("init_param",{}).get("CPLD",None) + if items == None: + return True + try: + for item in items: + if item.get("gettype") == "i2c": + bus = item["bus"] + loc = item["loc"] + reg = item["reg"] + val = item["val"] + ret, log = rji2cset(bus, loc, reg, val) + if ret == False: + RJPRINT("Write cpld falied,bus:%d,loc:0x%2x,reg:0x%2x,value:0x%2x" %(bus,loc,reg,val)) + return False + else: + pass + except Exception as error: + errmsg = str(error) + RJPRINT("errmsg") + return False + return True + +def usb0_init(): + '''Set the IP address of USB0''' + usbip = TESTCASE.get("SONIC",{}).get("ip","1.1.1.1") + cmd = "ifconfig usb0 %s netmask 255.255.255.0" % usbip + ret,log = log_os_system(cmd, 0) + if ret or "ERROR" in log: + return False + return True + +class IniRdwr(): + from ConfigParser import ConfigParser + path = '/tmp/.status.ini' + config = None + def __init__(self): + self.config = ConfigParser.ConfigParser() + self.config.read(self.path) + + def check_section(self, section): + return self.config.has_section(section) + + def check_option(self, section, option): + return self.config.has_option(section, option) + + def rd_ini_option(self, section, option, type = "str"): + self.config.read(self.path) + if self.check_option(section, option) is False: + return False, 'no section or option in %s' % self.path + if type == 'int': + value = self.config.getint(section, option) + elif type == 'bool': + value = self.config.getboolean(section, option) + elif type == "float": + value = self.config.getfloat(section, option) + elif type == "str": + value = self.config.get(section, option) + else: + return False, 'error para' + return True, value + + def wr_ini_option(self, section, option, value): + if self.check_section(section) is False: + self.config.add_section(section) + self.config.set(section, option, value) + with open(self.path, "w") as f: + self.config.write(f) + return True, "success" + +def bmc_presence_check(): + obj = IniRdwr() + ret, val = obj.rd_ini_option("bmc", "bmc_present", "bool") + if ret and val: + return True + else: + return False + +def psu_check(): + '''Power supply anti-freeze detection''' + RET = {RETURN_KEY1 : 0, RETURN_KEY2 : ""} + totalerr = 0 + errmsg = "" + psus = FRULISTS.get('psus',[]) + psucheckitem = TESTCASE.get("firmware_check",{}).get("psus",None) + + if psucheckitem == None: # No power check item + return True + psutypes = psucheckitem.get("psutype") + for psu in psus: + psuscheck = False + try: + eeprom = I2CUTIL.dumpValueByI2c(psu.get('bus'), psu.get('loc')) + if eeprom is None: + continue + fru = ipmifru() + fru.decodeBin(eeprom) + realtype = fru.productInfoArea.productPartModelName.strip() + for type in psutypes: + if type in realtype: # match is successful + psuscheck = True + break + if psuscheck == False: + RJPRINT("%s 电源类型不匹配,请检查!" % psu.get("name")) + totalerr -= 1 + except Exception as e: + errmsg = " %s %s %s \n" %(errmsg, psu.get('name'), str(e)) + continue + + if totalerr < 0: + RJPRINT("检测错误,无法启动生测程序!请使用以下型号电源进行测试:") + for type in psutypes: + RJPRINT(type) + quit() + return True + +def fac_check_rtc(): + try: + time1 = time.time(); + timeArraystart = time.localtime(time1) + otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArraystart) + log_debug("当前时间:%s" % otherStyleTime) + time_t = otherStyleTime.split("-") + time_year = int(time_t[0].strip()) + log_debug("当前时间:%d年" % time_year) + if time_year <= 2000: + RJPRINT("当前时间:%s,请先进入系统配置,设置RTC" % otherStyleTime) + except Exception as e: + log_debug(str(e)) + pass + +class LPCTool(): + REG_ADDR = None + REG_DATA = None + + def __init__(self, reg_addr = 0x4E, re_data = 0x4F): + self.REG_ADDR = reg_addr + self.REG_DATA = re_data + self.disable_sio_val = 0xAA + self.enable_sio_val = 0xA5 + self.SIORx_07 = 0x07 + self.SIORD_30 = 0x30 + self.ldu_0d_val = 0x0D # Select LDU 0D (iLPC2AHB-LPC to AHB bus bridge) + self.SIORD_F8 = 0xF8 + self.sio_length_4 = 0x02 + self.PORT_ADDR = "/dev/port" + + def dis_ilpc2ahb(self): + try: + # disabled ilpc2ahb + self.seek_addr(self.SIORD_30) + self.port_write(self.REG_DATA, 0x00) + # dis_superio + self.seek_addr(self.disable_sio_val) + except Exception as error: + RJPRINT("dis_ilpc2ahb fail:" + str(error)) + + def en_ilpc2ahb(self): + try: + # dis_superio + self.seek_addr(self.disable_sio_val) + # en_superio + self.seek_addr(self.enable_sio_val) + self.seek_addr(self.enable_sio_val) + # enable bmc ilpc2ahb + self.seek_addr(self.SIORx_07) + self.port_write(self.REG_DATA, self.ldu_0d_val) + + self.seek_addr(self.SIORD_30) + self.port_write(self.REG_DATA, 0x01) + self.seek_addr(self.SIORD_F8) + val = self.port_read(self.REG_DATA) + except Exception as error: + RJPRINT("en_ilpc2ahb fail:" + str(error)) + return False, None + if int(val, 16) & 0x03 != self.sio_length_4: + return False, val + return True, val + + def port_read(self, offset, size=1): + ret = None + with open(self.PORT_ADDR, "rb") as f: + f.seek(offset) + ret = f.read(size) + # return ret + return "".join(["{:02x}".format(ord(item)) for item in ret]) + + def port_write(self, offset, val): + if isinstance(val, int): + val = chr(val) + + with open(self.PORT_ADDR, "r+b") as f: + f.seek(offset) + f.write(val) + f.flush() + + def write_32bit_val(self, addr): + address_base = 0xF0 # reg for access address + for i in range(4): + self.seek_addr(address_base + i) + bit = 32 - (i + 1) * 8 + self.port_write(self.REG_DATA, addr >> bit & 0xFF) + + def seek_addr(self, addr): + self.port_write(self.REG_ADDR, addr) + + def read_bmc_reg_32(self, addr): + try: + value_address_base = 0xF4 # reg for value address + ret, _ = self.en_ilpc2ahb() + if ret is False: + return ret, "" + self.write_32bit_val(addr) + self.seek_addr(0xFE) + ret = self.port_read(self.REG_DATA) + val = "" + for i in range(4): + self.seek_addr(value_address_base + i) + val += self.port_read(self.REG_DATA) + self.dis_ilpc2ahb() + except Exception as error: + RJPRINT("read_bmc_reg_32 fail:" + str(error)) + return False, "" + return True, val + +def fac_check_bmc_status(): + try: + lpctool = LPCTool() + ret, val = lpctool.en_ilpc2ahb() + obj = IniRdwr() + if ret is False and val == "ff": + obj.wr_ini_option("bmc","bmc_present","False") + elif ret is True: + obj.wr_ini_option("bmc","bmc_present","True") + except Exception as e: + RJPRINT(str(e)) + finally: + lpctool.dis_ilpc2ahb() + +def reboot_system(): + ret, msg = rj_os_system("reboot -f") + if ret == 0: + return True, msg + return False, msg + +def firmware_check(): + # Power supply anti-freeze detection + psu_check() + # I210 and MAC detection + fac_check_eth_mac() + # RTC detection + fac_check_rtc() + # BMC status detection + fac_check_bmc_status() + +def fac_firmware_init(): + cpld_init() + +def factest_check(argv): + global DIAGTEST + if len(argv) == 2 and argv[1] == 'diag': + DIAGTEST = True + bmcmac = getBMCMAC() + RJPRINT("BMC MAC【%s】" % bmcmac) + else: + pass + +## Production test master program +if __name__ == '__main__': + # ApplicationInstance() + # print sys.getdefaultencoding() + # print sys.getfilesystemencoding() + # import locale + # print locale.getdefaultlocale() + root_check() + factest_check(sys.argv) + fac_init() + log_info("生产测试主程序") + start() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/fancontrol.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/fancontrol.py new file mode 100755 index 000000000000..ebec42efa7ce --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/fancontrol.py @@ -0,0 +1,450 @@ +#!/usr/bin/env python3.9 +# -*- coding: UTF-8 -*- +import sys +import click +import os +import subprocess +import time +import json +import syslog +import traceback +import glob +from interface import Interface +import logging.handlers +from ragileutil import CompressedRotatingFileHandler + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +FILE_NAME = "/var/log/fancontrol.log" +MAX_LOG_BYTES = 20*1024*1024 +BACKUP_COUNT = 9 + +logger = logging.getLogger("fancontrol") +logger.setLevel(logging.DEBUG) +fanctrl_log = CompressedRotatingFileHandler(FILE_NAME, mode='a', maxBytes=MAX_LOG_BYTES, backupCount=BACKUP_COUNT, encoding=None, delay=0) +formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") +fanctrl_log.setFormatter(formatter) +logger.addHandler(fanctrl_log) + +DEBUG_FILE = "/etc/fancontrol_debug" +FAN_CTRL_CFG_FILE = "/usr/local/bin/fan_ctrl_cfg.json" +KEY_THERMAL = "Thermal" +KEY_FAN = "Fans" +KEY_PID = "PID" +KEY_OPEN_LOOP = "OpenLoop" +KEY_DEVICE = "Device" + +KEY_INLET_TEMP = "INLET_TEMP" +KEY_OUTLET_TEMP = "OUTLET_TEMP" +KEY_SWITCH_TEMP = "SWITCH_TEMP" +KEY_TEMP = [KEY_INLET_TEMP, KEY_OUTLET_TEMP, KEY_SWITCH_TEMP] + +KEY_PID_PWM_MAX = "Pwm_Max" +KEY_PID_PWM_MIN = "Pwm_Min" +KEY_PID_SETPOINT = "SetPoint" +KEY_PID_P = "P" +KEY_PID_I = "I" +KEY_PID_D = "D" +KEY_PID_TEMP_MIN = "Temp_Min" +KEY_PID_TEMP_MAX = "Temp_Max" + +KEY_OPENLOOP_A = "a" +KEY_OPENLOOP_B = "b" +KEY_OPENLOOP_C = "c" +KEY_OPENLOOP_FIXUP = "fix_up" +KEY_OPENLOOP_PWM_MAX = "pwmMax" +KEY_OPENLOOP_PWM_MIN = "pwmMin" +KEY_OPENLOOP_TEMP_MIN = "tempMin" + +STATUS_HIGH_CRIT = 1 +STATUS_MISS_CRIT = 2 +STATUS_BAD_FAN = 4 +STATUS_LOW_FAN = 8 +STATUS_MISS_ERR = 16 + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def fanctrl_debug_log(s): + # s = s.decode('utf-8').encode('gb2312') + if os.path.isfile(DEBUG_FILE): + logger.debug(s) + +class OpenLoop(): + def __init__(self): + self.a = 0 + self.b = 0 + self.c = 0 + self.fix_up = 0 + self.pwmMax = 0 + self.pwmMin = 0 + self.temp = 0 + self.tempMin = 0 + + def calcPwm(self): + if self.temp < self.tempMin: + return self.pwmMin + pwm = self.a * self.temp * self.temp + self.b * self.temp + self.c + pwm = (pwm / 2.56) + pwm = min(pwm, self.pwmMax) + pwm = max(pwm, self.pwmMin) + return pwm + + +class FanPid(): + def __init__(self): + self.pwmMin = 30 + self.pwmMax = 100 + self.SetPoint = 89 + self.D = 0.196 + self.I = 0.196 + self.P = 1.176 + self.tempMin = 28.0 + self.tempMax = 45.0 + self.pwms = [30, 30] + self.temps = [-1, -1, -1] + self.last_temp = -1 + self.sensor = KEY_SWITCH_TEMP + + def calcPwm(self): + temp_delta = self.temps[2] - self.last_temp + temp_sp_delta = self.temps[2] - self.SetPoint + temp_last_delta = ((self.temps[2] - self.temps[1]) - (self.temps[1] - self.temps[0])) + + delta_pwm = self.P * temp_delta + self.I * temp_sp_delta + self.D * temp_last_delta + + self.temps[0] = self.temps[1] + self.temps[1] = self.temps[2] + self.last_temp = self.temps[2] + + self.pwms[0] = self.pwms[1] + self.pwms[1] = self.pwms[0] + delta_pwm + self.pwms[1] = max(self.pwms[1], self.pwmMin) + self.pwms[1] = min(self.pwms[1], self.pwmMax) + + return self.pwms[1] + +class FanControl(): + + def __init__(self): + self.status = 0 + self.fan_status = 0 + self.error_time = 0 + self.low_time = 0 + self.fan_pwm = 40 + self.interface = Interface() + self.temps = {} + self.tempsMax = {} + self.tempsMin = {} + self.tempStatus = {} + self.tempCritTime = {} + self.tempMissTime = {} + + self.fans = {} + self.fanStatus = {} + self.fanErrTime = {} + self.fanLowTime = {} + + self.fanPid = None + self.openloop = None + + self.isBuildin = 0 + self.isLiquid = 0 + self.eeproms = {} + self.airflow = "" + self.pid_switch = 1 + self.openloop_switch = 1 + pass + + def doGetAirFlow(self): + if self.isLiquid == 1: + return "Liquid" + # PSU and Fan is buildin using Tlve2 + if self.isBuildin == 1: + productName = self.interface.get_productname() + if productName != "": + tmp = productName.split("-") + fanairflow = tmp[-1] + if fanairflow == "R": + return "B2F" + else: + return "F2B" + elif self.isBuildin == 0: + return self.interface.get_airflow() + + return "" + + def doFanCtrlInit(self): + if os.path.isfile(FAN_CTRL_CFG_FILE): + fh = open(FAN_CTRL_CFG_FILE) + if not fh: + logger.error("Config file %s doesn't exist" % FAN_CTRL_CFG_FILE) + return + cfg_json = json.load(fh) + if not cfg_json: + logger.error('Load config file %s failed' % FAN_CTRL_CFG_FILE) + return False + + cfg_keys = [KEY_THERMAL, KEY_FAN, KEY_PID, KEY_OPEN_LOOP, KEY_DEVICE] + for key in cfg_keys: + if key not in cfg_json: + logger.error('Key %s not present in cfg file' % key) + return False + thermal_json = cfg_json[KEY_THERMAL] + fan_json = cfg_json[KEY_FAN] + pid_json = cfg_json[KEY_PID] + openloop_json = cfg_json[KEY_OPEN_LOOP] + device_json = cfg_json[KEY_DEVICE] + # Get Airflow + self.isBuildin = device_json["Buildin"] + self.isLiquid = device_json["Liquid"] + self.airflow = self.doGetAirFlow() + if self.airflow == "": + logger.warning("Cannot get airflow from device!") + + # Init openloop + self.openloop = OpenLoop() + self.openloop.a = openloop_json[KEY_OPENLOOP_A] + self.openloop.b = openloop_json[KEY_OPENLOOP_B] + self.openloop.c = openloop_json[KEY_OPENLOOP_C] + self.openloop.fix_up = openloop_json[KEY_OPENLOOP_FIXUP] + self.openloop.pwmMax = openloop_json[KEY_OPENLOOP_PWM_MAX] + self.openloop.pwmMin = openloop_json[KEY_OPENLOOP_PWM_MIN] + self.openloop.tempMin = openloop_json[KEY_OPENLOOP_TEMP_MIN] + # Init thermal setting + for key, item in list(thermal_json.items()): + fanctrl_debug_log("%s %s " % (key,item)) + if key not in KEY_TEMP: + logger.error('Key %s not present in cfg file' % key) + return False + self.temps[item] = -1.0 + self.tempsMax[item] = self.interface.get_thermal_temp_max(item) + self.tempsMin[item] = self.interface.get_thermal_temp_min(item) + self.tempStatus[item] = 0 + self.tempMissTime[item] = [0, 0] + self.tempCritTime[item] = [0, 0] + + # Init fans setting + for key, item in list(fan_json.items()): + self.fans[key] = item + self.fanStatus[key] = 0 + self.fanErrTime[key] = [0, 0] + self.fanLowTime[key] = [0, 0] + + else: + logger.error('%s is not a file' % FAN_CTRL_CFG_FILE) + return False + + fanctrl_debug_log("Device AirFlow: %s" % (self.airflow)) + self.updateThermal() + return True + + def setFanSpeed(self, speed): + return self.interface.set_fan_speed_pwm(speed) + + def updateThermal(self): + for key in self.temps: + self.temps[key] = self.interface.get_thermal_temp(key) + fanctrl_debug_log("%s temps %d C" % (key, self.temps[key])) + + if self.temps[KEY_INLET_TEMP] >= self.tempsMax[KEY_INLET_TEMP] or self.temps[KEY_INLET_TEMP] <= -99999: + self.temps[KEY_INLET_TEMP] = self.tempsMax[KEY_INLET_TEMP] + self.openloop.temp = self.temps[KEY_INLET_TEMP] + + def checkThermal(self): + thermal_cnt = 0 + for key in self.temps: + if self.temps[key] <= -9999: + if self.tempStatus[key] & STATUS_MISS_CRIT != 0: + self.tempMissTime[key][0] = time.time() + else: + self.tempMissTime[key][1] = time.time() + self.tempStatus[key] = self.tempStatus[key] | STATUS_MISS_CRIT + if self.tempMissTime[key][1] - self.tempMissTime[key][0] > 15: + logger.warning("%s Read Invaild Temperautre %d " % (key, self.temps[key])) + self.tempStatus[key] = self.tempStatus[key] | STATUS_MISS_ERR + else: + self.tempStatus[key] = self.tempStatus[key] & ~(STATUS_MISS_CRIT | STATUS_MISS_ERR) + + if self.temps[key] >= self.tempsMax[key]: + self.tempCritTime[key][0] = time.time() + self.tempStatus[key] = self.tempStatus[key] | STATUS_HIGH_CRIT + logger.warning("%s Temperautre %d >= High Threshold %d" % (key, self.temps[key], self.tempsMax[key])) + elif self.tempStatus[key] & (STATUS_HIGH_CRIT) != 0: + self.tempCritTime[key][1] = time.time() + logger.warning("%s Temperautre %d Recovery" % (key, self.temps[key])) + if self.tempCritTime[key][1] - self.tempCritTime[key][0] > 300: + self.tempStatus[key] = self.tempStatus[key] & ~(STATUS_HIGH_CRIT) + + if self.tempStatus[key] & ~(STATUS_MISS_CRIT) != 0: + thermal_cnt = thermal_cnt + 1 + + self.status = thermal_cnt + fanctrl_debug_log("Thermal error num %d" % self.status) + + def checkFanSpeed(self): + fan_error_cnt = 0 + for key, item in list(self.fans.items()): + speed = self.interface.get_fan_speed_rpm(item) + rpm_max = self.interface.get_fan_rpm_max() + if self.fan_pwm == 100 and speed < rpm_max * 0.7: + if self.fanStatus[key] & STATUS_BAD_FAN != 0: + self.fanErrTime[key][0] = time.time() + else: + self.fanErrTime[key][1] = time.time() + + self.fanStatus[key] = self.fanStatus[key] | STATUS_BAD_FAN + if self.fanErrTime[key][1] - self.fanErrTime[key][0] >= 30: + logger.warning("%s PWM is %d but Speed %d <= %d RPM" % (item, self.fan_pwm, speed, rpm_max * 0.7)) + else: + self.fanStatus[key] = self.fanStatus[key] & ~(STATUS_BAD_FAN) + + if speed < 1000: + if self.fanStatus[key] & STATUS_LOW_FAN != 0: + self.fanLowTime[key][0] = time.time() + else: + self.fanLowTime[key][1] = time.time() + self.fanStatus[key] = self.fanStatus[key] | STATUS_LOW_FAN + if self.fanLowTime[key][1] - self.fanLowTime[key][0] > 30: + logger.warning("%s Speed %d <= %d RPM" % (item, speed, 1000)) + else: + self.fanStatus[key] = self.fanStatus[key] & ~(STATUS_LOW_FAN) + + fanctrl_debug_log("%s speed %d RPM" % (key, speed)) + + if self.fanStatus[key] != 0: + fan_error_cnt = fan_error_cnt + 1 + self.fan_status = fan_error_cnt + fanctrl_debug_log("Fan error num %d" % fan_error_cnt) + + def doApplyPolicy(self): + if self.isLiquid == 1: + return + openloop_pwm = int(self.openloop.calcPwm()) + fanctrl_debug_log("OpenLoop pwm %d" % (openloop_pwm)) + self.fan_pwm = openloop_pwm + # Check fan presence + if self.interface.get_fan_presence() == False: + logger.warning("Fan presence check false, set fan pwm to 100") + self.fan_pwm = 100 + if self.fan_status != 0 or self.status != 0: + self.fan_pwm = 100 + fanctrl_debug_log("Fan Speed set to %d pwm" % self.fan_pwm) + for i in range(3): + ret = self.setFanSpeed(self.fan_pwm) + if ret == False: + logger.warning("Fan speed set %d pwm failed, retry %d times" % (self.fan_pwm, i + 1)) + continue + break + + def doBoardFanLedCtrl(self): + if self.interface.get_fan_status() != False and self.interface.get_fan_presence() != False and self.fan_status == 0: + fanctrl_debug_log("Fan status good setting LED to green") + self.interface.set_fan_board_led("green") + else: + fanctrl_debug_log("Fan status error setting LED to red") + self.interface.set_fan_board_led("red") + + def doBoardPsuLedCtrl(self): + if self.interface.get_psu_status() != False: + fanctrl_debug_log("PSU status good setting LED to green") + self.interface.set_psu_board_led("green") + else: + fanctrl_debug_log("PSU status error setting LED to red") + self.interface.set_psu_board_led("red") + +def run(interval, fanCtrol): + loop = 0 + # waitForDocker() + fanCtrol.setFanSpeed(fanCtrol.fan_pwm) #init set fan speed to 50 pwm + fanCtrol.doFanCtrlInit() + if fanCtrol.airflow == "Liquid": + logger.warning('Liquid device stopping fancontrol') + return True + while True: + try: + if loop % 5 == 0: # Fan speed control + try: + fanCtrol.updateThermal() + except Exception as e: + logger.error('Failed: Update Thermal, %s' % str(e)) + logger.error('%s' % traceback.format_exc()) + time.sleep(3) + continue + + try: + fanCtrol.checkThermal() + except Exception as e: + logger.error('Failed: Check Thermal, %s' % str(e)) + logger.error('%s' % traceback.format_exc()) + time.sleep(3) + continue + + try: + fanCtrol.checkFanSpeed() + except Exception as e: + logger.error('Failed: Check Fan Speed, %s' % str(e)) + logger.error('%s' % traceback.format_exc()) + time.sleep(3) + continue + + try: + fanCtrol.doApplyPolicy() + except Exception as e: + logger.error('Failed: Apply Policy, %s' % str(e)) + logger.error('%s' % traceback.format_exc()) + time.sleep(3) + continue + + try: + fanCtrol.doBoardFanLedCtrl() + except Exception as e: + logger.error('Failed: Led Control, %s' % str(e)) + logger.error('%s' % traceback.format_exc()) + time.sleep(3) + continue + + try: + fanCtrol.doBoardPsuLedCtrl() + except Exception as e: + logger.error('Failed: Led Control, %s' % str(e)) + logger.error('%s' % traceback.format_exc()) + time.sleep(3) + continue + time.sleep(interval) + loop += interval + except Exception as e: + traceback.print_exc() + logger.error(str(e)) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + '''start fan control''' + logger.info("FANCTROL start") + fanCtrol = FanControl() + interval = 1 + run(interval, fanCtrol) + +@main.command() +def stop(): + '''stop fan control ''' + logger.info("FANCTROL stop") + +# device_i2c operation +if __name__ == '__main__': + main() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/grtd_test.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/grtd_test.py new file mode 100644 index 000000000000..8318f287f46d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/grtd_test.py @@ -0,0 +1,1686 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +import sys +import click +import os +import subprocess +import syslog +import json +import mmap +import time +import device_i2c as di +import re +import traceback +from ragileutil import * +from click_default_group import DefaultGroup +from tabulate import tabulate +import unicodedata +from eepromutil.fru import * +# from rest.rest import DeviceMessage +# from rest.rest import BMCMessage + +def restful_get(url): + if url == "" or len(url) <=0: + print ("invalid url") + return + from rest.rest import DeviceMessage, BMCMessage + bmc = BMCMessage() + value = bmc.getBmcValue(url) + json_dicts=json.dumps(value,indent=4) + return str(json_dicts) + +def wide_chars(s): + if isinstance(s, str): + s = s.decode('utf-8') + return sum(unicodedata.east_asian_width(x) in ('F', 'W') for x in s) + +try: + from port import PortTest,PortPrbsTest + import ConfigParser as configparser + +except ImportError: + pass + +stopFanctrol = di.stopFanctrol +startFanctrol = di.startFanctrol + +GRTD_BROADCAST_RETRY_SLEEP_TIME = 3 + +SYSLOG_IDENTIFIER = "GRTD_TEST" + +# ========================== Syslog wrappers ========================== +def log_info(msg, also_print_to_console=False): + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +def log_debug(msg, also_print_to_console=False): + try: + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + except Exception as e: + pass + +def log_warning(msg, also_print_to_console=False): + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + + +def log_error(msg, also_print_to_console=False): + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +# Print the output according to the format +def port_totalprint(arr, tips): + if len(arr) <= 0: + return + print("%-20s" % tips ,) + for index in range(len(arr)): + print ("%03d" % arr[index] ,) + if (index + 1) % 8 == 0: + print ("") + print (" " * 20,) + print ("") + +# Port frame +def test_port_portframe(): + try: + from port import PortScene, hsdk_check + if (hsdk_check()): + portscene = PortScene() + return portscene.port_frame_test(port_list=[]) + else: + return test_port_portframe_old() + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + +# Original logic of sending and receiving frames on the port +def test_port_portframe_old(): + framenum = 10000 + len_t = len(PortTest().bcm_ports) + upports = [] + ret_t = 0 + errt_t = [] + testerror ={} + caseerror=[] + testerror["name"] = "端口收发帧" + successport=[] + updownerrport=[] + errorport = [] + try: + # All values UP Port PRBS + for i in range(len_t): + status = PortTest().get_port_status(i + 1) + if status == "up": + upports.append(i + 1) + PortTest().init_port_cpu() + PortTest().clear_port_packets() + for i in range(len(PortTest().bcm_ports)): + if (i + 1) in upports : + PortTest().start_send_port_packets(i + 1, framenum, 1024) + log_debug("%d:正在发包"%(i+1)) + time.sleep(5) + for i in range(len(PortTest().bcm_ports)): + if (i + 1) in upports : + ret, log = PortTest().check_port_packets(i + 1, framenum, "rx") + log_debug(ret) + if ret == True: + successport.append(i + 1) + else: + errorport.append(i + 1) + ret_t -= 1 + caseerror.append({"name":"端口%d"%(i + 1), "error":"端口收发帧失败"}) + log_debug(log) + else: + ret_t -= 1 + caseerror.append({"name":"端口%d"%(i + 1), "error":"up/down状态异常"}) + updownerrport.append(i+1) + except Exception as e: + print (e) + ret_t = -1 + finally: + PortTest().reset_port_cpu() + port_totalprint(successport, "OK") + port_totalprint(updownerrport, "up/down状态异常") + port_totalprint(errorport, "failed") + testerror['errmsg'] = caseerror + errt_t.append(testerror) + if ret_t < 0: + return False , errt_t + return True ,"" + + +def test_ports_prbs_new(): + '''ports prbs''' + + result_t = [] + testerror1 = {} + testerror1["name"] = "mac prbs测试结果" + testerror2 = {} + testerror2["name"] = "sys prbs测试结果" + testerror3 = {} + testerror3["name"] = "line prbs测试结果" + pr = None + val_ber = TESTCASE.get("PRBS").get("prbsber", None) + # print val_ber + if val_ber is None: + pr = PortPrbsTest(val_ber) + else: + pr = PortPrbsTest() + pr.clear_port_prbs() + ret, log = pr.init_port_prbs() + if ret == False: + raise Exception("prbs初始化失败 %s" % log) + total_err = 0 + caseerror=[] + print ("mac prbs测试结果:") + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("mac", i + 1) + if ret == False: + print ("端口%03d : " % (i + 1),) + print (result) + total_err -= 1 + caseerror.append({"name":"端口%03d"%(i + 1), "error":result}) + testerror1['errmsg'] = caseerror + + caseerror=[] + print ("sys prbs测试结果:") + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("sys", i + 1) + if ret == False: + print ("端口%03d : " % (i + 1),) + print (result) + total_err -= 1 + caseerror.append({"name":"端口%03d"%(i + 1), "error":str(result)}) + testerror2['errmsg'] = caseerror + + caseerror=[] + print ("line prbs测试结果:") + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("line", i + 1) + if ret == False: + print ("端口%03d : " % (i + 1),) + print (result) + total_err -= 1 + caseerror.append({"name":"端口%03d"%(i + 1), "error":str(result)}) + + testerror3['errmsg'] = caseerror + pr.clear_port_prbs() + + result_t.append(testerror1) + result_t.append(testerror2) + result_t.append(testerror3) + + if total_err < 0: + return False , result_t + return True ,"" + +# port prbs +def test_port_prbs(): + errt_t = [] + ret_t = 0 + # Take port + len_t = len(PortTest().bcm_ports) + errmsg = [] + testerror ={} + caseerror=[] + testerror["name"] = "端口PRBS" + upports = [] + + successport=[] + updownerrport=[] + errorport = [] + + PortTest().init_port_prbs() + for i in range(len_t): + sta = PortTest().get_port_status(i + 1) + if sta == "up": + upports.append(i + 1); + log_debug(",".join(str(index) for index in upports)) + for i in range(len_t): + if (i + 1) in upports : + PortTest().set_port_prbs(i + 1, 1) + time.sleep(5) + # get value + for i in range(len_t): + if (i + 1) in upports : + log_debug("端口prbs校验:%d"% (i + 1)) + ret = PortTest().get_port_prbs_result(i + 1) + # log_debug(ret) + if ret == 0: + # print "端口%d : %s" %( i + 1, "[ok]") + successport.append(i + 1) + else: + errorport.append(i + 1) + caseerror.append({"name":"端口%d"%(i + 1), "error":"prbs测试失败"}) + ret_t -= 1 + else: + updownerrport.append(i + 1) + ret_t -= 1 + caseerror.append({"name":"端口%d"%(i + 1),"error":"up/down状态异常"}) + + # All values UP Port PRBS + for i in range(len_t): + if (i + 1) in upports : + PortTest().set_port_prbs(i + 1, 0) + PortTest().reset_port_prbs() + testerror['errmsg'] = caseerror + errt_t.append(testerror) + + port_totalprint(successport, "OK") + port_totalprint(updownerrport, "up/down状态异常") + port_totalprint(errorport, "failed") + + if ret_t < 0: + return False , errt_t + return True ,"" + +# Port broadcast test +def test_port(): + errt_t = [] + ret_t = 0 + # Take port + len_t = len(PortTest().bcm_ports) + errmsg = [] + + successport=[] + updownerrport=[] + errorport = [] + + # Obtain which port is valid + for i in range(len_t): + sta = PortTest().get_port_status(i + 1) + if sta == "up": + log_debug("发送广播报文端口:%d" % (i+1)) + ret = PortTest().start_send_port_packets((i + 1), 10000) + break + else: + log_debug(" 端口%d 状态:%s"% ( i + 1 ,sta)) + errmsg.append({"name":PortTest().bcm_ports[i], "error":sta}) + # Waiting time + time.sleep(GRTD_BROADCAST_RETRY_SLEEP_TIME) + log_debug("等待结果......") + + errt_t = [] + testerror ={} + caseerror=[] + testerror["name"] = "端口广播" + for i in range(len_t): + sta = PortTest().get_port_status(i + 1) + log_debug("端口%d结果%s......"% ((i+1),sta)) + if sta == "up": + ret , fcs = PortTest().get_port_fcs_status(i + 1) + if ret == True and fcs[0] == 0 and fcs[1] == 0: + successport.append(i + 1) + else: + ret_t -= 1 + errorport.append(i + 1) + caseerror.append({"name":"端口%d"%(i + 1) ,"error":" 发送校验:%d 接收校验 %d" %(fcs[0], fcs[0]) }) + log_debug("error: 端口%d 发送校验:%d 接收校验 %d" %( (i + 1), fcs[0], fcs[0]) ) + else: + ret_t -= 1 + updownerrport.append(i + 1) + caseerror.append({"name":"端口%d"%(i + 1), "error":"up/down状态异常"}) + testerror['errmsg'] = caseerror + errt_t.append(testerror) + # Close the radio + sta = PortTest().stop_send_port_packets() + time.sleep(5) + + port_totalprint(successport, "OK") + port_totalprint(updownerrport, "up/down状态异常") + port_totalprint(errorport, "failed") + if ret_t < 0: + return False , errt_t + return True ,"" + +def fan_check(fans, levelpolicy , errt_t): + ret_t = 0 + try: + stopFanctrol() + # Keep the current fan level + currentValue = "null" + currentValue = get_pmc_register(fans["location"]) + log_debug("当前转速等级为: %s" % currentValue) + print ("%s" % fans.get("name",None)) + # Keep the current fan level + for level in levelpolicy["level"]: + testerror = {} + testind = 0 + ind = levelpolicy["level"].index(level) + loc = fans["location"] + if write_sysfs_value(loc, "0x%02x"% level ) : + time.sleep(2) + print ("风扇转速等级: 【%s】 0x%02x "% (levelpolicy["tips"][ind], level)) + log_debug("风扇转速等级: 【%s】 0x%02x " % (levelpolicy["tips"][ind], level)) + caseerror = [] + for fanstatus in fans["childfans"]: + real_value = get_pmc_register(fanstatus["location"]) + nowspeed = int(real_value) + lowspeed = levelpolicy["low_speed"][ind] + highspeed = levelpolicy["high_speed"][ind] + log_debug("%s [nowspeed: %d low_speed:%d high:%d]"% (fanstatus["name"], nowspeed ,lowspeed,highspeed)) + if lowspeed < nowspeed and highspeed > nowspeed: + print (" %s : %s"%(fanstatus["name"], "[PASS]")) + else: + print (" %s : %s"%(fanstatus["name"], "[FAILED]")) + caseerror.append({"name":fanstatus["name"] ,"error":"不在转速范围内 [nowspeed: %d low_speed:%d high:%d]" % ( nowspeed ,lowspeed,highspeed)}) + ret_t -= 1 + testind -= 1 + if len(caseerror) > 0: + testerror["name"] = "[%s]转速等级:[%s]0x%02x "% (fans.get("name",None),levelpolicy["tips"][ind], level) + testerror['errmsg'] = caseerror + if testind < 0: + errt_t.append(testerror) + except Exception as e: + log_error(e.message) + return False + finally: + if write_sysfs_value(loc, currentValue): + log_debug("恢复初始转速") + startFanctrol() + if ret_t < 0: + return ret_t + return ret_t + +# execute shell command +def log_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + +class Config(object): + """Object to hold CLI config""" + def __init__(self): + self.path = os.getcwd() + self.aliases = {} + + def read_config(self, filename): + parser = configparser.RawConfigParser() + parser.read([filename]) + try: + self.aliases.update(parser.items('aliases')) + except configparser.NoSectionError: + pass +_config = None + +############################################################################# +######### ragile util cli +############################################################################ +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(DefaultGroup): + def get_command(self, ctx, cmd_name): + global _config + if _config is None: + _config = Config() + cfg_file = os.path.join(os.path.dirname(__file__), 'aliases.ini') + _config.read_config(cfg_file) + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + if cmd_name in _config.aliases: + actual_cmd = _config.aliases[cmd_name] + return click.Group.get_command(self, ctx, actual_cmd) + matches = [x for x in self.list_commands(ctx) + if x.lower().startswith(cmd_name.lower())] + if not matches: + ctx.arg0 = cmd_name + cmd_name = self.default_cmd_name + return DefaultGroup.get_command(self, ctx, cmd_name) + elif len(matches) == 1: + return DefaultGroup.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +@click.group(context_settings=CONTEXT_SETTINGS) +def main(): + '''ragileutil interface''' + pass + +# get regisetr value +@main.command() +@click.argument('bus', required=True) +@click.argument('loc', required=True) +@click.argument('bit', required=True) +def dev_rd(bus, loc , bit): + ''' i2c_rd get issuccess''' + ret , log = rji2cget(int(bus), int(loc, 16) , int(bit, 16)) + if ret == True: + click.echo("SUCCESS") + else: + click.echo(log) + +# write register +@main.command() +@click.argument('bus', required=True) +@click.argument('loc', required=True) +@click.argument('bit', required=True) +@click.argument('value', required=True) +def dev_wr(bus, loc , bit, value): + ''' i2c_set set value if success''' + ret , log = rji2cset (int(bus), int(loc, 16) , int(bit, 16), int(value, 16)) + if ret == True: + click.echo("SUCCESS") + else: + click.echo("Error:" + log) + +# cpld test +@main.command() +@click.argument('bus', required=True) +@click.argument('loc', required=True) +@click.argument('bit', required=True) +def cpld_check(bus, loc , bit): + '''check read/write test''' + try: + ret , log = rji2cget(int(bus), int(loc, 16) , int(bit, 16)) + if ret != True: + click.echo("Error[get bus:%s loc:%s bit:%s] %s" %(bus, loc,bit ,log)) + return + value = 0xFF ^ int(log, 16) + ''' check i2c dev''' + ret , log = rji2cset(int(bus), int(loc, 16) , int(bit, 16), value) + if ret != True: + click.echo("Error[write bus:%s loc:%s bit:%s] %s" %(bus, loc,bit ,log)) + return + ret , log = rji2cget(int(bus), int(loc, 16) , int(bit, 16)) + if ret != True : + click.echo("Error[confirm bus:%s loc:%s bit:%s] %s" %(bus, loc,bit ,log)) + return + if int(log, 16) != value : + click.echo("Error: read not equal write") + return + click.echo("SUCCESS") + except Exception as e: + click.echo("Error" + str(e)) + +@main.command() +@click.argument('location', required=True) +def sysfs(location): + '''get sysfs value''' + pos_t = str(location) + name = get_pmc_register(pos_t) + click.echo(name) + +# Takes the I2C name at the specified location +@main.command() +@click.argument('location', required=True) +@click.argument('value', required=False) +def i2c(location , value): + '''check i2c name''' + pos_t = str(location) + "/name" + name = get_pmc_register(pos_t) + click.echo(name) + +@main.group() +def led(): + ''' led test''' + pass + +# Writes values to the specified file +# grtd_test led loc 2-0033/broad_front_cpu 0x01 +@led.command() +@click.argument('location', required=True) +@click.argument('value', required=True) +def loc(location, value): + locs = location.split(",") + val = value.split(",") + if len(locs) != len(val): + click.echo("不相等") + else: + for i in range(len(locs)): + cmd = "echo %s > %s%s" % (val[i], MAILBOX_DIR,locs[i]) + ret , log =log_os_system(cmd) + if ret != 0: + click.echo("Error") + click.echo(log) + click.echo("SUCCESS") + +@main.command() +@click.argument('location', required=True) +def temp(location): + cmd = "cat %s%s" % (MAILBOX_DIR, location) + ret , log = log_os_system(cmd) + if ret != 0: + click.echo("Error") + click.echo(log) + +@main.group() +def fan(): + ''' fan set ''' + pass + +def printbinvalue(b): + index = 0 + print (" ",) + for width in range(16): + print ("%02x " % width,) + print ("") + for i in range(0, len(b)): + if index % 16 == 0: + print (" ") + print (" %02x " % i,) + print ("%02x " % ord(b[i]),) + index += 1 + print ("") + +def decodeBinByValue(retval): + fru = ipmifru() + fru.decodeBin(retval) + return fru + +@fan.command() +def resetfane2(): + ''' show fan e2''' + fru = ipmifru() + # fru.initDefault() + boardinfoarea = BoardInfoArea(name="Board Info Area", + size=0) + boardinfoarea.isPresent = True + boardinfoarea.boardManufacturer = "Ragile" + boardinfoarea.boardProductName = "M2EFAN I" + boardinfoarea.boardSerialNumber = "0000000000000" + boardinfoarea.boardPartNumber = "M2EFAN I" + boardinfoarea.fruFileId = "3-8" + boardinfoarea.boardextra1 = 'AA' + + pia = ProductInfoArea(name="Product Info Area ", + size=0) + pia.isPresent = True + pia.productManufacturer = 'Ragile' + pia.productName = 'M2EFAN I-F' + pia.productPartModelName = 'M2EFAN I-F' + pia.productVersion = '00' + pia.productSerialNumber = '0000000000000' + pia.productAssetTag = None + pia.fruFileId = '3-8' + pia.productextra1 = '2019-03-27' + pia.productextra2 = '8600' + fru.productInfoArea = pia + fru.boardInfoArea = boardinfoarea + fru.recalcute() + printbinvalue(fru.bindata) + + + fans = FRULISTS.get('fans') + for fan in fans: + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(fan.get('bus'), fan.get('loc'), fru.bindata) + I2CUTIL.closeFanE2Protect() + +@fan.command() +def showfane2(): + fans = FRULISTS.get('fans') + header = [ 'FAN', 'Presence', 'Status', 'Speed', 'LowThd', 'HighThd', 'PN', 'SN', 'AirFlow' ] + status_table = [] + for fan in fans: + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + ret = decodeBinByValue(eeprom) + # print ret + fan_name = fan.get('name') + presence = True + status = True + speed = 0 + low = 0 + high = 0 + pn = ret.productInfoArea.productName + sn = ret.productInfoArea.productSerialNumber + airflow = 'FTOB' + + status_table.append([fan_name, presence, status, speed, low, high, pn, sn, airflow]) + click.echo(tabulate(status_table, header, tablefmt='simple')) + + +def checkinput(b): + if b.isdigit() == False: + raise Exception("非法数字") + if int(b) > 0xff or int(b) < 0: + raise Exception("不在区间内") + +def checkinputproduct(b): + if b.isalnum() ==False: + raise Exception("非法字符串") + +def getInputSetmac(val): + bia = val.boardInfoArea + pia = val.productInfoArea + if bia != None: + a = raw_input("[板卡区]产品序列号:") + if len(a) != 13: + raise Exception("序列号长度不对") + checkinputproduct(a) + bia.boardSerialNumber = a + b = raw_input("[板卡区]产品版本号:(从1-255)") + checkinput(b) + b = "%0x" % int(b) + bia.boardextra1 = b.upper() + if pia != None: + a = raw_input("[产品区]产品序列号:") + if len(a) != 13: + raise Exception("序列号长度不对") + checkinputproduct(a) + pia.productSerialNumber = a + b = raw_input("[产品区]产品版本号:(从1-255)") + checkinput(b) + b = "%0x" % int(b) + pia.productVersion = b.upper() + return val + +@fan.command() +def setmace2(): + '''fan setmac e2''' + fans = FRULISTS.get('fans') + for fan in fans: + eeprom = get_fane2_sysfs(fan.get('bus'), fan.get('loc')) + fru = decodeBinByValue(eeprom) + newfru = getInputSetmac(fru) + + newfru.recalcute() + + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(fan.get('bus'), fan.get('loc'), newfru.bindata) + I2CUTIL.closeFanE2Protect() + + pass + +@fan.command() +def setmac_open(): + '''enable setmac fan e2''' + I2CUTIL.openFanE2Protect() + +@fan.command() +def setmac_close(): + '''disable setmac fan e2''' + I2CUTIL.closeFanE2Protect() + +@fan.command() +def speed_max(): + ''' set fan speed max''' + stopFanctrol() + cmd = "echo 0xFF > /sys/bus/i2c/devices/0-0032/fan_speed_set" + ret , log = log_os_system(cmd) + if ret != 0: + click.echo("Error") + click.echo(log) + +@fan.command() +@click.argument('level', required=True) +def speed(level): + ''' set fan speed_level as input''' + cmd = "echo %s > /sys/bus/i2c/devices/0-0032/fan_speed_set" % level + ret , log = log_os_system(cmd) + if ret != 0: + click.echo("Error") + click.echo(log) + +@fan.command() +def monitor_start(): + ''' fan control beyond sonic''' + if STARTMODULE['fancontrol'] == 1: + startFanctrol() + else: + click.echo("no fancontrol") + +@fan.command() +def monitor_stop(): + '''stop fancontrol.py''' + if STARTMODULE['fancontrol'] == 1: + stopFanctrol() + else: + click.echo("no fancontrol") + +@main.group() +def port(): + pass + +@port.command() +def deleteprbs(): + '''clear port prbs''' + len_t = len(PortTest().bcm_ports) + print (len_t) + for i in range(len_t): + PortTest().set_port_prbs(i + 1, 0) + +@main.group() +def e2(): + ''' show eeprom ''' + # ret = get_sys_eeprom() + # for item in ret: + # print "%-20s : %s" % (item["name"], item["value"]) + +@click.command() +def cardid(): + ''' product cardid ''' + ret = getCardId() + click.echo(ret) + +@click.command() +def cardidreset(): + '''product cardid reset''' + ret = getCardId() + if ret != None: + ret_input = getInputCheck("realy want do reset tlv all(Yes/No):") + print (ret_input) + if ret_input != True: + return None + else: + eeprom_ret = get_sys_eeprom() + for item in eeprom_ret: + print ("%-20s : %s" % (item["name"], item["value"]) ) + _value = {} + _value[TLV_CODE_VENDOR_EXT] = generate_ext(RAGILE_CARDID) + rst, ret = generate_value(_value) + writeToEEprom(rst) + + ret = getCardId() + print (ret) + +@click.command() +def tlvdetail(): + ''' show eeprom detail ''' + ret = get_sys_eeprom() + for item in ret: + print ("%-20s : %s" % (item["name"], item["value"])) + +@click.command() +def settlve2(): + return fac_board_setmac() + +def getfilevalue(location): + try: + with open(location, 'r') as fd: + retval = fd.read() + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return True, retval.strip() + except Exception as e: + return False, "error" +ret, result = getfilevalue("/tmp/.debug") +if ret == True and result == "openset": + e2.add_command(cardidreset) + e2.add_command(settlve2) + +e2.add_command(cardid) +e2.add_command(tlvdetail) + +""" +@click.command() +def resetall(): + '''reset all E2''' + ret = getInputCheck("realy want do reset all(Yes/No):") + if ret != True: + return + I2CUTIL.openFanE2Protect() + frus = [ elem for elem in FRULISTS if '1'==elem["CANRESET"] ] + for fru in frus: + ret = FruUtil.fru_getdefault_eeprom(fru['E2PRODUCT'], fru['E2TYPE']) + I2CUTIL.writeToE2(fru['bus'], fru['loc'], ret.bindata) + click.echo("%02d %02x update success" %(fru['bus'], fru['loc'])) + I2CUTIL.closeFanE2Protect() + pass + + + +@click.command() +@click.argument('e2type', required=True, default="ZZ" ) +def set(e2type): + '''set fru by type''' + if e2type == "ZZ": + showe2typetips(); + return + FruUtil().setmac(e2type) + +@click.command() +@click.argument('type', required=True, default = 'ZZ') +def show(type): + '''show frus by type''' + if type == 'ZZ': + showe2typetips(); + return + psus = [ elem for elem in FRULISTS if type == elem["E2TYPE"]] + for val in psus: + print "####################%s####################" % val["name"] + filename = I2CUTIL.getE2File(val['bus'], val['loc']) + ret = FruUtil.fru_decode_eeprom(filename) + head = ["key","value"] + if ret.boardInfoArea!= None: + click.echo("=================board=================") + click.echo(tabulate(ret.boardInfoArea.todict().items(), head, tablefmt="simple")) + + if ret.productInfoArea!= None: + click.echo("\n\n=================product=================") + click.echo(tabulate(ret.productInfoArea.todict().items(), head, tablefmt="simple")) + +@click.command() +def getall(): + '''get all E2''' + for fru in FRULISTS: + click.echo("\n\n================%s======================"%fru['name']) + filename = I2CUTIL.getE2File(fru['bus'], fru['loc']) + ret = FruUtil.fru_decode_eeprom(filename) + head = ["key","value"] + if ret != None: + if ret.boardInfoArea!= None: + click.echo(tabulate(ret.boardInfoArea.todict().items(), head, tablefmt="simple")) + if ret.productInfoArea!= None: + click.echo(tabulate(ret.productInfoArea.todict().items(), head, tablefmt="simple")) + pass +def getfilevalue(location): + try: + with open(location, 'r') as fd: + retval = fd.read() + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return True, retval.strip() + except Exception as e: + return False, "error" +ret, result = getfilevalue("/tmp/.debug") +if ret == True and result == "openset": + e2.add_command(cardidreset) + e2.add_command(resetall) + e2.add_command(set) + e2.add_command(settlve2) + + + +e2.add_command(cardid) +e2.add_command(getall) +e2.add_command(tlvdetail) +""" + + +def showe2typetips(): + ret = FRULISTS.keys() + + e2type2 = FRULISTS.keys() + click.echo("please inpute type such as:" ) + for itemtype in e2type2: + click.echo("\t%s : %s" % (itemtype,itemtype)) + +@click.command() +@click.argument('types', required=True, default = 'ZZ') +def show(types): + '''show frus by type''' + if type == 'ZZ': + showe2typetips(); + return + + for val in FRULISTS.get(types): + print ("####################%s####################" % val["name"]) + eeprom = get_fane2_sysfs(val['bus'], val['loc']) + ret = decodeBinByValue(eeprom) + head = ["key","value"] + if ret.boardInfoArea!= None: + click.echo("=================board=================") + click.echo(tabulate(ret.boardInfoArea.todict().items(), head, tablefmt="simple")) + + if ret.productInfoArea!= None: + click.echo("\n\n=================product=================") + click.echo(tabulate(ret.productInfoArea.todict().items(), head, tablefmt="simple")) +e2.add_command(show) + +@main.group() +def sys(): + pass + + +@main.group(cls=AliasedGroup) +def setmac(): + pass + +@setmac.command() +@click.argument('eth', required=False,default = "eth0" ) +@click.argument('mac', required=True) +def hwaddrset(eth, mac): + ''' set hwaddr''' + ret ,msg = util_setmac(eth, mac) + if ret == True: + click.echo("设置成功") + else: + click.echo("设置失败[%s]" % msg) + +@setmac.command() +def hwaddrget(eth, mac): + get_local_eth0_mac() + +@setmac.command() +def bmcreset(): + if ipmi_set_mac("00:10:f3:32:91:d7")==True: + click.echo("设置bmc成功") + +@setmac.command() +def bmcinfo(): + ret, status =log_os_system("ipmitool lan print 1") + click.echo(status) + +@sys.command() +def mem(): + '''get hardware mem slot and size''' + ret, result = getsysmeminfo() + if ret == True: + for item in result: + click.echo (" 槽位号%s : %s" % (item['slot'], item['size'])) + +@sys.command() +def memdetail(): + '''get hardware mem message detail''' + ret , result = getsysmeminfo_detail() + if ret == True: + for item in result: + click.echo("内存槽位:%s"%item["Locator"]) + click.echo("====================================================") + for v,k in item.items(): + click.echo("%-30s: %s"% (v ,k)) + click.echo("") + +@sys.command() +def hwinfo(): + '''get hardware bios''' + ret , result = gethwsys() + + head = ["key","value"] + if ret == True: + click.echo(tabulate(result.items(), head, tablefmt="simple")) + click.echo("") + +@sys.command() +def bios(): + '''get hardware bios''' + ret , result = getsysbios() + head = ['key','value'] + if ret == True: + click.echo(tabulate(result.items(), head, tablefmt="simple")) + click.echo("") + +def getFormatHead(HEAD): + len_t = len(HEAD) + formatstr = " " + headtip = formatstr + septips = formatstr + for i in range(len_t): + formatstr += "%-20s " + headtip += "%%-%ds "%(20+wide_chars(HEAD[i])) + septips +="%-20s " + headtip = headtip % HEAD[i] + septips = septips % ("-"*20) + print (headtip) + print (septips) + return formatstr + +def cpld_version_restful(url): + if url == "" or len(url) <=0: + print("invalid url") + return + from rest.rest import DeviceMessage, BMCMessage + bmc = BMCMessage() + value = bmc.getBmcValue(url) + if value == None: + return None + json_dicts=json.dumps(value,indent=4) + return json_dicts + + +@sys.command() +def cpld_version(): + '''get cpld version''' + if len(CPLDVERSIONS) <=0: + click.echo("没找到配置文件") + header = ["名称","日期","版本"] + formatstr = getFormatHead(header) + result = [] + for cpld in CPLDVERSIONS: + dict = {} + gettype = cpld.get("gettype",None) + bus = cpld.get("bus",None) + devno = cpld.get("devno",None) + url = cpld.get("url",None) + io_addr = cpld.get("io_addr",None) + data = "" + t = True + ret = None + if gettype == "lpc": + for i in range(4): + ret = lpc_cpld_rd(i) + if ret == None: + t = False + break; + data += chr(strtoint(ret)) + elif gettype == "io": + for i in range(4): + ret = io_rd(io_addr + i) + if ret == None: + t = False + break; + data += chr(strtoint(ret)) + elif gettype == "restful": + ret = cpld_version_restful(url) + if ret == None: + continue + data_1 = ret.replace("\""," ").strip().split(" ") + for item in data_1: + data += chr(strtoint(item)) + else: + for i in range(4): + ind, ret = rji2cget(bus, devno, i) + if ind == False: + t = False + break; + data += chr(strtoint(ret)) + if data == "": + result.append([ cpld.get('name',None),"NA","NA" ]) + else: + result.append([ cpld.get('name',None),"%02x%02x%02x" % (ord(data[1]) ,ord(data[2]) ,ord(data[3])),"%02x" % (ord(data[0]))]) + for item in result: + formatstr = " %%-%ds %%-20s %%-20s "%((20+wide_chars(item[0]))) + print (formatstr%(item[0],item[1],item[2])) + + # print item[0] + # click.echo(tabulate(result, header, tablefmt="simple")) +@sys.command() +def mactemp(): + sta, ret = getMacTemp(); + head = ["temp(average)","temp(max)"] + formatstr = getFormatHead(head) + print (" %-20s %-20s "%(ret['average'],ret['maximum'])) + +@sys.command() +def cputemp(): + '''show cpu temp''' + cputemp =[] + status.getcputemp(cputemp) + head = ["name","temperature"] + formatstr = getFormatHead(head) + for ctemp in cputemp: + print (formatstr % (ctemp["name"], str(ctemp["temp"]) + "℃" )) + +@sys.command() +def usbinfo(): + '''show usb info''' + ret , info = getusbinfo(); + if ret == False: + print (info) + return + click.echo("%s %s"%("-"*6,"-"*20)) + click.echo("{id} {size}G".format(**info)) + + +@main.group() +def mac(): + pass + +@mac.command() +@click.argument('name', required=True) +def getreg(name): + '''get sdk reg''' + ret, status = getSdkReg(name)# DMU_PCU_OTP_CONFIG_8 + # click.echo (status) + if ret == False: + click.echo(status) + click.echo("%s : %s"% (name, status)) + +@mac.command() +def pressure(): + ''' MAC Voltage regulation ''' + ret = AVSUTIL.mac_adj() + if ret == False: + click.echo("调压失败") + else: + click.echo("调压成功") + +@main.group() +def restful(): + pass +@restful.command() +@click.argument('url', required=True) +def get(url): + if url == "" or len(url) <=0: + print("invalid url") + return + from faclib.rest import HttpRest + response = HttpRest().Get(url) + print (response) + +def lpc_cpld_rd(reg_addr): + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/lpc_cpld" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str = os.read(fd, 1) + return "%02x" % ord(str) + except ValueError: + return None + except Exception as e: + print (e) + return None + finally: + os.close(fd) + return None + +@main.group() +def io(): + pass + +@io.command() +@click.argument('reg_addr', required=True) +@click.argument('len', required=True, default = 1, type = click.INT) +def rd(reg_addr,len): + val = io_rd(reg_addr, len) + print (val) + + +@io.command() +@click.argument('reg_addr', required=True) +@click.argument('reg_data', required=True) +def wr(reg_addr, reg_data): + val = io_wr(reg_addr, reg_data) + print (val) + + +@main.group() +def pci(): + pass + +@pci.command() +@click.argument('pcibus', required=True) +@click.argument('slot', required=True) +@click.argument('fn', required=True) +@click.argument('bar', required=True, type = int) +@click.argument('offset', required=True, type = int) +def rd(pcibus , slot , fn, bar, offset): + '''read pci register''' + if offset % 4 != 0: + click.echo("offset must be multiple of 4") + return + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + with open(filename, "r+") as file: + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + click.echo("0x%08x" % val) + data.close() + pass + +@pci.command() +@click.argument('pcibus', required=True) +@click.argument('slot', required=True) +@click.argument('fn', required=True) +@click.argument('bar', required=True, type = int) +@click.argument('offset', required=True, type = int) +@click.argument('data', required=True) +def wr(pcibus , slot ,fn, bar, offset, data): + '''write pci register''' + vl = strtoint(data) + ret = inttostr(vl, 4) + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + with open(filename, "r+") as file: + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + data[offset: offset + 4] = ret + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + click.echo("0x%08x" % val) + data.close() + pass + +def bmc_version_inner(): + "get bmc version" + from rest.rest import DeviceMessage, BMCMessage + BMC_VER_PATH="/xyz/openbmc_project/version/attr/BmcVersion" + bmc = BMCMessage() + value = bmc.getBmcValue(BMC_VER_PATH) + if value == None: + return -1 + json_dicts=json.dumps(value,indent=4) + bmc_ver_str =("BMC Version:%s"%json_dicts) + print(" %-20s\n"%bmc_ver_str) + return 0 + + +def cpld_version_inner(): + '''get cpld version''' + if len(CPLDVERSIONS) <=0: + click.echo("没找到配置文件") + header = ["名称","日期","版本"] + result = [] + return_ret = 0 + return_log = "Success" + for cpld in CPLDVERSIONS: + dict = {} + gettype = cpld.get("gettype",None) + bus = cpld.get("bus",None) + devno = cpld.get("devno",None) + url = cpld.get("url",None) + data = "" + t = True + ret = None + if gettype == "lpc": + for i in range(4): + ret = lpc_cpld_rd(i) + if ret == None: + t = False + break; + data += chr(strtoint(ret)) + elif gettype == "restful": + ret = cpld_version_restful(url) + if ret == None: + return_ret = -1 + return_log = "get version failed: restful type cpld" + continue + data_1 = ret.replace("\""," ").strip().split(" ") + for item in data_1: + data += chr(strtoint(item)) + else: + for i in range(4): + ind, ret = rji2cget(bus, devno, i) + if ind == False: + t = False + break; + data += chr(strtoint(ret)) + result.append([ cpld.get('name',None),"%02x%02x%02x" % (ord(data[1]) ,ord(data[2]) ,ord(data[3])),"%02x" % (ord(data[0]))]) + formatstr = getFormatHead(header) + for item in result: + formatstr = " %%-%ds %%-20s %%-20s "%((20+wide_chars(item[0]))) + print (formatstr%(item[0],item[1],item[2])) + return return_ret,return_log,result + +@sys.command() +def show_all_version(): + # ONIE version + print ("ONIE version\n") + cmd="grep -rn onie_build_date /host/machine.conf" + ret, log=log_os_system(cmd) + cmd="grep -rn onie_version /host/machine.conf" + ret1, log1=log_os_system(cmd) + if ret != 0 or ret1 != 0: + print ("get version failed: ONIE") + print (log+log1) + if len(log)<=0 or len(log1)<=0: + print ("get version failed: ONIE") + else: + check_onie_version=log1.split('=')[1].strip()+"_"+log.split('=')[1].strip() + print ("\tONIE 版本:%s"%(check_onie_version)) + # Check version consistency + config_onie_version=get_version_config_info("ONIE_VERSION") + # config_onie_version_test=get_rjconfig_info("ONIE_VERSION_TEST") + if config_onie_version == None: + onie_flag=True + else: + onie_flag=False + if not onie_flag : + if check_onie_version==config_onie_version.strip() : + print ("\tONIE 版本信息一致: PASS\n") + else: + print ("\tONIE 版本信息一致%s: FAILED\n"%(config_onie_version)) + + # diag version + print ("diag version") + # cmd="show version 2>/dev/null | grep SONiC |awk '{print $4}'" + # ret, log=log_os_system(cmd) + cmd1="show version 2>/dev/null" + ret, log1=log_os_system(cmd1) + # log_debug("diag version:cmd1:%s"%log1) + cmd2="echo \"%s\" | grep SONiC"%log1 + ret, log2=log_os_system(cmd2) + # log_debug("diag version:cmd2:%s"%log2) + cmd="echo \"%s\" | awk '{print $4}'"%log2 + ret, log=log_os_system(cmd) + # log_debug("diag version:cmd3:%s"%log) + if ret != 0: + print ("get version failed: diag") + log_debug("diag version:cmd1:%s"%log1) + log_debug("diag version:cmd2:%s"%log2) + log_debug("diag version:cmd3:%s"%log) + # print log + if len(log)<5: + print ("get version failed: diag") + log_debug("diag version:cmd1:%s"%log1) + log_debug("diag version:cmd2:%s"%log2) + log_debug("diag version:cmd3:%s"%log) + else: + print ("\n\t"+log[6:]+"\n") + # Check version consistency + str_diag=get_version_config_info("DIAG_VERSION") + if str_diag == None: + diag_flag=True + else: + diag_flag=False + if not diag_flag: + if str_diag.strip()==log[6:].strip() : + print ("\tdiag 版本信息一致: PASS") + else: + print ("\tdiag 版本信息一致%s: FAILED"%(str_diag)) + + restful_url="/xyz/openbmc_project/version" + try: + log = restful_get(restful_url) + # print repr(log) + rest_t = json.loads(log) + if rest_t == None: + print("get version failed:restful获取失败") + return -1 + except Exception as e: + print (e) + return -1 + master_bmc_version_none=rest_t.get("MasterBmcVersion") + if master_bmc_version_none==None: + master_bmc_version="" + else: + master_bmc_version=master_bmc_version_none.encode('gbk') + slave_bmc_version_none=rest_t.get("SlaveBmcVersion") + if slave_bmc_version_none==None: + slave_bmc_version="" + else: + slave_bmc_version=slave_bmc_version_none.encode('gbk') + # current_bmc_version=rest_t.get("BmcVersion").encode('gbk') + + # BMC + print ("\nBMC Information\n") + ret = bmc_version_inner() + if ret != 0: + print ("get version failed: bmc") + # print "\n\t当前BMC版本:%s"%(current_bmc_version) + # Check version consistency + print ("\t主BMC版本:%s"%(master_bmc_version)) + config_bmc_master=get_version_config_info("BMC_MASTER_VERSION") + if config_bmc_master == None: + master_bmc_flag=True + else: + master_bmc_flag=False + if not master_bmc_flag: + if config_bmc_master.strip()==master_bmc_version.strip() : + print ("\n\tBMC 主版本信息一致: PASS") + else: + print ("\n\tBMC 主版本信息一致%s: FAILED"%(config_bmc_master)) + print ("\n\t备BMC版本:%s"%(slave_bmc_version)) + config_bmc_slave=get_version_config_info("BMC_SLAVE_VERSION") + if config_bmc_slave == None: + slave_bmc_flag=True + else: + slave_bmc_flag=False + if not slave_bmc_flag: + if config_bmc_slave.strip()==slave_bmc_version.strip() : + print ("\n\tBMC 备版本信息一致: PASS") + else: + print ("\n\tBMC 备版本信息一致%s: FAILED"%(config_bmc_slave)) + + # SDK + print ("\nSDK Information\n") + temp_sdk_version=get_version_config_info("SDK_VERSION") + if temp_sdk_version == None: + sdk_flag=True + else: + sdk_flag=False + + # print repr(temp_sdk_version) + cmd = "bcmcmd \"version\"" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: sdk") + print (log) + else: + version_temp = re.subn("( \r\n)|( \r\n\r\r\ndrivshell>)|(version\r\r)","",log)[0] + version_clean = re.subn("\n","\n\t",version_temp)[0] + print (version_clean) + # Check version consistency + if not sdk_flag: + sdk_temp1=version_temp.split('\n')[2] + # print repr(sdk_temp1) + sdk_version_temp=sdk_temp1.split(' ') + sdk_vers=sdk_version_temp[1] + sdk_date=sdk_version_temp[3] + check_sdk=sdk_vers.strip()+"_"+sdk_date.strip() + if check_sdk == temp_sdk_version.strip(): + print ("\tSDK 版本信息一致: PASS\n") + else: + print ("\tSDK %s版本信息一致%s: FAILED\n"%(check_sdk,temp_sdk_version)) + + # BOIS + cmd = "dmidecode -t bios" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: bios") + print (log) + else: + version_temp1 = re.subn("[\s\S]*(BIOS Information[\s\S]*)","\g<1>",log)[0] + version_clean = re.subn("Handle[^\n]*\n","",version_temp1)[0] + print (version_clean) + # Check version consistency + config_bios_master=get_version_config_info("BIOS_MASTER_VERSION") + if config_bios_master == None: + master_bios_flag=True + else: + master_bios_flag=False + master_bios_version_none=rest_t.get("MasterBiosVersion") + if master_bios_version_none==None: + master_bios_version="" + else: + master_bios_version=master_bios_version_none.encode('gbk') + print ("\t主BIOS版本:%s"%(master_bios_version)) + if not master_bios_flag: + if config_bios_master.strip()==master_bios_version.strip() : + print ("\tBIOS 主版本信息一致: PASS\n") + else: + print ("\tBIOS %s %s主版本信息一致: FAILED\n"%(master_bios_version,config_bios_master)) + config_bios_slave=get_version_config_info("BIOS_SLAVE_VERSION") + if config_bios_slave == None: + slave_bios_flag=True + else: + slave_bios_flag=False + slave_bios_version_none=rest_t.get("SlaveBiosVersion") + if slave_bios_version_none==None: + slave_bios_version="" + else: + slave_bios_version=slave_bios_version_none.encode('gbk') + print ("\t备BIOS版本:%s"%(slave_bios_version)) + if not slave_bios_flag: + if config_bios_slave.strip()==slave_bios_version.strip() : + print ("\tBIOS 备版本信息一致: PASS\n") + else: + print ("\tBIOS %s %s备版本信息一致: FAILED\n"%(slave_bios_version,config_bios_slave)) + + # CPLD + print ("\nCPLD Information\n") + ret,log,tmp= cpld_version_inner() + if ret != 0: + print ("get version failed: cpld") + print (log) + # Check version consistency + temp_cpld_version=get_version_config_info("CPLD_VERSION") + if temp_cpld_version == None: + cpld_flag=True + else: + cpld_flag=False + if not cpld_flag: + # print repr(temp_cpld_version) + dict_cpld_version=eval(temp_cpld_version) + dict_cpld_keys=dict_cpld_version.keys() + # print repr(tmp) + for item in tmp: + for config_cpld_key in dict_cpld_keys: + if item[0] == config_cpld_key: + item_temp=item[1]+item[2] + if item_temp == dict_cpld_version[config_cpld_key]: + print ("\n\tCPLD %s版本信息一致: PASS"%(config_cpld_key)) + else: + print ("\n\tCPLD %s 版本信息一致%s: FAILED"%(config_cpld_key,dict_cpld_version[config_cpld_key])) + + # FPGA + fpga_check="" + config_fpga=get_version_config_info("FPGA_VERSION") + if config_fpga == None: + fpga_flag=True + else: + fpga_flag=False + print ("\nFPGA Information\n") + cmd = "grtd_test.py pci rd 8 0 0 0 0" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: fpga") + print (log) + else: + print ("\tversion : %s"%log) + + fpga_check=fpga_check+log[2:] + + cmd = "grtd_test.py pci rd 8 0 0 0 4" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: fpga") + print (log) + else: + print ("\tdate : %s"%log) + # Check version consistency + if not fpga_flag: + fpga_check=fpga_check+"-"+log[2:] + + cmd = "grtd_test.py pci rd 8 0 0 0 12" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: fpga") + print (log) + else: + print ("\tgolden version : %s"%log) + # Check version consistency + if not fpga_flag: + fpga_check=fpga_check+"-"+log[2:] + if fpga_check==config_fpga: + print ("\n\tFPGA 版本信息一致: PASS") + else: + print ("\n\rFPGA %s %s版本信息一致: FAILED"%(config_fpga,fpga_check)) + + # TH3/TD3 PCIe + temp_pcie_version=get_version_config_info("PCIE_VERSION") + if temp_pcie_version == None: + pcie_flag=True + else: + pcie_flag=False + # print repr(temp_pcie_version) + print ("\npciephy fw Information\n") + cmd = "bcmcmd \"pciephy fw version\"" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: pciephy fw") + print (log) + else: + version_temp = re.subn("( \r\n)|( \r\n\r\r\ndrivshell>)|(version\r\r)","",log)[0] + version_clean = re.subn("(pciephy fw \n)|(\r\r\ndrivshell>)","",version_temp)[0] + print (version_clean) + # Check version consistency + if not pcie_flag: + # print repr(version_clean) + version1=version_clean.split('\n') + # print repr(version1) + ver_load_tmp=version1[1] + ver_load=ver_load_tmp[1:len(ver_load_tmp)-1].split(':')[1] + ver_vers_tmp=version1[2] + ver_vers=ver_vers_tmp[1:len(ver_vers_tmp)-1].split(':')[1] + # print repr(ver_load) + # print repr(ver_vers) + + config_pcie=eval(temp_pcie_version) + config_pcie_load=config_pcie["PCIE_FW_LOADER"] + config_pcie_fw=config_pcie["PCIE_FW"] + if ver_load.strip() == config_pcie_load and ver_vers.strip() == config_pcie_fw: + print ("\tPCIe 版本信息一致: PASS") + else: + print ("\tPCIe %s %s版本信息一致%s %s: FAILED"%(config_pcie_fw,config_pcie_load,ver_vers,ver_load)) + + + # I210 + config_firm=get_version_config_info("I210_FIRMWARE") + if config_firm == None: + i210_flag=True + else: + i210_flag=False + print ("\ni210 fw Information\n") + cmd = "ethtool -i eth0" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: 210 fw") + print (log) + else: + version_temp = log.split('\n') + # print repr(version_temp) + for i in version_temp: + print ('\t%s' % i) + # Check version consistency + if not i210_flag: + firm_version=version_temp[2] + firm_ver=firm_version.split(':')[1].strip() + firm_check=firm_ver.replace(', ','-') + + if firm_check in config_firm: + print ("\n\ti210 fw 版本信息一致: PASS\n") + else: + print ("\n\ti210 fw %s 版本信息一致 %s: FAILED\n"%(firm_check,config_firm)) + + if (RAGILE_PRODUCTNAME == "AS23-128H" or RAGILE_PRODUCTNAME == "AS14-128H") : + # firmware Information + firm_81724_ver_temp=get_version_config_info("81724_FIRMWARE") + if firm_81724_ver_temp == None: + firm_81724_ver="" + f81724_flag=True + else: + firm_81724_ver=firm_81724_ver_temp + f81724_flag=False + print ("\n81724 fw Information\n") + cmd = "bcmcmd \"phy control ce getee\"|grep fw_version" + ret , log = log_os_system(cmd) + if ret != 0: + print ("get version failed: 81724 fw") + print (log) + else: + # filted_list = re.findall(r".*fw_version=(\S*).*",log.lower()) + print (log) + filted_list = re.findall(r"\bfailed",log.lower()) + if len(filted_list) > 0 : + print ("\nthere are %d FAILED."%(len(filted_list))) + # print("\tversion: %s\n"%filted_list[0]) + if not f81724_flag: + version_list = re.findall(r".*port=(\S*).*fw_version=(\S*).*",log.lower()) + number_ver=0 + if len(version_list) > 0: + for port,ver in version_list: + number_ver+=1 + if ver.strip() != firm_81724_ver.strip(): + break + + if number_ver == len(version_list): + print ("81724 fw information 版本信息一致: PASS\n") + else: + print ("81724 fw information 版本信息一致: FAILED\n") + +# Production test master program +if __name__ == '__main__': + main() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_fanctrl.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_fanctrl.py new file mode 100644 index 000000000000..ad5700e0f897 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_fanctrl.py @@ -0,0 +1,414 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import inspect +import os +import sys +import json +import time +import syslog +import traceback +from plat_hal.interface import * +from plat_hal.baseutil import baseutil +from algorithm.pid import pid +from algorithm.openloop import openloop + +SWITCH_TEMP = "SWITCH_TEMP" +INLET_TEMP = "INLET_TEMP" +BOARD_TEMP = "BOARD_TEMP" +OUTLET_TEMP = "OUTLET_TEMP" +CPU_TEMP = "CPU_TEMP" + +FANCTROL_DEBUG_FILE = "/etc/.fancontrol_debug_flag" + +FANCTROLERROR = 1 +FANCTROLDEBUG = 2 + +debuglevel = 0 + +def fancontrol_debug(s): + if FANCTROLDEBUG & debuglevel: + syslog.openlog("FANCONTROL", syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG, s) + +def fancontrol_error(s): + if FANCTROLERROR & debuglevel: + syslog.openlog("FANCONTROL", syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR, s) + +class fancontrol(object): + __int_case = None + + __pwm = 0x80 + __critnum = 0 + + def __init__(self): + self.int_case = interface() + self.__config = baseutil.get_monitor_config() + self.__pid_config = self.__config["pid"] + self.__temps_threshold_config = self.__config["temps_threshold"] + for temp_threshold in self.__temps_threshold_config.values(): + temp_threshold['temp'] = 0 + temp_threshold['fail_num'] = 0 + + self.__fancontrol_para = self.__config["fancontrol_para"] + self.__interval = self.__fancontrol_para.get("interval") + self.__max_pwm = self.__fancontrol_para.get("max_pwm") + self.__min_pwm = self.__fancontrol_para.get("min_pwm") + self.__abnormal_pwm = self.__fancontrol_para.get("abnormal_pwm") + self.__temp_fail_num = self.__fancontrol_para.get("temp_fail_num") + self.__check_temp_fail = self.__fancontrol_para.get("check_temp_fail") + self.__inlet_mac_diff = self.__fancontrol_para.get("inlet_mac_diff") + self.__check_crit_reboot_num = self.__fancontrol_para.get("check_crit_reboot_num") + self.__check_crit_sleep_time = self.__fancontrol_para.get("check_crit_sleep_time") + self.__psu_absent_fullspeed_num = self.__fancontrol_para.get("psu_absent_fullspeed_num") + self.__fan_absent_fullspeed_num = self.__fancontrol_para.get("fan_absent_fullspeed_num") + self.__rotor_error_fullspeed_num = self.__fancontrol_para.get("rotor_error_fullspeed_num") + self.openloop = openloop() + self.pid = pid() + + self.__pwm = self.__min_pwm + + def debug_init(self): + global debuglevel + if os.path.exists(FANCTROL_DEBUG_FILE): + debuglevel = debuglevel | FANCTROLDEBUG | FANCTROLERROR + else: + debuglevel = debuglevel & ~(FANCTROLDEBUG | FANCTROLERROR) + + def get_para(self, type): + para = self.__pid_config.get(type) + return para + + def get_monitor_temp(self): + sensorlist = self.int_case.get_temp_info() + + for temp_threshold in self.__temps_threshold_config.values(): + sensor = sensorlist.get(temp_threshold['name']) + if sensor["Value"] == None: + temp_threshold['fail_num'] += 1 + fancontrol_error("get %s failed, fail_num = %d" % (temp_threshold['name'], temp_threshold['fail_num'])) + else: + temp_threshold['fail_num'] = 0 + temp_threshold.setdefault('fix', 0) + temp_threshold['temp'] = sensor["Value"] + temp_threshold['fix'] + fancontrol_debug("%s = %d" % (temp_threshold['name'], temp_threshold['temp'])) + fancontrol_debug("warning = %d, critical = %d" % (temp_threshold['warning'], temp_threshold['critical'])) + + def is_temp_warning(self): + warning_flag = False + for temp_threshold in self.__temps_threshold_config.values(): + if temp_threshold['temp'] >= temp_threshold['warning']: + warning_flag = True + fancontrol_debug("%s is over warning" % temp_threshold['name']) + fancontrol_debug("%s = %d, warning = %d" % (temp_threshold['name'], temp_threshold['temp'], temp_threshold['warning'])) + return warning_flag + + def checkTempWarning(self): + try: + if self.is_temp_warning(): + fancontrol_debug("temp is over warning") + return True + except Exception as e: + fancontrol_error("%%policy: checkTempWarning failed") + fancontrol_error(str(e)) + return False + + def is_temp_critical(self): + critical_flag = False + for temp_threshold in self.__temps_threshold_config.values(): + temp_threshold['critical_flag'] = False + if temp_threshold['temp'] >= temp_threshold['critical']: + critical_flag = True + temp_threshold['critical_flag'] = True + fancontrol_debug("%s is over critical" % temp_threshold['name']) + fancontrol_debug("%s = %d, critical = %d" % (temp_threshold['name'], temp_threshold['temp'], temp_threshold['critical'])) + return critical_flag + + def checkTempCrit(self): + try: + if self.is_temp_critical(): + temp_dict = dict(self.__temps_threshold_config) + tmp = temp_dict.get(SWITCH_TEMP) + if tmp['critical_flag'] == True: + fancontrol_debug("temp is over critical") + return True + + del temp_dict[SWITCH_TEMP] + for temp_items in temp_dict.values(): + if temp_items['critical_flag'] == False: + return False + + fancontrol_debug("temp is over critical") + return True + except Exception as e: + fancontrol_error("%%policy: checkTempCrit failed") + fancontrol_error(str(e)) + return False + + def checkCritReboot(self): + try: + if self.checkTempCrit() == True: + time.sleep(self.__check_crit_sleep_time) + self.get_monitor_temp()# Read it again + if self.checkTempCrit() == True: + fancontrol_debug("The temperature of device is over critical value.") + self.__critnum += 1 # Image stabilization + if self.__critnum >= self.__check_crit_reboot_num: + print("The temperature of device is over critical value.") + print("The system is going to reboot now.") + time.sleep(3) + os.system("reboot") + fancontrol_debug("critnum:%d" % self.__critnum) + else: + self.__critnum = 0 + else: + self.__critnum = 0 + except Exception as e: + fancontrol_error("%%policy: checkCritReboot failed") + fancontrol_error(str(e)) + + def get_fan_total_number(self): + return self.int_case.get_fan_total_number() + + def get_rotor_number(self, fan_name): + return self.int_case.get_fan_rotor_number(fan_name) + + def get_fan_presence(self, fan_name): + return self.int_case.get_fan_presence(fan_name) + + def get_fan_rotor_status(self, fan_name, rotor_name): + return self.int_case.get_fan_rotor_status(fan_name, rotor_name) + + def get_psu_total_number(self): + return self.int_case.get_psu_total_number() + + def get_psu_presence(self, psu_name): + return self.int_case.get_psu_presence(psu_name) + + def get_psu_input_output_status(self, psu_name): + return self.int_case.get_psu_input_output_status(psu_name) + + def checkFanPresence(self): + absent_num = 0 + fan_num = self.get_fan_total_number() + for i in range(fan_num): + fan_name = "FAN" + str(i + 1) + status = self.get_fan_presence(fan_name) + if status == False: + absent_num = absent_num + 1 + fancontrol_debug("%s absent" % fan_name) + else: + fancontrol_debug("%s presence" % fan_name) + return absent_num + + def checkFanRotorStatus(self): + err_num = 0 + fan_num = self.get_fan_total_number() + for i in range(fan_num): + fan_name = "FAN" + str(i + 1) + rotor_num = self.get_rotor_number(fan_name) + for j in range(rotor_num): + rotor_name = "Rotor" + str(j + 1) + status = self.get_fan_rotor_status(fan_name, rotor_name) + if status == False: + err_num = err_num + 1 + fancontrol_debug("%s %s error" % (fan_name, rotor_name)) + else: + fancontrol_debug("%s %s ok" % (fan_name, rotor_name)) + return err_num + + def checkPsuPresence(self): + absent_num = 0 + psu_num = self.get_psu_total_number() + for i in range(psu_num): + psu_name = "PSU" + str(i + 1) + status = self.get_psu_presence(psu_name) + if status == False: + absent_num = absent_num + 1 + fancontrol_debug("%s absent" % psu_name) + else: + fancontrol_debug("%s presence" % psu_name) + return absent_num + + def checkPsuStatus(self): + err_num = 0 + psu_num = self.get_psu_total_number() + for i in range(psu_num): + psu_name = "PSU" + str(i + 1) + status = self.get_psu_input_output_status(psu_name) + if status == False: + err_num = err_num + 1 + fancontrol_debug("%s error" % psu_name) + else: + fancontrol_debug("%s ok" % psu_name) + return err_num + + def checkDevError(self): + pwm = self.__min_pwm + switchtemp = self.__temps_threshold_config.get(SWITCH_TEMP)['temp'] + inlettemp = self.__temps_threshold_config.get(INLET_TEMP)['temp'] + temp_diff = abs(switchtemp - inlettemp) + fancontrol_debug("|switchtemp - inlettemp| = %d" % temp_diff) + if temp_diff >= self.__inlet_mac_diff: + fancontrol_debug("temp_diff is over than inlet_mac_diff(%d)" % self.__inlet_mac_diff) + if self.__pwm > self.__abnormal_pwm: + pwm = self.__max_pwm + else: + pwm = self.__abnormal_pwm + return pwm + + def checktempfail(self): + pwm = self.__min_pwm + for temp in self.__check_temp_fail: + temp_name = temp.get("temp_name") + temp_fail_num = self.__temps_threshold_config.get(temp_name)['fail_num'] + if temp_fail_num >= self.__temp_fail_num: + pwm = self.__abnormal_pwm + fancontrol_debug("%s temp_fail_num = %d" % (temp_name, temp_fail_num)) + fancontrol_debug("self.__temp_fail_num = %d" % self.__temp_fail_num) + return pwm + + def abnormal_check(self): + pwm_list = [] + pwm_min = self.__min_pwm + pwm_list.append(pwm_min) + status = self.checkTempCrit() + if status == True: + over_crit_pwm = self.__max_pwm + pwm_list.append(over_crit_pwm) + fancontrol_debug("over_crit_pwm = 0x%x" % over_crit_pwm) + # do reset check + self.checkCritReboot() + + status = self.checkTempWarning() + if status == True: + over_warn_pwm = self.__max_pwm + pwm_list.append(over_warn_pwm) + fancontrol_debug("over_warn_pwm = 0x%x" % over_warn_pwm) + + fan_absent_num = self.checkFanPresence() + if fan_absent_num >= self.__fan_absent_fullspeed_num: + fan_absent_pwm = self.__max_pwm + pwm_list.append(fan_absent_pwm) + fancontrol_debug("fan_absent_pwm = 0x%x" % fan_absent_pwm) + + rotor_err_num = self.checkFanRotorStatus() + if rotor_err_num >= self.__rotor_error_fullspeed_num: + rotor_err_pwm = self.__max_pwm + pwm_list.append(rotor_err_pwm) + fancontrol_debug("rotor_err_pwm = 0x%x" % rotor_err_pwm) + + psu_absent_num = self.checkPsuPresence() + if psu_absent_num >= self.__psu_absent_fullspeed_num: + psu_absent_pwm = self.__max_pwm + pwm_list.append(psu_absent_pwm) + fancontrol_debug("psu_absent_pwm = 0x%x" % psu_absent_pwm) + + dev_err_pwm = self.checkDevError() + pwm_list.append(dev_err_pwm) + fancontrol_debug("dev_err_pwm = 0x%x" % dev_err_pwm) + + temp_fail_pwm = self.checktempfail() + pwm_list.append(temp_fail_pwm) + fancontrol_debug("temp_fail_pwm = 0x%x" % temp_fail_pwm) + + pwm = max(pwm_list) + return pwm + + + def do_fancontrol(self): + pwm_list = [] + pwm_min = self.__min_pwm + pwm_list.append(pwm_min) + + self.get_monitor_temp() + fancontrol_debug("last_pwm = 0x%x" % self.__pwm) + # openloop + inlettemp = self.__temps_threshold_config.get(INLET_TEMP)['temp'] + linear_value = self.openloop.linear_cacl(inlettemp) + if linear_value == None: + linear_value = self.__min_pwm + pwm_list.append(linear_value) + fancontrol_debug("linear_value = 0x%x" % linear_value) + + curve_value = self.openloop.curve_cacl(inlettemp) + if curve_value == None: + curve_value = self.__min_pwm + pwm_list.append(curve_value) + fancontrol_debug("curve_value = 0x%x" % curve_value) + + # pid + for pid_index in self.__pid_config.values(): + temp_name = pid_index['name'] + tmp_temp = self.__temps_threshold_config.get(temp_name)['temp'] + pid_value = self.pid.cacl(self.__pwm, temp_name, tmp_temp) + if pid_value == None: + pid_value = self.__min_pwm + pwm_list.append(pid_value) + fancontrol_debug("%s pid_value = 0x%x" % (temp_name, pid_value)) + + # abnormal + abnormal_value = self.abnormal_check() + pwm_list.append(abnormal_value) + fancontrol_debug("abnormal_value = 0x%x" % abnormal_value) + + self.__pwm = max(pwm_list) + fancontrol_debug("__pwm = 0x%x\n" % self.__pwm) + self.set_all_fan_speed_pwm(self.__pwm) + + def run(self): + while True: + try: + self.debug_init() + self.do_fancontrol() + time.sleep(self.__interval) + except Exception as e: + traceback.print_exc() + fancontrol_error(str(e)) + + def set_all_fan_speed_pwm(self, pwm): + self.fan_set_speed_pwm(pwm); + self.set_psu_fan_speed_pwm(pwm); + + def get_fans(self): + return self.int_case.get_fans() + + def get_speed(self, fan_name, rotor_index): + return self.int_case.get_fan_speed(fan_name, rotor_index) + + def get_speed_pwm(self, fan_name, rotor_index): + return self.int_case.get_fan_speed_pwm(fan_name, rotor_index) + + def fan_get_speed_pwm(self): + fans = self.get_fans() + for fan in fans: + rotor_len = self.get_rotor_number(fan.name) + for i in range(rotor_len): + fancontrol_debug("%s rotor%d: %d" % (fan.name, i + 1, self.get_speed_pwm(fan.name, i + 1))) + + def fan_set_speed_pwm(self, pwm): + duty = round(pwm * 100 / 255) + fans = self.get_fans() + for fan in fans: + rotor_len = self.get_rotor_number(fan.name) + for i in range(rotor_len): + val = self.int_case.set_fan_speed_pwm(fan.name, i + 1, duty) + if val != 0: + fancontrol_error("%s rotor%d: %d" % (fan.name, i + 1, val)) + + def set_psu_fan_speed_pwm(self, pwm): + duty = round(pwm * 100 / 255) + psu_num = self.get_psu_total_number() + for i in range(psu_num): + psu_name = "PSU" + str(i + 1) + status = self.int_case.set_psu_fan_speed_pwm(psu_name, int(duty)) + if status != True: + fancontrol_error("set %s speed fail" % psu_name) + + +if __name__ == '__main__': + fancontrol_debug("enter main") + fan_control = fancontrol() + fan_control.run() + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_ledctrl.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_ledctrl.py new file mode 100644 index 000000000000..4deeee4cec5c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_ledctrl.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import inspect +import os +import sys +import json +import time +import syslog +import traceback +from plat_hal.interface import * +from plat_hal.baseutil import baseutil + +SWITCH_TEMP = "SWITCH_TEMP" +INLET_TEMP = "INLET_TEMP" +BOARD_TEMP = "BOARD_TEMP" +OUTLET_TEMP = "OUTLET_TEMP" +CPU_TEMP = "CPU_TEMP" + +FRONT_SYS_LED = "FRONT_SYS_LED" +BACK_SYS_LED = "BACK_SYS_LED" +FRONT_BMC_LED = "FRONT_BMC_LED" +BACK_BMC_LED = "BACK_BMC_LED" +FRONT_PSU_LED = "FRONT_PSU_LED" +FRONT_FAN_LED = "FRONT_FAN_LED" + +LEDCTROL_DEBUG_FILE = "/etc/.ledcontrol_debug_flag" + +LEDCTROLERROR = 1 +LEDCTROLDEBUG = 2 + +debuglevel = 0 + +def ledcontrol_debug(s): + if LEDCTROLDEBUG & debuglevel: + syslog.openlog("LEDCONTROL", syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG, s) + +def ledcontrol_error(s): + if LEDCTROLERROR & debuglevel: + syslog.openlog("LEDCONTROL", syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR, s) + +class ledcontrol(object): + __int_case = None + + __interval = 30 + + __temps_threshold_config = None + + def __init__(self): + self.__fanerrnum = 0 + self.__psuerrnum = 0 + self.int_case = interface() + + self.__config = baseutil.get_monitor_config() + self.__temps_threshold_config = self.__config["temps_threshold"] + for temp_threshold in self.__temps_threshold_config.values(): + temp_threshold['temp'] = 0 + temp_threshold['fail_num'] = 0 + self.__ledcontrol_para = self.__config["ledcontrol_para"] + self.__interval = self.__ledcontrol_para.get("interval") + self.__checkpsu = self.__ledcontrol_para.get("checkpsu", 0) + self.__checkfan = self.__ledcontrol_para.get("checkfan", 0) + self.__psu_yellow_num = self.__ledcontrol_para.get("psu_yellow_num") + self.__fan_yellow_num = self.__ledcontrol_para.get("fan_yellow_num") + self.__board_sys_led = self.__ledcontrol_para.get("board_sys_led") + self.__board_psu_led = self.__ledcontrol_para.get("board_psu_led") + self.__board_fan_led = self.__ledcontrol_para.get("board_fan_led") + + @property + def fanerrnum(self): + return self.__fanerrnum + + @fanerrnum.setter + def fanerrnum(self, value): + self.__fanerrnum = value + + @property + def psuerrnum(self): + return self.__psuerrnum + + @psuerrnum.setter + def psuerrnum(self, value): + self.__psuerrnum = value + + def debug_init(self): + global debuglevel + if os.path.exists(LEDCTROL_DEBUG_FILE): + debuglevel = debuglevel | LEDCTROLDEBUG | LEDCTROLERROR + else: + debuglevel = debuglevel & ~(LEDCTROLDEBUG | LEDCTROLERROR) + + def get_monitor_temp(self): + sensorlist = self.int_case.get_temp_info() + + for temp_threshold in self.__temps_threshold_config.values(): + sensor = sensorlist.get(temp_threshold['name']) + if sensor["Value"] == None: + temp_threshold['fail_num'] += 1 + ledcontrol_error("get %s failed, fail_num = %d" % (temp_threshold['name'], temp_threshold['fail_num'])) + else: + temp_threshold['fail_num'] = 0 + temp_threshold.setdefault('fix', 0) + temp_threshold['temp'] = sensor["Value"] + temp_threshold['fix'] + ledcontrol_debug("%s = %d" % (temp_threshold['name'], temp_threshold['temp'])) + ledcontrol_debug("warning = %d, critical = %d" % (temp_threshold['warning'], temp_threshold['critical'])) + + def is_temp_warning(self): + warning_flag = False + for temp_threshold in self.__temps_threshold_config.values(): + if temp_threshold['temp'] >= temp_threshold['warning']: + warning_flag = True + ledcontrol_debug("%s is over warning" % temp_threshold['name']) + ledcontrol_debug("%s = %d, warning = %d" % (temp_threshold['name'], temp_threshold['temp'], temp_threshold['warning'])) + return warning_flag + + def checkTempWarning(self): + try: + if self.is_temp_warning(): + ledcontrol_debug("temp is over warning") + return True + except Exception as e: + ledcontrol_error("%%policy: checkTempWarning failed") + ledcontrol_error(str(e)) + return False + + def is_temp_critical(self): + critical_flag = False + for temp_threshold in self.__temps_threshold_config.values(): + temp_threshold['critical_flag'] = False + if temp_threshold['temp'] >= temp_threshold['critical']: + critical_flag = True + temp_threshold['critical_flag'] = True + ledcontrol_debug("%s is over critical" % temp_threshold['name']) + ledcontrol_debug("%s = %d, critical = %d" % (temp_threshold['name'], temp_threshold['temp'], temp_threshold['critical'])) + return critical_flag + + def checkTempCrit(self): + try: + if self.is_temp_critical(): + temp_dict = dict(self.__temps_threshold_config) + tmp = temp_dict.get(SWITCH_TEMP) + if tmp['critical_flag'] == True: + ledcontrol_debug("temp is over critical") + return True + + del temp_dict[SWITCH_TEMP] + for temp_items in temp_dict.values(): + if temp_items['critical_flag'] == False: + return False + + ledcontrol_debug("temp is over critical") + return True + except Exception as e: + ledcontrol_error("%%policy: checkTempCrit failed") + ledcontrol_error(str(e)) + return False + + def set_led_color(self, led_name, color, blink=False): + return self.int_case.set_led_color(led_name, color, blink) + + def set_fan_led(self, fan_name, color, blink=False): + return self.int_case.set_fan_led(fan_name, color, blink) + + def get_fan_total_number(self): + return self.int_case.get_fan_total_number() + + def get_rotor_number(self, fan_name): + return self.int_case.get_fan_rotor_number(fan_name) + + def get_fan_presence(self, fan_name): + return self.int_case.get_fan_presence(fan_name) + + def get_fan_rotor_status(self, fan_name, rotor_name): + return self.int_case.get_fan_rotor_status(fan_name, rotor_name) + + def get_psu_total_number(self): + return self.int_case.get_psu_total_number() + + def get_psu_presence(self, psu_name): + return self.int_case.get_psu_presence(psu_name) + + def get_psu_input_output_status(self, psu_name): + return self.int_case.get_psu_input_output_status(psu_name) + + def get_monitor_fan(self): + try: + fanerrnum = 0 + fan_num = self.get_fan_total_number() + for i in range(fan_num): + fan_name = "FAN" + str(i + 1) + present_status = self.get_fan_presence(fan_name) + if present_status == False: + fanerrnum += 1 + ledcontrol_debug("%s absent" % fan_name) + continue + ledcontrol_debug("%s presence" % fan_name) + rotor_num = self.get_rotor_number(fan_name) + color = "green" + err_motor_num = 0 + for j in range(rotor_num): + rotor_name = "Rotor" + str(j + 1) + roll_status = self.get_fan_rotor_status(fan_name, rotor_name) + if roll_status == False: + err_motor_num += 1 + color = "red" + ledcontrol_debug("%s %s error" % (fan_name, rotor_name)) + else: + ledcontrol_debug("%s %s ok" % (fan_name, rotor_name)) + self.set_fan_led(fan_name, color) + ledcontrol_debug("set %s led success, color:%s," % (fan_name, color)) + if err_motor_num > 0: + fanerrnum += 1 + self.fanerrnum = fanerrnum + ledcontrol_debug("fan error number:%d" % self.fanerrnum) + except Exception as e: + ledcontrol_error("%%policy: get_monitor_fan failed") + ledcontrol_error(str(e)) + + def get_monitor_psu(self): + try: + psuerrnum = 0 + psu_num = self.get_psu_total_number() + for i in range(psu_num): + psu_name = "PSU" + str(i + 1) + present = self.get_psu_presence(psu_name) + status = self.get_psu_input_output_status(psu_name) + ledcontrol_debug("%s present:%s, status:%s" % (psu_name, present, status)) + if present == False or status == False: + psuerrnum += 1 + self.psuerrnum = psuerrnum + ledcontrol_debug("psu error number:%d" % self.psuerrnum) + except Exception as e: + ledcontrol_error("%%policy: get_monitor_psu failed") + ledcontrol_error(str(e)) + + def dealSysLedStatus(self): + try: + if ((self.checkTempCrit() == True) or + (self.__checkfan and (self.fanerrnum > self.__fan_yellow_num)) or + (self.__checkpsu and (self.psuerrnum > self.__psu_yellow_num))): + color = "red" + elif ((self.checkTempWarning() == True) or + (self.__checkfan and (self.fanerrnum > 0)) or + (self.__checkpsu and (self.psuerrnum > 0))): + color = "yellow" + else: + color = "green" + for led in self.__board_sys_led: + led_name = led.get("led_name") + self.set_led_color(led_name, color) + ledcontrol_debug("deal %s success, color:%s," % (led_name, color)) + except Exception as e: + ledcontrol_error(str(e)) + + def dealFanLedStatus(self): + try: + if self.fanerrnum == 0: + color = "green" + elif self.fanerrnum <= self.__fan_yellow_num: + color = "yellow" + else: + color = "red" + for led in self.__board_fan_led: + led_name = led.get("led_name") + self.set_led_color(led_name, color) + ledcontrol_debug("deal %s success, color:%s," % (led_name, color)) + except Exception as e: + ledcontrol_error(str(e)) + + def dealPsuLedStatus(self): + try: + if self.psuerrnum == 0: + color = "green" + elif self.psuerrnum <= self.__psu_yellow_num: + color = "yellow" + else: + color = "red" + for led in self.__board_psu_led: + led_name = led.get("led_name") + self.set_led_color(led_name, color) + ledcontrol_debug("deal %s success, color:%s," % (led_name, color)) + except Exception as e: + ledcontrol_error(str(e)) + + def do_ledcontrol(self): + self.get_monitor_temp() + self.get_monitor_psu() + self.get_monitor_fan() + self.dealSysLedStatus() + self.dealFanLedStatus() + self.dealPsuLedStatus() + + def run(self): + while True: + try: + self.debug_init() + self.do_ledcontrol() + time.sleep(self.__interval) + except Exception as e: + traceback.print_exc() + ledcontrol_error(str(e)) + + +if __name__ == '__main__': + ledcontrol_debug("enter main") + led_control = ledcontrol() + led_control.run() + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_pltfm.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_pltfm.py new file mode 100644 index 000000000000..7844f9ee7ffa --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/hal_pltfm.py @@ -0,0 +1,380 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +from __future__ import print_function +import inspect +import os +import sys +import json +import time +from plat_hal.interface import interface + +class Basecommand(): + def __init__(self, doc = '', name = None): + self.name = name + self.doc = doc + +class Command(Basecommand): + def __init__(self, name, f): + self.name =name + self.f = f + self.paramcount =self.f.__code__.co_argcount + + def dofun(self, args): + fn = self.f.__call__ + fn(*args) + +class Group(Basecommand): + def __init__(self, name, f): + self.groups= [] + self.commands = [] + self.name =name + self.f = f + pass + + def add_groups(self, command): + self.groups.append(command) + pass + + def add_commands(self, commnad): + x = Command(commnad.__name__, commnad) + self.subprocess.append(x) + + def find_valuebyname(self, name): + for item in self.groups: + if name == item.name: + return item + for item in self.commands: + if name == item.name: + return item + return None + + def deal(self, args): + if len(args) <= 0: + return self.print_help() + funclevel = args[0] + val = self.find_valuebyname(funclevel) + if val is None: + return self.print_help() + if isinstance(val, Command): + if len(args) < (val.paramcount + 1): + return self.print_help() + else: + inputargs = args[1: (1 + val.paramcount)] + return val.dofun(inputargs) + if isinstance(val , Group): + args = args[1:] + return val.deal(args) + else: + self.print_help() + + def get_max(self, arr): + lentmp = 0 + for ar in arr: + lentmp = len(ar) if (len(ar) > lentmp) else lentmp + return lentmp + + def print_help(self,*attrs): + + namesize = [] + for item in self.groups: + namesize.append(item.name) + for item in self.commands: + namesize.append(item.name) + maxvalue = self.get_max(namesize) + + if len(self.groups) > 0: + print("Groups:") + for item in self.groups: + print(" %-*s %s" % (maxvalue, item.name, item.f.__doc__ or '')) + if len(self.commands) > 0: + print("Commands:") + for item in self.commands: + print(" %-*s %s" % (maxvalue,item.name, item.f.__doc__ or '')) + +class clival(): + @staticmethod + def Fire(val = None): + group = Group("top",'mainlevel') + clival.iterGroup(val, group) + # context = {} + # caller = inspect.stack()[1] + # caller_frame = caller[0] + # caller_globals = caller_frame.f_globals + # caller_locals = caller_frame.f_locals + # context.update(caller_globals) + # context.update(caller_locals) + args = sys.argv[1:] + group.deal(args) + + @staticmethod + def iterGroup(val, group): + for key, item in val.items(): + if item is None: # first level + if (inspect.isfunction(key)): + group.add_commands(key) + else: + group1 = Group(key.__name__, key) + clival.iterGroup(item, group1) + group.add_groups(group1) + +def psu(): + '''test psu ''' + pass + +def fan(): + '''test fan ''' + pass + +def sensor(): + '''test sensor ''' + pass + +int_case = interface() + +def get_total_number(): + '''psu get_total_number ''' + print("=================get_total_number======================") + print(int_case.get_psu_total_number()) + +def get_presence(): + '''psu get_presence ''' + print("=================get_presence======================") + psus = int_case.get_psus() + for psu in psus: + print(psu.name, end=' ') + print(int_case.get_psu_presence(psu.name)) + +def get_fru_info(): + '''psu get_fru_info ''' + print("=================get_fru_info======================") + psus = int_case.get_psus() + for psu in psus: + print(psu.name, end=' ') + print(json.dumps(int_case.get_psu_fru_info(psu.name), ensure_ascii = False,indent=4)) + +def get_status(): + '''psu get_status ''' + print("=================get_status======================") + psus = int_case.get_psus() + for psu in psus: + print(psu.name, end=' ') + print(json.dumps(int_case.get_psu_status(psu.name), ensure_ascii = False,indent=4)) + +def set_psu_fan_speed_pwm(realspeed): + '''set_psu_fan_speed_pwm''' + print("=================set_psu_fan_speed_pwm======================") + psus = int_case.get_psus() + for psu in psus: + print(psu.name, end=' ') + print(int_case.set_psu_fan_speed_pwm(psu.name, int(realspeed))) + pass + +def get_psu_fan_speed_pwm(): + '''get_psu_fan_speed_pwm''' + print("=================get_psu_fan_speed_pwm======================") + psus = int_case.get_psus() + for psu in psus: + print(psu.name, end=' ') + print(json.dumps(int_case.get_psu_fan_speed_pwm(psu.name))) + pass + +def get_psu_power_status(): + '''psu get_psu_power_status ''' + print("=================get_psu_power_status======================") + psus = int_case.get_psus() + for psu in psus: + print(psu.name, end=' ') + print(json.dumps(int_case.get_psu_power_status(psu.name), ensure_ascii = False,indent=4)) + +def get_info_all(): + '''psu get_info_all ''' + print("=================get_info_all======================") + print(json.dumps(int_case.get_psu_info_all(), ensure_ascii = False,indent=4)) + +def fan_get_total_number(): + print("=================get_info_all======================") + print(json.dumps(int_case.get_fan_total_number(), ensure_ascii = False, indent=4)) + + +def fan_get_rotor_number(): + '''fan_get_rotor_numbe''' + print("=================fan_get_rotor_number======================") + fans = int_case.get_fans() + for fan in fans: + print(fan.name, end=' ') + print(int_case.get_fan_rotor_number(fan.name)) + + pass + +def fan_get_speed(): + '''fan_get_speed''' + print("=================fan_get_speed======================") + fans = int_case.get_fans() + for fan in fans: + rotors = fan.rotor_list + for rotor in rotors: + index = rotors.index(rotor) + print("%s rotor%d"%(fan.name, index + 1) , end =' ' ) + print(int_case.get_fan_speed(fan.name, index + 1)) + pass + +def fan_set_speed(realspeed): + '''fan_set_speed''' + speed = int(realspeed) + xspeed = round(speed /255 * 100) + print("=================fan_set_speed======================") + fans = int_case.get_fans() + for fan in fans: + rotors = fan.rotor_list + for rotor in rotors: + index = rotors.index(rotor) + print("%s %s" % (fan.name, rotor.name) , end =' ' ) + print(int_case.get_fan_speed(fan.name, index + 1), end =' ') + print(int_case.set_fan_speed(fan.name, index + 1, xspeed)) + time.sleep(5) + print("%s %s" % (fan.name, rotor.name) , end =' ' ) + print(int_case.get_fan_speed(fan.name, index + 1)) + +def fan_get_speed_pwm(): + '''fan_get_speed_pwm''' + print("=================fan_get_speed_pwm======================") + fans = int_case.get_fans() + for fan in fans: + rotors = fan.rotor_list + for rotor in rotors: + index = rotors.index(rotor) + print("%s rotor%d" % (fan.name, index + 1), end=' ' ) + print (int_case.get_fan_speed_pwm(fan.name, index + 1)) + +def fan_set_speed_pwm(pwm): + '''fan_set_speed_pwm''' + print("=================fan_set_speed_pwm======================") + fans = int_case.get_fans() + for fan in fans: + rotors = fan.rotor_list + for rotor in rotors: + index = rotors.index(rotor) + print("%s %s"% (fan.name, rotor.name), end =' ') + val = int_case.set_fan_speed_pwm(fan.name, index + 1, pwm) + print (val) + +def fan_get_watchdog_status(): + '''fan_get_watchdog_status''' + print("=================fan_get_watchdog_status======================") + print(int_case.get_fan_watchdog_status()) + pass + +def fan_enable_watchdog(): + '''fan_enable_watchdog''' + print("=================fan_enable_watchdog======================") + print('enable',int_case.enable_fan_watchdog()) + +def fan_disable_watchdog(): + '''fan_disable_watchdog''' + print("=================fan_disable_watchdog======================") + print('disable', int_case.enable_fan_watchdog(enable = False)) + +def fan_get_speed1(): + '''fan_get_speed''' + print("=================fan_get_speed======================") + fans = int_case.get_fans() + for fan in fans: + total = int_case.get_fan_rotor_number(fan.name) + rotors = fan.rotor_list + for rotor in rotors: + print("%s %s"%(fan.name, rotor.name) , end =' ' ) + print(int_case.get_fan_speed(fan.name, rotor.name)) + pass + +def fan_feed_watchdog(): + '''fan_feed_watchdog''' + print("=================fan_feed_watchdog======================") + fan_get_speed() + print (int_case.feed_fan_watchdog(None)) + time.sleep(2) + fan_get_speed() + +def fan_set_led(color): + '''fan_set_led''' + print("=================fan_set_led======================") + fans = int_case.get_fans() + for fan in fans: + print("%s" % fan.name) + for i in range(2): + if i == 0: + flag = True + elif i == 1: + flag = False + print(color, int_case.set_fan_led(fan.name, color, flag)) + +def fan_get_presence(): + '''fan_get_presence''' + print("=================fan_get_presence======================") + fans = int_case.get_fans() + for fan in fans: + print("%s" % fan.name) + print(int_case.get_fan_presence(fan.name)) + +def fan_get_fru_info(): + '''fan_get_fru_info''' + print("=================fan_get_fru_info======================") + fans = int_case.get_fans() + for fan in fans: + print("%s" % fan.name) + print(json.dumps(int_case.get_fan_fru_info(fan.name), ensure_ascii=False, indent=4)) + +def fan_get_status(): + '''fan_get_status''' + print("=================fan_get_status======================") + fans = int_case.get_fans() + for fan in fans: + print("%s" % fan.name) + print(json.dumps(int_case.get_fan_status(fan.name), ensure_ascii=False, indent=4)) + +def fan_get_info_all(): + '''fan_get_info_all''' + print("=================fan_get_info_all======================") + print(json.dumps(int_case.get_fan_info_all(), ensure_ascii=False, indent=4)) + pass + +def get_sensor_info(): + '''get_sensor_info''' + print("=================get_sensor_info======================") + print(json.dumps(int_case.get_sensor_info(), ensure_ascii = False, indent=4)) + +if __name__ == '__main__': + clival.Fire( + { + psu:{ + get_total_number : None, + get_presence : None, + get_fru_info : None, + set_psu_fan_speed_pwm : None, + get_psu_fan_speed_pwm : None, + get_status : None, + get_psu_power_status : None, + get_info_all : None + }, + fan:{ + fan_get_total_number : None, + fan_get_rotor_number : None, + fan_get_speed : None, + fan_set_speed : None, + fan_get_speed_pwm : None, + fan_set_speed_pwm : None, + fan_get_watchdog_status : None, + fan_enable_watchdog : None, + fan_disable_watchdog : None, + fan_feed_watchdog : None, + fan_set_led : None, + fan_get_presence : None, + fan_get_fru_info : None, + fan_get_status : None, + fan_get_info_all : None + }, + sensor:{ + get_sensor_info : None + } + } + + ) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/interface.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/interface.py new file mode 100644 index 000000000000..3b58e1a5fe9d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/interface.py @@ -0,0 +1,76 @@ +from sonic_platform.fan import Fan +from sonic_platform.thermal import Thermal +from sonic_platform.chassis import Chassis + +class Interface(): + def __init__(self): + self.chassis = Chassis() + self.fan_list = self.chassis._fan_list + self.thermal_list = self.chassis._thermal_list + self.psu_list = self.chassis._psu_list + # Device + def get_productname(self): + return self.chassis.get_name() + + # Thermal + def get_thermal_temp_max(self, name): + for thermal in self.thermal_list: + if name == thermal.get_name(): + return thermal.get_high_threshold() + + def get_thermal_temp_min(self, name): + for thermal in self.thermal_list: + if name == thermal.get_name(): + return thermal.get_low_threshold() + + def get_thermal_temp(self, name): + for thermal in self.thermal_list: + if name == thermal.get_name(): + return thermal.get_temperature() + # Fans + def set_fan_speed_pwm(self, speed): + return self.fan_list[0].set_speed_pwm(speed) + + def get_fan_status(self): + for fan in self.fan_list: + if fan.get_status() == False: + return False + return True + + def get_fan_presence(self): + for fan in self.fan_list: + if fan.get_presence() == False: + return False + return True + + def set_fan_board_led(self, color): + return self.fan_list[0].set_status_led(color) + + def get_fan_speed_rpm(self, name): + for fan in self.fan_list: + if name == fan.get_name(): + return fan.get_speed_rpm() + return 0 + + def get_fan_rpm_max(self): + return self.fan_list[0].get_high_critical_threshold() + + def get_airflow(self): + tmp1 = self.fan_list[0].get_direction() + tmp2 = self.fan_list[0].get_direction() + for fan in self.fan_list: + tmp1 = fan.get_direction() + if tmp1 != tmp2: + return "F2B" + tmp2 = tmp1 + return tmp2 + # Psus + def get_psu_status(self): + for psu in self.psu_list: + if psu.get_powergood_status == False: + return False + return True + + def set_psu_board_led(self, color): + return self.psu_list[0].set_status_led(color) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_manufacturer b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_manufacturer new file mode 100644 index 000000000000..078b3d2fec2c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_manufacturer @@ -0,0 +1,395 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from os import popen +from sys import path, exit, stderr +from commands import getstatusoutput +from ragileconfig import * +from monitor import status +import mmap + + +INDENT = 4 + +def printerr(vchar): + stderr.write(vchar + '\n') + +g_extra_cache = dict() +g_meminfo_cache = dict() +g_exphy_cache = dict() + +def exphyfwsplit(): + # improve performance + global g_exphy_cache + if g_exphy_cache: + return + cmd = "bcmcmd -t 1 \"phy control xe,ce fw_get\" |grep fw_version" + status, output = log_os_system(cmd) + if status or len(output) == 0: + raise Exception("run cmd: {} error, status {}".format(cmd, status)) + exphyfwstr = output.strip() + portlist = exphyfwstr.split("\n") + for port in portlist: + phy_addr_str = get_regular_val(port,r"phy_addr\s*=\s*\w+",0) + if phy_addr_str.startswith("ERR"): + continue + phy_addr_key = phy_addr_str.replace(" ","") + if phy_addr_key in g_exphy_cache: + continue + + g_exphy_cache[phy_addr_key] = {} + + fw_version_str = get_regular_val(port,r"fw_version\s*=\s*\w+",0) + if fw_version_str.startswith("ERR"): + del g_exphy_cache[phy_addr_key] + continue + + fw_version = fw_version_str.split("=")[1].strip() + g_exphy_cache[phy_addr_key]["fw_version"] = fw_version + + if "success" in port: + status = "OK" + else: + status = "Unexpected" + g_exphy_cache[phy_addr_key]["status"] = status + return + +def get_exphy_fw(phyid): + exphyfwsplit() + if phyid not in g_exphy_cache: + return "ERR %s not found." % phyid + fw_version = g_exphy_cache.get(phyid).get("fw_version") + status = g_exphy_cache.get(phyid).get("status") + msg = "%s %s" % (fw_version, status) + return msg + +def lshwmemorysplit(): + # improve performance + global g_meminfo_cache + if g_meminfo_cache: + return + cmd = "lshw -c memory" + status, output = log_os_system(cmd) + if status or len(output) == 0: + raise Exception("run cmd: {} error, status {}".format(cmd, status)) + memstr = output.strip() + memlist = memstr.split("*-") + for item in memlist: + if item.strip().startswith("memory") and "System Memory" not in item: + continue + line_index = 0 + for line in item.splitlines(): + line_index += 1 + if line_index == 1: + memdict_key = line + g_meminfo_cache[memdict_key] = {} + else: + if ":" not in line: + continue + key = line.split(":", 1)[0].strip() + value = line.split(":", 1)[1].strip() + g_meminfo_cache[memdict_key][key] = value + if "empty" in item: + break + return + + +def run_extra_func(funcname): + # improve performance + if g_extra_cache.__contains__(funcname): + return g_extra_cache.get(funcname) + func = getattr(status, funcname) + ret = [] + func(ret) + if ret: + g_extra_cache[funcname] = ret + return ret + + +def get_extra_value(funcname, itemid, key): + for item in run_extra_func(funcname): + if item.get("id") == itemid: + return item.get(key,"NA") + return "NA" + + +def get_memory_value(params): + global g_meminfo_cache + root_key = params.get("root_key") + sub_key = params.get("sub_key") + lshwmemorysplit() + return g_meminfo_cache.get(root_key,{}).get(sub_key,"NA") + + +def get_memory_bank_value(params): + global g_meminfo_cache + lshwmemorysplit() + bank = params.get("bankid") + if g_meminfo_cache.get(bank,{}): + return True + return False + + +def get_func_value(funcname, params): + ret = eval(funcname)(params) + return ret + +def read_pci_reg(pcibus , slot , fn, bar, offset): + '''read pci register''' + if offset % 4 != 0: + return + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + size = os.path.getsize(filename) + with open(filename, "r+") as file: + data = mmap.mmap(file.fileno(), size) + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + data.close() + return "0x%08x" % val + + +def read_reg(loc, offset, size): + with open(loc, 'rb') as file: + file.seek(offset) + return ' '.join(["%02x" % ord(item) for item in file.read(size)]) + + +def std_match(stdout, pattern): + if pattern is None: + return stdout.strip() + for line in stdout.splitlines(): + if re.match(pattern, line): + return line.strip() + raise EOFError("pattern: {} does not match anything in stdout {}".format( + pattern, stdout)) + + +def i2c_rd(bus, loc, offset): + ''' + read i2c with i2cget command + ''' + cmd = "i2cget -f -y {} {} {}".format(bus, loc, offset) + # TODO: add retry + retrytime = 6 + for i in range(retrytime): + ret, stdout = getstatusoutput(cmd) + if ret == 0: + return stdout + time.sleep(0.1) + raise RuntimeError("run cmd: {} error, status {}".format(cmd, ret)) + + +def i2c_rd_bytes(bus, loc, offset, size): + blist = [] + for i in range(size): + ret = i2c_rd(bus, loc, offset + i) + blist.append(ret) + + return blist + + +def get_pair_val(source, separator): + try: + value = source.split(separator, 1)[1] + except (ValueError, IndexError) as e: + # printerr(e.message) + return ("ERR separator: {} does not match in source: {}".format(separator, source)) + return value.strip() + +def get_regular_val(source, pattern, group): + try: + value = re.findall(pattern, source)[group] + except Exception as e: + # printerr(str(e)) + return ("ERR pattern: {} does not match in source: {} with group: {}".format(pattern, source, group)) + return value.strip() + + +def find_match(file2read, pattern): + with open(file2read, 'r') as file: + for line in file: + if not re.match(pattern, line): + continue + return line.strip() + + +def readaline(file2read): + with open(file2read, 'r') as file: + return file.readline() + + +def sort_key(e): + return e.arrt_index + +def log_os_system(cmd): + status, output = getstatusoutput(cmd) + return status, output + +class CallbackSet: + def cpld_format(self, blist): + if isinstance(blist, str): + blist = blist.split() + elif not isinstance(blist, list) or len(blist) != 4: + raise ValueError("cpld format: wrong parameter: {}".format(blist)) + + return "{}{}{}{}".format(*blist).replace("0x", "") + + +class VersionHunter: + call = CallbackSet() + + def __init__(self, entires): + self.head = None + self.next = None + self.key = None + self.cmd = None + self.file = None + self.reg = None + self.i2c = None + self.extra = None + self.pattern = None + self.separator = None + self.parent = None + self.ignore = False + self.children = [] + self.level = 0 + self.callback = None + self.delspace = None + self.arrt_index = None + self.config = None + self.precheck = None + self.func = None + self.regular = None + self.group = 0 + self.pci = None + self.__dict__.update(entires) + + def check_para(self): + if self.pattern is None: + return False + if self.cmd is None or self.file is None: + return False + return True + + def get_version(self): + ret = "NA" + try: + if self.cmd is not None: + status, output = log_os_system(self.cmd) + if status or len(output) == 0: + raise RuntimeError("run cmd: {} error, status {}".format(self.cmd, ret)) + ret = std_match(output, self.pattern) + elif self.file is not None: + ret = self.read_file() + elif self.reg is not None: + ret = read_reg(self.reg.get("loc"), self.reg.get("offset"), + self.reg.get("size")) + elif self.extra: + ret = get_extra_value(self.extra.get("funcname"), + self.extra.get("id"), + self.extra.get("key")) + elif self.i2c: + ret = i2c_rd_bytes(self.i2c.get("bus"), self.i2c.get("loc"), + self.i2c.get("offset"), + self.i2c.get("size")) + elif self.config: + ret = self.config + elif self.func: + ret = get_func_value(self.func.get("funcname"), + self.func.get("params")) + elif self.pci: + ret = read_pci_reg(self.pci.get("bus"),self.pci.get("slot"), + self.pci.get("fn"),self.pci.get("bar"),self.pci.get("offset")) + + except Exception as e: + # printerr(e.message) + return "ERR %s" % str(e) + return self.exe_callback(ret) + + def exe_callback(self, data): + try: + if self.callback: + method = getattr(self.call, self.callback) + return method(data) + except Exception as e: + # printerr("run callback method: {} error, data: {}".format(self.callback, data)) + # printerr(e.message) + return "ERR run callback method: {} error, data: {}".format(self.callback, data) + return data + + def read_file(self): + if self.pattern is not None: + return find_match(self.file, self.pattern) + else: + return readaline(self.file) + + def hunt(self): + if self.ignore: + return + indent = self.level * INDENT * " " + + if self.precheck: + try: + ret = eval(self.precheck.get("funcname"))(self.precheck.get("params")) + if ret is not True: + return + except Exception as e: + err_msg = "ERR %s" % str(e) + format_str = "{}{:<{}}{}".format(indent, self.key + ':', + (30 - len(indent)), err_msg) + return + # has children + if self.children: + self.children.sort(key=sort_key) + format_str = "{}{}:".format(indent, self.key) + print(format_str) + for child in self.children: + if not isinstance(child, VersionHunter): + continue + child.level = self.level + 1 + child.hunt() + else: + version = self.get_version() or "" + if not version.startswith("ERR"): + version = version.replace("\x00","").strip() + if self.separator is not None: + version = get_pair_val(version, self.separator) + if self.delspace is not None: + version = version.replace(" ", "") + if self.regular is not None: + version = get_regular_val(version, self.regular, self.group) + format_str = "{}{:<{}}{}".format(indent, self.key + ':', + (30 - len(indent)), version) + print(format_str) + + if self.next: + print("") + self.next.hunt() + + +if __name__ == "__main__": + objmap = dict() + + try: + target = {} + target.update(MANUINFO_CONF) + for objname, value in target.items(): + objmap[objname] = VersionHunter(value) + except Exception as e: + printerr(e.message) + exit(-1) + + head = None + for objname, obj in objmap.items(): + if head is None and obj.head: + head = obj + if obj.parent: + objmap.get(obj.parent).children.append(obj) + if obj.next: + obj.next = objmap.get(obj.next) + + head.hunt() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_sensors.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_sensors.py new file mode 100644 index 000000000000..71a50043d59f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/platform_sensors.py @@ -0,0 +1,201 @@ +#!/usr/bin/python + +# On S6100, the Platform Management Controller runs the +# thermal algorithm. It provides a mailbox for the Host +# to query relevant thermals. The dell_mailbox module +# provides the sysfs support for the following objects: +# * onboard temperature sensors +# * FAN trays +# * PSU +# +import os +import sys +import re +import imp +from collections import OrderedDict + +def get_machine_info(): + if not os.path.isfile('/host/machine.conf'): + return None + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + +def get_platform_info(machine_info): + if machine_info != None: + if machine_info.__contains__('onie_platform'): + return machine_info['onie_platform'] + elif machine_info.__contains__('aboot_platform'): + return machine_info['aboot_platform'] + return None + + + +PLATFORM_ROOT_PATH = '/usr/share/sonic/device' +PLATFORM_SPECIFIC_MODULE_NAME = 'monitor' +PLATFORM_SPECIFIC_CLASS_NAME = 'status' +platform_status_class = None +platform = None + +def get_platform_name(): + global platform + platform = get_platform_info(get_machine_info()) + return platform + +val = get_platform_name() +import sys +sys.path.append("/".join([PLATFORM_ROOT_PATH, platform])) + +# Loads platform specific sfputil module from source +def load_platform_monitor(): + global platform_status_class + platform = get_platform_info(get_machine_info()) + platform_path = "/".join([PLATFORM_ROOT_PATH, platform]) + try: + module_file = "/".join([platform_path, PLATFORM_SPECIFIC_MODULE_NAME + ".py"]) + module = imp.load_source(PLATFORM_SPECIFIC_MODULE_NAME, module_file) + except IOError as e: + return -1 + try: + platform_status_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + except AttributeError as e: + return -2 + return 0 + + +def printerr(str): + print("\033[0;31m%s\033[0m" % str) + +def print_console(str): + print(str) + + +val_t = load_platform_monitor() +if val_t != 0: + raise Exception("load monitor.py error") + +def print_platform(): + platform_info = get_platform_name() + print_console(platform_info) + print_console('Adapter: Ragile Platform Management Controller') + print_console("") + +def print_cputemp_sensors(): + val_ret = get_call_value_by_function("getcputemp") + print_info_str = "" + toptile = "Onboard coretemp Sensors:" + formatstr = " {name:<20} : {temp} C (high = {max} C , crit = {crit} C )" + + if len(val_ret) != 0 : + print_info_str += toptile + '\n' + for item in val_ret: + print_info_str += formatstr.format(**item) + '\n' + print_console(print_info_str) + + +def print_boardtemp(): + val_ret = get_call_value_by_function("getTemp") + print_info_str = "" + toptile = "Onboard Temperature Sensors:" + formatstr = " {id:<20} : {temp1_input} C (high ={temp1_max} C, hyst ={temp1_max_hyst} C)" # %15s : %10.1f %s (high = %.1f C , hyst = %.1f C) + + if len(val_ret) != 0 : + print_info_str += toptile + '\n' + for item in val_ret: + print_info_str += formatstr.format(**item) + '\n' + print_console(print_info_str) + +def print_fan_sensor(): + val_ret = get_call_value_by_function("checkFan") + print_info_str = "" + toptile = "Onboard fan Sensors:" + errformat = " {id} : {errmsg}\n" # " {id:<20} : {errmsg}" + fan_signle_rotor_format =" {id} : \n" \ + " fan_type :{fan_type}\n" \ + " sn :{sn}\n" \ + " hw_version:{hw_version}\n" \ + " Speed :{Speed} RPM\n" \ + " status :{errmsg} \n" + fan_double_rotor_format = " {id} : \n" \ + " fan_type :{fan_type}\n" \ + " sn :{sn}\n" \ + " hw_version:{hw_version}\n" \ + " Speed :\n" \ + " speed_front :{rotor1_speed:<5} RPM\n" \ + " speed_rear :{rotor2_speed:<5} RPM\n" \ + " status :{errmsg} \n" + + if len(val_ret) != 0 : + print_info_str += toptile + '\n' + for item in val_ret: + if item.get('Speed', None) is None: + realformat = fan_double_rotor_format if item.get('errcode', 0) == 0 else errformat + else: + realformat = fan_signle_rotor_format if item.get('errcode', 0) == 0 else errformat + print_info_str += realformat.format(**item) + print_console(print_info_str) + +def print_psu_sensor(): + val_ret = get_call_value_by_function("getPsu") + print_info_str = "" + toptile = "Onboard Power Supply Unit Sensors:" + errformat = " {id} : {errmsg}\n" #" {id:<20} : {errmsg}" + psuformat = " {id} : \n" \ + " type :{type1}\n" \ + " sn :{sn}\n" \ + " in_current :{in_current} A\n" \ + " in_voltage :{in_voltage} V\n" \ + " out_current:{out_current} A\n" \ + " out_voltage:{out_voltage} V\n" \ + " temp :{temp} C \n" \ + " fan_speed :{fan_speed} RPM\n" \ + " in_power :{in_power} W\n" \ + " out_power :{out_power} W\n" + + if len(val_ret) != 0 : + print_info_str += toptile + '\r\n' + for item in val_ret: + realformat = psuformat if item.get('errcode', 0) == 0 else errformat + print_info_str += realformat.format(**item) + print_console(print_info_str) + +def print_slot_sensor(): + val_ret = get_call_value_by_function("checkSlot") + print_info_str = "" + toptile = "Onboard slot Sensors:" + errformat = " {id} : {errmsg}" # " {id:<20} : {errmsg}" + psuformat = " {id} : \n" \ + " slot_type :{slot_type}\n" \ + " sn :{sn}\n" \ + " hw_version :{hw_version} \n" \ + " status :{errmsg}\n" + + if len(val_ret) != 0 : + print_info_str += toptile + '\r\n' + for item in val_ret: + realformat = psuformat if item.get('errcode', 0) == 0 else errformat + print_info_str += realformat.format(**item) + print_console(print_info_str) + +def get_call_value_by_function(function_name): + valtemp = [] + if hasattr(platform_status_class, function_name): + test2_func = getattr(platform_status_class, function_name) + test2_func(valtemp) + return valtemp + +def getsensors(): + print_platform() + print_cputemp_sensors() + print_boardtemp() + print_fan_sensor() + print_psu_sensor() + print_slot_sensor() + +if __name__ == "__main__": + getsensors() \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/pmon_sys b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/pmon_sys new file mode 100644 index 000000000000..f23f3ca0142e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/pmon_sys @@ -0,0 +1,134 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +# * onboard interval check +# * FAN trays +# * PSU +# * temp +import os +import time +import datetime +import platform +import syslog + +from rjutil.baseutil import get_machine_info +from rjutil.baseutil import get_platform_info + +x = get_platform_info(get_machine_info()) +if x != None: + filepath = "/usr/share/sonic/device/" + x +import sys +sys.path.append(filepath) + +from monitor import status + +class platformSyslog(): + def __init__(self): + self.preFanStatus = [] + self.prePsuStatus = [] + + def sortCallback(self, element): + return element['id'] + + def updateFanStatus(self): + curFanStatus = [] + status.checkFan(curFanStatus) + curFanStatus.sort(key = self.sortCallback) + if cmp(self.preFanStatus, curFanStatus) != 0: + if len(self.preFanStatus) == 0: + # first time + for i,item in enumerate(curFanStatus): + if cmp(item['errmsg'], 'OK') == 0: + syslog.syslog('%%PMON-0-FAN_PLUG_IN: %s'%(item['id'])) + elif cmp(item['errmsg'], 'NOT OK') == 0: + syslog.syslog('%%PMON-0-FAN_FAILED: %s'%(item['id'])) + else: + syslog.syslog('%%PMON-0-FAN_ABSENT: %s'%(item['id'])) + self.preFanStatus.append(item) + else: + for i,item in enumerate(curFanStatus): + if cmp(item['errmsg'], self.preFanStatus[i]['errmsg']) == 0: + continue + else: + if cmp(item['errmsg'], 'OK') == 0 and cmp(self.preFanStatus[i]['errmsg'], 'ABSENT') == 0: + syslog.syslog('%%PMON-0-FAN_PLUG_IN: %s'%(item['id'])) + elif cmp(item['errmsg'], 'OK') == 0 and cmp(self.preFanStatus[i]['errmsg'], 'NOT OK') == 0: + syslog.syslog('%%PMON-0-FAN_PLUG_IN: %s. Recover from FAN FAILED.'%(item['id'])) + elif cmp(item['errmsg'], 'NOT OK') == 0 and cmp(self.preFanStatus[i]['errmsg'], 'OK') == 0: + syslog.syslog('%%PMON-0-FAN_FAILED: %s.'%(item['id'])) + elif cmp(item['errmsg'], 'NOT OK') == 0 and cmp(self.preFanStatus[i]['errmsg'], 'ABSENT') == 0: + syslog.syslog('%%PMON-0-FAN_PLUG_IN: %s'%(item['id'])) + syslog.syslog('%%PMON-0-FAN_FAILED: %s'%(item['id'])) + elif cmp(item['errmsg'], 'ABSENT') == 0 and cmp(self.preFanStatus[i]['errmsg'], 'OK') == 0: + syslog.syslog('%%PMON-0-FAN_PLUG_OUT: %s'%(item['id'])) + elif cmp(item['errmsg'], 'ABSENT') == 0 and cmp(self.preFanStatus[i]['errmsg'], 'NOT OK') == 0: + syslog.syslog('%%PMON-0-FAN_PLUG_OUT: %s'%(item['id'])) + self.preFanStatus.remove(self.preFanStatus[i]) + self.preFanStatus.insert(i, item) + + def updatePsuStatus(self): + curPsuStatus = [] + status.getPsu(curPsuStatus) + curPsuStatus.sort(key = self.sortCallback) + if cmp(self.prePsuStatus, curPsuStatus) != 0: + if len(self.prePsuStatus) == 0: + # first time + for i,item in enumerate(curPsuStatus): + if cmp(item['errmsg'], 'OK') == 0: + syslog.syslog('%%PMON-0-PSU_PLUG_IN: %s'%(item['id'])) + elif cmp(item['errmsg'], 'NOT OK') == 0: + syslog.syslog('%%PMON-0-PSU_FAILED: %s'%(item['id'])) + else: + syslog.syslog('%%PMON-0-PSU_ABSENT: %s'%(item['id'])) + self.prePsuStatus.append(item) + else: + for i,item in enumerate(curPsuStatus): + if cmp(item['errmsg'], self.prePsuStatus[i]['errmsg']) == 0: + continue + else: + if cmp(item['errmsg'], 'OK') == 0 and cmp(self.prePsuStatus[i]['errmsg'], 'ABSENT') == 0: + syslog.syslog('%%PMON-0-PSU_PLUG_IN: %s'%(item['id'])) + elif cmp(item['errmsg'], 'OK') == 0 and cmp(self.prePsuStatus[i]['errmsg'], 'NOT OK') == 0: + syslog.syslog('%%PMON-0-PSU_PLUG_IN: %s. Recover from PSU FAILED.'%(item['id'])) + elif cmp(item['errmsg'], 'NOT OK') == 0 and cmp(self.prePsuStatus[i]['errmsg'], 'OK') == 0: + syslog.syslog('%%PMON-0-PSU_FAILED: %s.'%(item['id'])) + elif cmp(item['errmsg'], 'NOT OK') == 0 and cmp(self.prePsuStatus[i]['errmsg'], 'ABSENT') == 0: + syslog.syslog('%%PMON-0-PSU_PLUG_IN: %s'%(item['id'])) + syslog.syslog('%%PMON-0-PSU_FAILED: %s'%(item['id'])) + elif cmp(item['errmsg'], 'ABSENT') == 0 and cmp(self.prePsuStatus[i]['errmsg'], 'OK') == 0: + syslog.syslog('%%PMON-0-PSU_PLUG_OUT: %s'%(item['id'])) + elif cmp(item['errmsg'], 'ABSENT') == 0 and cmp(self.prePsuStatus[i]['errmsg'], 'NOT OK') == 0: + syslog.syslog('%%PMON-0-PSU_PLUG_OUT: %s'%(item['id'])) + self.prePsuStatus.remove(self.prePsuStatus[i]) + self.prePsuStatus.insert(i, item) + + def getTempStatus(self): + temp = [] + status.getTemp(temp) + for i,item in enumerate(temp): + ''' + if cmp(item['errmsg'], 'OK') != 0: + syslog.syslog('%%PMON-0-TEMP_FAILED: %s'%(item['id'])) + elif float(item['temp1_input']) >= float(item['temp1_max']): + syslog.syslog('%%PMON-0-TEMP_HIGH: %s temperature %sC is larger than max threshold %sC.'%(item['id'], item['temp1_input'], item['temp1_max'])) + ''' + if float(item['temp1_input']) >= float(item['temp1_max']): + syslog.syslog('%%PMON-0-TEMP_HIGH: %s temperature %sC is larger than max threshold %sC.'%(item['id'], item['temp1_input'], item['temp1_max'])) + +def doWork(platform): + platform.updateFanStatus() + platform.updatePsuStatus() + platform.getTempStatus() + +def run(interval, platform): + while True: + try: + doWork(platform) + time.sleep(interval) + except Exception as e: + print(e) + +if __name__ == '__main__': + platform = platformSyslog() + interval = 3 + run(interval, platform) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/port.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/port.py new file mode 100644 index 000000000000..3fecf95e1592 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/port.py @@ -0,0 +1,3790 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +'''Test the PORT component''' +import time +import datetime +import os +import re +import io +import logging +import syslog +import subprocess +import portutil +import collections +import json +import collections +import traceback +import abc +import sys +import click +import copy +import yaml + +from sfputil.main import * +from rjutil.baseutil import get_machine_info +from rjutil.baseutil import get_platform_info + +SYSLOG_IDENTIFIER = "PORT" +SAI_PROFILE = "sai.profile" +SAI_PROFILE_PREDIX = "SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/" +CONFIG_DB_JSON_PATH = "/etc/sonic/config_db.json" +MACHINE_FILE = "/host/machine.conf" +MACHINE_PLATFORM_PREDIX = "onie_platform=" + +LOG_DEBUG_LEVEL = 1 +LOG_INFO_LEVEL = 2 +LOG_WARNING_LEVEL = 3 +LOG_ERROR_LEVEL = 4 + +LANE_MAX = 4 +PACKETS_COUNT = 10000 +PACKETS_SIZE = 64 +PACKETS_DST_MAC = "ff:ff:ff:ff:ff:ff" +PORT_TEST_VLAN = 4048 +KR_VLAN = 4080 +PRBS_BER_DEFAULT = 1.0e-8 +PRBS_TIME_DEFAULT = 120 + +###################### HSDK Config ###################### +# --------------------------------------------------------------------- # +# Internal management port +global_mgmt_kr_ports = { + "x86_64-ragile_b6510-48vs8cq-r0":{"eth1":66, "eth2":130}, +} + +global_prbs_port_range = { + +} + +# A device with an external PHY +global_extphy_device = { + +} + +# Use HSDK equipment +global_hsdk_device = { + +} + +# Device correspondingprbs ber +global_prbs_ber = { + +} + +# Device corresponding prbs test of time +global_prbs_time = { + +} + +# Port Test related configuration +PORT_FACTEST_CONFIG = { + "port_frame_test_retrynum": 1,# Retry times of sending and receiving frames on the port + "port_brcst_test_retrynum": 1,# Number of port broadcast test retries + "port_prbs_test_retrynum": 1,# Port PRBS test retry count + "port_kr_test_retrynum": 1,# Number of internal management port test retries + "port_frame_del_time": 10,# Waiting time for sending and receiving frames on the port to recover the test environment(s) + "port_brcst_del_time": 10,# Port broadcast test Recovery test environment wait time(s) + "port_prbs_del_time": 10,# Port PRBS test Recovery test environment waiting time(s) + "port_kr_del_time": 10,# Internal management port test Recovery test environment waiting time(s) + "port_log_level": LOG_ERROR_LEVEL,# PORT Component log level +} +# --------------------------------------------------------------------- # + +# True: Print the log at the same time (default False) +log_also_print_to_console = False +# True: Print CMD at the same time (default False) +cmd_also_print_to_console = False +# True: Print CMD execution results at the same time (default False) +cmd_output_also_print_to_console = False +# True: Prints the log of the entire test flow to the console when the test fails (default True) +port_log_info_print_to_console = False +# True: Enable input redirection cmd + < /dev/null(default True) +sdk_cmd_redirect_console = True + +# Test Port configurations +global_port_config = { + "hsdk_device" : 1,# bcmcmdb devices + "mgmt_kt_ports" : {}, + "prbs_port_range" : "", + "extphy_device" : 0, + "prbs_ber" : PRBS_BER_DEFAULT, + "prbs_time" : PRBS_TIME_DEFAULT, + "port_frame_test_retrynum": 1,# Retry times of sending and receiving frames on the port + "port_brcst_test_retrynum": 1,# Number of port broadcast test retries + "port_prbs_test_retrynum": 1,# Port PRBS test retry count) + "port_kr_test_retrynum": 1,# Number of internal management port test retries + "port_frame_del_time": 10,# Waiting time for sending and receiving frames on the port to recover the test environment(s) + "port_brcst_del_time": 10,# Port broadcast test Recovery test environment wait time(s) + "port_prbs_del_time": 10,# Port PRBS test Recovery test environment waiting time(s) + "port_kr_del_time": 10,# Internal management interface Test Recovery Test environment Waiting time (s) + "port_log_level": LOG_ERROR_LEVEL,# PORT Component log level + "flag" : False # Whether the port configuration has been loaded +} + +global_port_log_info = "port_log_info:\n" +global_prbs_info = "" +global_onie_platform = "" +global_unit_port_list = [] + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + '''Command alias''' + + def get_command(self, ctx, cmd_name): + '''Get command''' + get_rv = click.Group.get_command(self, ctx, cmd_name) + if get_rv is not None: + return get_rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if matches: + if len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + return None + +###################### HSDK Config ###################### + + +def prepare_kr_test(): + pk = PortKrTest() + pk.install_pktgen_mode() + +# Print the output according to the format +def port_totalprint(arr, tips): + if len(arr) <= 0: + return + print ("%-20s" % tips ,) + for index in range(len(arr)): + print ("%03d" % arr[index] ,) + if (index + 1) % 8 == 0: + print ("") + print (" " * 20,) + print ("") + +def singleton(cls): + '''singleton''' + + _instance = {} + def _singleton(*args, **kargs): + if cls not in _instance: + _instance[cls] = cls(*args, **kargs) + return _instance[cls] + + return _singleton + +def log_info_gather_fun(log_content): + '''test process log collection''' + + global global_port_log_info + global_port_log_info = global_port_log_info + "\n" + log_content + +def prbs_info_gather_fun(prbs_content, clear=False): + '''prbs test process information collection''' + + global global_prbs_info + if clear == True: + global_prbs_info = prbs_content + else: + global_prbs_info = global_prbs_info + "\n" + prbs_content + +def log_debug(msg): + '''debug log''' + + funcName = sys._getframe().f_back.f_code.co_name # Gets the name of the calling function + lineNumber = sys._getframe().f_back.f_lineno # obtain a line number + dt_ms = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') # Date time in microseconds + info_str = dt_ms + "| DEBUG PORT: " + funcName +": "+ str(lineNumber) + log_info_gather = "%-40s| %s" % (info_str, str(msg)) + log_info_gather_fun(log_info_gather) + if global_port_config["port_log_level"] <= LOG_DEBUG_LEVEL: + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if log_also_print_to_console: + click.echo(log_info_gather) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + +def log_info(msg): + '''info log''' + + funcName = sys._getframe().f_back.f_code.co_name # Gets the name of the calling function + lineNumber = sys._getframe().f_back.f_lineno # obtain a line number + dt_ms = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') # Date time in microseconds + info_str = dt_ms + "| INFO PORT: " + funcName +": "+ str(lineNumber) + log_info_gather = "%-40s| %s" % (info_str, str(msg)) + log_info_gather_fun(log_info_gather) + if global_port_config["port_log_level"] <= LOG_INFO_LEVEL: + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + if log_also_print_to_console: + click.echo(log_info_gather) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + +def log_warning(msg): + '''warning log''' + + funcName = sys._getframe().f_back.f_code.co_name # Gets the name of the calling function + lineNumber = sys._getframe().f_back.f_lineno # obtain a line number + dt_ms = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') # Date time in microseconds + info_str = dt_ms + "| WARNING PORT: " + funcName +": "+ str(lineNumber) + log_info_gather = "%-40s| %s" % (info_str, str(msg)) + log_info_gather_fun(log_info_gather) + if global_port_config["port_log_level"] <= LOG_WARNING_LEVEL: + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if log_also_print_to_console: + click.echo(log_info_gather) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + +def log_error(msg): + '''error log''' + + funcName = sys._getframe().f_back.f_code.co_name # Gets the name of the calling function + lineNumber = sys._getframe().f_back.f_lineno # obtain a line number + dt_ms = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') # Date time in microseconds + info_str = dt_ms + "| ERROR PORT: " + funcName +": "+ str(lineNumber) + log_info_gather = "%-40s| %s" % (info_str, str(msg)) + log_info_gather_fun(log_info_gather) + if global_port_config["port_log_level"] <= LOG_ERROR_LEVEL: + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if log_also_print_to_console: + click.echo(log_info_gather) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + +def port_getstatusoutput(cmd, time_sleep=0): + '''Obtain the execution result of the command''' + + ret, output = subprocess.getstatusoutput(cmd) + + t = int(time_sleep) + if cmd_also_print_to_console: + log_debug(cmd) + if cmd_output_also_print_to_console: + log_debug(output) + if t != 0: + log_debug("time sleep: %ds" % t) + time.sleep(t) + if ret == 0: + if (re.search('hsdk msg connect fail', output.strip())): + return -1, output + return ret, output + else: + output_content = "cmd: %s execution fail, output:%s" % (cmd, output) + return_output_content = output_content.replace("\"","'") + log_error("%s" % output_content) + return ret, "%s" % return_output_content + +def get_sdk_cmd(cmd, time_out=0, grep=""): + '''Combine the CMD passed in, return sdk_cmd''' + + cmd_str = "" + sdk_cmd = "" + t = int(time_out) + if (hsdk_check()): + sdk_cmd = "bcmcmdb " + else: + sdk_cmd = "bcmcmd " + if t != 0: + cmd_str = sdk_cmd + "-t %d \"" % t + else: + cmd_str = sdk_cmd + "\"" + if sdk_cmd_redirect_console == True: + cmd_str = cmd_str + str(cmd) + "\" < /dev/null" + else: + cmd_str = cmd_str + str(cmd) + "\"" + if grep != "": + cmd_str += " | grep \"%s\"" % str(grep) + return cmd_str + +class PortKrTest(object): + + def __get_onie_platform(self): + with open(MACHINE_FILE, "r") as machine_f: + for line in machine_f: + if(re.search('%s(.*?)$' % MACHINE_PLATFORM_PREDIX, line)): + onie_platform = re.findall(r"%s(.*?)$" % MACHINE_PLATFORM_PREDIX, line)[0] + return onie_platform + return None + + + def install_pktgen_mode(self): + try: + cmd = "lsmod | grep pktgen" + ret, output = subprocess.getstatusoutput(cmd) + if not output or ret != 0: + cmd = "modprobe pktgen" + ret, output = subprocess.getstatusoutput(cmd) + eth_list = list(global_mgmt_kr_ports[self.__get_onie_platform()].keys()) + eth_list.sort() + for eth in eth_list: + xe_port = self.get_mgmt_bcmport(eth) + cmd = "bcmcmd \"port %s en=1\"" % xe_port + ret, output = subprocess.getstatusoutput(cmd) + + time.sleep(3) + + for eth in eth_list: + cmd = "ls /proc/net/pktgen/%s" % eth + ret, output = subprocess.getstatusoutput(cmd) + if "cannot" in output: + cmd = "ifconfig %s up" % eth + ret, output = subprocess.getstatusoutput(cmd) + cmd = "echo \"add_device %s\" > /proc/net/pktgen/kpktgend_0" % eth + ret, output = subprocess.getstatusoutput(cmd) + + except Exception as e: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + + + def get_mgmt_bcmport(self, port): + cmd = "bcmcmd ps" + ret, output = subprocess.getstatusoutput(cmd) + lines = output.split("\n") + logic_port = global_mgmt_kr_ports[self.__get_onie_platform()][port] + for line in lines: + line.strip() + if re.search(r"^.*?\(.*?\)", line) and int(re.findall(r"^.*?\((.*?)\)", + line)[0].strip()) == logic_port: + return re.findall("^(.*?)\(.*?\)", line)[0].strip() + return None + + + def start_send_port_packets(self, port, count, size=64, dst_mac="ff:ff:ff:ff:ff:ff", vlan=4080): + cmd = "echo \"pkt_size %d\" > /proc/net/pktgen/%s" % (size, port) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"count %d\" > /proc/net/pktgen/%s" % (count, port) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"dst_mac %s\" > /proc/net/pktgen/%s" % (dst_mac, port) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"vlan_id %s\" > /proc/net/pktgen/%s" % (vlan, port) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"start\" > /proc/net/pktgen/pgctrl" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + time.sleep(2) + cmd = "echo \"stop\" > /proc/net/pktgen/pgctrl" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "cat /proc/net/pktgen/%s" % port + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def clear_port_packets(self): + for port in global_mgmt_kr_ports[self.__get_onie_platform()]: + cmd = "bcmcmd \"clear c %s\"" % self.get_mgmt_bcmport(port) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def check_port_packets(self, port, count): + cmd = "bcmcmd \"show c XLMIB_RPOK.%s\"" % self.get_mgmt_bcmport(port) + ret, output = subprocess.getstatusoutput(cmd) + lines = output.split("\n") + if(lines[1].strip()): + if (count == int(re.sub('[,]', '', lines[1].split()[2].strip("+-")))): + return True, lines[1].split()[2] + else: + return False, lines[1].split()[2] + return False, "fail" + +class PortTest(object): + __mode = 0 + + interfaces = [] + porttabfile = " " + bcm_ports = [] + + def __init__(self, mode = "sdk"): + self.__get_global_interfaces() + self.__get_global_bcmports() + if(mode == "sonic"): + self.__mode = 1 + else: + self.__mode = 0 + + def __get_global_interfaces(self): + if(len(self.interfaces)): + # print("inited interfaces") + pass + else: + cmd = "show interfaces status" + strs = os.popen(cmd) + for line in strs: + line.strip() + if(len(line.split()) and re.search("Ethernet[0-9]+", line.split()[0])): + self.interfaces.append(line.split()[0]) + + + def __get_global_bcmports(self): + if(len(self.bcm_ports)): + pass + else: + pu = portutil.PortUtil() + cmd = "bcmcmd ps" + strs = os.popen(cmd) + lines = strs.readlines() + for port in pu.device_port_list: + for line in lines: + line.strip() + if re.search(r"^.*?\(.*?\)", line) and int(re.findall(r"^.*?\((.*?)\)", line)[0].strip()) == port.logic_port: + self.bcm_ports.append(re.findall("^(.*?)\(.*?\)", line)[0].strip()) + break + + + def __get_port_status_by_sonic(self, port): + cmd = "show int status %s" % self.interfaces[port - 1] + strs = os.popen(cmd) + lines = strs.readlines() + return lines[-2].split()[5] + + + def __get_port_status_by_sdk(self, port): + cmd = "bcmcmd \"ps %s\"" % self.bcm_ports[port - 1] + strs = os.popen(cmd) + lines = strs.readlines() + if(re.search("up", lines[3])): + return "up" + elif(re.search("!ena", lines[3])): + return "!ena" + else: + return "down" + + + def __get_unit_port_by_bcm(self, port): + cmd = "bcmcmd \"ps %s\"" % self.bcm_ports[port - 1] + strs = os.popen(cmd) + lines = strs.readlines() + unit_port = int(re.findall("%s\((.*?)\)" % self.bcm_ports[port - 1], lines[3])[0].strip()) + return unit_port + + + def __start_send_port_packets_by_sonic(self, port, count, size=64, dst_mac="ff:ff:ff:ff:ff:ff"): + cmd = "echo \"add_device %s\" > /proc/net/pktgen/kpktgend_0" % self.interfaces[port - 1] + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"pkt_size %d\" > /proc/net/pktgen/%s" % (size, self.interfaces[port - 1]) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"count %d\" > /proc/net/pktgen/%s" % (count, self.interfaces[port - 1]) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"dst_mac %s\" > /proc/net/pktgen/%s" % (dst_mac, self.interfaces[port - 1]) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "echo \"start\" > /proc/net/pktgen/pgctrl" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = "cat /proc/net/pktgen/%s" % self.interfaces[port - 1] + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def __start_send_port_packets_by_sdk(self, port, count, size=64, dst_mac="ff:ff:ff:ff:ff:ff"): + cmd = "bcmcmd \"pbmp %s\"" % self.bcm_ports[port - 1] + strs = os.popen(cmd) + lines = strs.readlines() + pbmp = re.findall("0x[0-9]+",lines[1].strip())[0] + cmd = "bcmcmd \"tx %d VLantag=1 TXUnit=0 PortBitMap=%s Length=%d DestMac=%s\"" % (count, pbmp, size, dst_mac) + ret, output = subprocess.getstatusoutput(cmd) + # print output + if(ret != 0 ): + return False, output + return True, output + + + def __clear_port_packets_by_sonic(self): + cmd = "show interfaces counters -c" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def __clear_port_packets_by_sdk(self): + cmd = "bcmcmd \"clear c\"" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def __check_port_packets_by_sonic(self, port, count, direc = "tx"): + cmd = "show interfaces counters" + strs = os.popen(cmd) + lines = strs.readlines() + for line in lines: + line.strip() + if(len(line.split()) and re.search("Ethernet[0-9]+", line.split()[0])): + if(self.interfaces[port - 1] == line.split()[0]): + if(direc == "tx"): + if(count == int(re.sub('[,]', '', line.split()[9]))): + return True, line.split()[9] + else: + #print("packets num = %s" % int(re.sub('[,]', '', line.split()[9]))) + return False, line.split()[9] + elif(direc == "rx"): + if(count == int(re.sub('[,]', '', line.split()[2]))): + return True, line.split()[9] + else: + #print("packets num = %s" % int(re.sub('[,]', '', line.split()[2]))) + return False, line.split()[9] + return False, "fail" + + + def __check_port_packets_by_sdk(self, port, count, direc = "tx"): + if(direc == "tx"): + cmd = "bcmcmd \"show c CLMIB_TPOK\"" + strs = os.popen(cmd) + line = strs.read() + if re.search(r"failed", line): + showc = "CDMIB_TPKT" + else : + showc = "CLMIB_TPKT" + cmd = "bcmcmd \"show c %s.%s\"" % (showc, self.bcm_ports[port - 1]) + strs = os.popen(cmd) + lines = strs.readlines() + if(lines[1].strip()): + if(count == int(re.sub('[,]', '', lines[1].split()[2].strip("+-")))): + return True, lines[1].split()[2] + else: + return False, lines[1].split()[2] + elif(direc == "rx"): + cmd = "bcmcmd \"show c CLMIB_RPOK\"" + strs = os.popen(cmd) + line = strs.read() + if re.search(r"failed", line): + showc = "CDMIB_RPKT" + else : + showc = "CLMIB_RPKT" + logging.debug(self.bcm_ports[port - 1]) + cmd = "bcmcmd \"show c %s.%s\"" % (showc, self.bcm_ports[port - 1]) + strs = os.popen(cmd) + lines = strs.readlines() + # logging.debug(lines) + if(lines[1].strip()): + if (count == int(re.sub('[,]', '', lines[1].split()[2].strip("+-")))): + return True, lines[1].split()[2] + else: + return False, lines[1].split()[2] + return False, "fail" + + + ################################################################################################ + + + def get_port_status(self, port): + if(self.__mode == 0): + return self.__get_port_status_by_sdk(port) + elif(self.__mode == 1): + return self.__get_port_status_by_sonic(port) + + + def get_port_fcs_status(self, port): + tfcs = 0 + rfcs = 0 + cmd = "bcmcmd \"show c CLMIB_TPOK\"" + strs = os.popen(cmd) + line = strs.read() + if re.search(r"failed", line): + showc = "CDMIB_TFCS" + else : + showc = "CLMIB_TFCS" + cmd = "bcmcmd \"show c %s.%s\"" % (showc, self.bcm_ports[port - 1]) + strs = os.popen(cmd) + lines = strs.readlines() + if lines[1].strip(): + tfcs = int(re.sub('[,]', '', lines[1].split()[2])) + cmd = "bcmcmd \"show c CLMIB_RPOK\"" + strs = os.popen(cmd) + line = strs.read() + if re.search(r"failed", line): + showc = "CDMIB_RFCS" + else : + showc = "CLMIB_RFCS" + cmd = "bcmcmd \"show c %s.%s\"" % (showc, self.bcm_ports[port - 1]) + strs = os.popen(cmd) + lines = strs.readlines() + if lines[1].strip(): + rfcs = int(re.sub('[,]', '', lines[1].split()[2])) + if(tfcs == 0 and rfcs == 0): + return True, (tfcs, rfcs) + return False, (tfcs, rfcs) + + + def start_send_port_packets(self, port, count, size=64, dst_mac="ff:ff:ff:ff:ff:ff"): + if(self.__mode == 0): + return self.__start_send_port_packets_by_sdk(port, count, size, dst_mac) + elif(self.__mode == 1): + return self.__start_send_port_packets_by_sonic(port, count, size, dst_mac) + return False, "fail" + + + def stop_send_port_packets(self): + cmd = "bcmcmd \"port xe,ce en=0\"" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + time.sleep(2) + cmd = "bcmcmd \"port xe,ce en=1\"" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def clear_port_packets(self): + if(self.__mode == 0): + return self.__clear_port_packets_by_sdk() + elif(self.__mode == 1): + return self.__clear_port_packets_by_sonic() + return False, "fail" + + + def check_port_packets(self, port, count, direc = "tx"): + if(self.__mode == 0): + return self.__check_port_packets_by_sdk(port, count, direc) + elif(self.__mode == 1): + return self.__check_port_packets_by_sonic(port, count, direc) + return False, "fail" + + + def init_port_cpu(self): + cmd = "bcmcmd \"cint /usr/share/sonic/platform/cpu.cint\"" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def reset_port_cpu(self): + cmd = "bcmcmd \"cint;\r\n bcm_field_entry_destroy(0, 2048);\r\n bcm_field_group_destroy(0, 5);\r\n exit;\"" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def init_port_prbs(self): + cmd = "bcmcmd \"cint /usr/share/sonic/platform/prbs.cint\"" + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def reset_port_prbs(self): + time.sleep(1) + + + def set_port_prbs(self, port, enable): + unit_port = self.__get_unit_port_by_bcm(port) + cmd = "bcmcmd \"cint;\r\n set_port_prbs(%d, %d);\r\n exit;\"" % (unit_port, enable) + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def get_port_prbs_result(self, port): + unit_port = self.__get_unit_port_by_bcm(port) + cmd = "bcmcmd \"cint;\r\n print get_port_prbs_result(%d);\r\n exit;\"" % unit_port + strs = os.popen(cmd) + time.sleep(1) + cmd = "bcmcmd \"cint;\r\n print get_port_prbs_result(%d);\r\n exit;\"" % unit_port + strs = os.popen(cmd) + lines = strs.readlines() + status = int(re.findall(" = (.*?) ",lines[-5])[0]) + return status + + + def test(self): + circle = 0 + while True: + print("circle %d:" % (circle + 1)) + self.init_port_cpu() + self.clear_port_packets() + for i in range(len(self.bcm_ports)): + self.start_send_port_packets(i + 1, 10000, 1000) + time.sleep(5) + for i in range(len(self.bcm_ports)): + if(self.check_port_packets(i + 1, 10000, "rx")): + print("port %d is ok" % (i + 1)) + else: + print ("error:%d" % (i + 1)) + self.reset_port_cpu() + circle += 1 + +class PortPrbsTest(object): + mac_output = [] + sys_output = [] + line_output = [] + bcm_ports = [] + standard = 0 + + def __init__(self, standard = 1.0e-10): + self.standard = standard + self.__get_global_bcmports() + + + def __get_global_bcmports(self): + if(len(self.bcm_ports)): + pass + else: + pu = portutil.PortUtil() + cmd = "bcmcmd ps" + strs = os.popen(cmd) + lines = strs.readlines() + for port in pu.device_port_list: + for line in lines: + line.strip() + if re.search(r"^.*?\(.*?\)", line) and int(re.findall(r"^.*?\((.*?)\)", line)[0].strip()) == port.logic_port: + self.bcm_ports.append(re.findall("^(.*?)\(.*?\)", line)[0].strip()) + break + + + def _get_mac_side_prbsstat_ber(self, port): + results = [] + i = 0 + for line in self.mac_output: + if ((self.bcm_ports[port - 1] + "[0]") in line) or ((self.bcm_ports[port - 1] + "[1]") in line): + results.append(line) + i = i + 1 + for result in results: + i = i - 1 + ex = "[0-9]{0,}[.][0-9]{0,}[e][+][0-9]{0,}|[0-9]{0,}[.][0-9]{0,}[e][-][0-9]{0,}" + ber = (re.search(ex,result)) + if (ber != None): + if (float(ber.group()) > float(self.standard)): + return False, results + elif(i == 0): + return True, results + return False, results + + + def _get_sys_side_prbsstat_ber(self, port): + results = [] + icount = 2 + ex = "[0-9]+$" + num = (re.search(ex, self.bcm_ports[port - 1])).group() + num = int(num) * 2 + 1 + results.append(self.sys_output[num]) + results.append(self.sys_output[num+1]) + for result in results: + icount = icount - 1 + ex = "[0-9]{0,}[.][0-9]{0,}[e][+][0-9]{0,}|[0-9]{0,}[.][0-9]{0,}[e][-][0-9]{0,}" + ber = re.search(ex, result) + if(ber != None): + if(float(ber.group()) > float(self.standard)): + return False, results + elif(icount == 0): + return True, results + return False, results + + + def _get_line_side_prbsstat_ber(self, port): + results = [] + icount = 4 + ex = "[0-9]+$" + num = (re.search(ex, self.bcm_ports[port - 1])).group() + num = int(num) * 4 + 1 + results.append(self.line_output[num]) + results.append(self.line_output[num + 1]) + results.append(self.line_output[num + 2]) + results.append(self.line_output[num + 3]) + for result in results: + icount = icount - 1 + ex = "[0-9]{0,}[.][0-9]{0,}[e][+][0-9]{0,}|[0-9]{0,}[.][0-9]{0,}[e][-][0-9]{0,}" + ber = re.search(ex, result) + if(ber != None): + if(float(ber.group()) > float(self.standard)): + return False, results + elif(icount == 0): + return True, results + return False, results + + + def init_port_prbs(self): + cmd = 'bcmcmd "phy diag ce prbs set p=3"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy control ce prbs lnside=1 p=5"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy control ce prbs lnside=0 p=5"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy diag ce prbs get"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy diag ce prbs get"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy diag ce prbsstat start i=120"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy control ce prbs lnside=1"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy control ce prbs lnside=0"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + time.sleep(120) + cmd = 'bcmcmd "phy control ce prbs lnside=1 time=120 cal=1"' + ret, output = subprocess.getstatusoutput(cmd) + self.sys_output = output.split("\r\n") + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy control ce prbs lnside=0 time=120 cal=1"' + ret, output = subprocess.getstatusoutput(cmd) + self.line_output = output.split("\r\n") + if(ret != 0): + return False, output + time.sleep(30) + cmd = 'bcmcmd "phy diag ce prbsstat ber"' + ret, output = subprocess.getstatusoutput(cmd) + self.mac_output = output.split("\r\n") + if(ret != 0): + return False, output + return True, output + + + def clear_port_prbs(self): + cmd = 'bcmcmd "phy diag ce prbs clear"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy control ce prbs lnside=1 clear=1"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = 'bcmcmd "phy control ce prbs lnside=0 clear=1"' + ret, output = subprocess.getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + + def get_port_prbs_result(self, flag, port): + if (flag == "mac"): + ret, output = self._get_mac_side_prbsstat_ber(port) + return ret,output + elif (flag == "sys"): + ret, output = self._get_sys_side_prbsstat_ber(port) + return ret, output + elif (flag == "line"): + ret, output = self._get_line_side_prbsstat_ber(port) + return ret, output + else: + return False, "fail" + +###################### HSDK Class ###################### + +class PortHsdkClass(): + '''PortHsdkClass is used to store aliases and related information of ports at different levels''' + + def __init__(self, **kwargs): + + lport = kwargs.get("lport", 0) + bcm_port = kwargs.get("bcm_port", "") + interface = kwargs.get("interface", "") + unit_port = kwargs.get("unit_port", 0) + phy_port = kwargs.get("phy_port", 0) + + self._lport = lport + self._interface = interface + self._bcm_port = bcm_port + self._unit_port = unit_port + self._phy_port = phy_port + + @property + def lport(self): + '''return lport''' + + return self._lport + + @property + def interface(self): + '''return interface''' + + return self._interface + + @property + def bcm_port(self): + '''return bcm_port''' + + return self._bcm_port + + @property + def unit_port(self): + '''return unit_port''' + + return self._unit_port + + @property + def phy_port(self): + '''return phy_port''' + + return self._phy_port + + def set_lport(self, lport): + '''set lport''' + + self._lport = lport + + def set_interface(self, interface): + '''set interface''' + + self._interface = interface + + def set_bcm_port(self, bcm_port): + '''set bcm_port''' + + self._bcm_port = bcm_port + + def set_unit_port(self, unit_port): + '''set unit_port''' + + self._unit_port = unit_port + + def set_phy_port(self, phy_port): + '''set phy_port''' + + self._phy_port = phy_port + +class PortHsdkUtil(): + '''Port utility class''' + + @staticmethod + def get_config_bcm_path(): + '''return config_bcm address''' + + config_bcm_path = "" + try: + (platform, hwsku) = get_platform_and_hwsku() + platform_path = "/".join([PLATFORM_ROOT_PATH, platform]) + hwsku_path = "/".join([platform_path, hwsku]) + saiprofile_path = "/".join([hwsku_path, SAI_PROFILE]) + with open(saiprofile_path, "r") as saiprofile_f: + for line in saiprofile_f: + if re.search('%s(.*?)$' % SAI_PROFILE_PREDIX, line): + config_bcm = re.findall(r"%s(.*?)$" % SAI_PROFILE_PREDIX, line)[0] + config_bcm_path = "/".join([hwsku_path, config_bcm]) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + + return config_bcm_path + + @staticmethod + def get_port_config_path(): + '''return port_config address''' + + port_config_path = get_path_to_port_config_file() + return port_config_path + + @staticmethod + def get_onie_platform(): + '''get onie_platform''' + + log_debug("获取onie_platform") + with open(MACHINE_FILE, "r") as machine_f: + for line in machine_f: + if(re.search('%s(.*?)$' % MACHINE_PLATFORM_PREDIX, line)): + onie_platform = re.findall(r"%s(.*?)$" % MACHINE_PLATFORM_PREDIX, line)[0] + global global_onie_platform + global_onie_platform = onie_platform + log_debug("onie_platform:%s" % global_onie_platform) + return onie_platform + return None + + class ReUtil(): + '''regular utility class''' + + @staticmethod + def is_port_id_line(line): + '''determine whether port_id line''' + + if re.search('_PORT_ID:(.*?)$', line.strip()): + return False + elif re.search('PORT_ID: \[', line.strip()): + return False + elif re.search('PORT_ID:(.*?)$', line.strip()): + return True + return False + + @staticmethod + def is_pc_phys_port_id_line(line): + '''determine whether pc_phys_phy_port_id line''' + + if re.search('PC_PHYS_PORT_ID:(.*?)$', line.strip()): + return True + return False + + @staticmethod + def yaml_getre_unit_port(line): + return int(re.findall(r"PORT_ID:(.*?)$", line.strip())[0]) + + @staticmethod + def yaml_getre_phy_port(line): + return int(re.findall(r"PC_PHYS_PORT_ID:(.*?)$", line.strip())[0]) + + @staticmethod + def getre_port_status(output): + '''parse the return result,get port up/down status''' + lines = output.split("\n") + + if len(lines) > 3: + if re.search("up", lines[3]): + return True, "up" + elif re.search("!ena", lines[3]): + return True, "!ena" + elif re.search("down", lines[3]): + return True, "down" + else: + return False, output + else: + return False, output + + @staticmethod + def is_unit_port_line(line, unit_port): + '''determine whether save unit_port line''' + + if (re.search(r"^.*?\(.*?\)", line) and + int(re.findall(r"^.*?\((.*?)\)", line)[0].strip()) == unit_port): + return True + return False + + @staticmethod + def getre_output_bcm_port(output): + '''parse the return result,get bcm_port/mgmt_bcm_port''' + + return re.findall(r"^(.*?)\(.*?\)", output)[0].strip() + + @staticmethod + def getre_output_packets_count(line): + '''parse the return result,get the number of received/sent packets''' + if (len(line.split())) > 2: + return int(re.sub('[,]', '', line.split()[2].strip("+-"))) + else: + return 0 + + @staticmethod + def getre_output_unit_port(output): + '''parse the return result,get unit_port''' + + return int((output.split(')')[0]).split('(')[1]) + + @staticmethod + def getre_output_speed(line): + '''parse the return result,get speed''' + + if (len(line.split())) > 4: + speed = (line.split("FD"))[0].split()[-1] + if "G" in speed: + return speed + return None + +class PortHsdkTest(): + '''PortHsdkTest parent class''' + + device_port_list = [] + bcm_ports = [] + prbs_port_range = None + standard_ber_val = None + prbs_time = None + + def __init__(self): + if global_onie_platform == "": + PortHsdkUtil.get_onie_platform() + self.get_factest_port_config() + if len(self.device_port_list) == 0: + self._config_yaml_file = io.open(PortHsdkUtil.get_config_bcm_path(), 'r', encoding="utf-8") + self._port_config_file = open(PortHsdkUtil.get_port_config_path(), 'r+') + self.__parse_port_config() + self.__parse_yaml_data() + self.__get_global_bcmports() + self._config_yaml_file.flush() + self._port_config_file.flush() + self._config_yaml_file.close() + self._port_config_file.close() + if self.prbs_time is None: + self.prbs_time = global_port_config.get("prbs_time", PRBS_TIME_DEFAULT) + if self.standard_ber_val is None: + self.standard_ber_val = global_port_config.get("prbs_ber", PRBS_BER_DEFAULT) + + @abc.abstractmethod + def init_test(self): + '''abstract method, to be inherited''' + + return None + + @abc.abstractmethod + def start_test(self, **kwargs): + '''abstract method, to be inherited''' + + return None + + @abc.abstractmethod + def check_test(self, **kwargs): + '''abstract method, to be inherited''' + + return None + + @abc.abstractmethod + def del_test(self): + '''abstract method, to be inherited''' + + return None + + def __parse_port_config(self): + '''parse port_config, get lport, interface, phy_port''' + + log_debug("解析port_config") + lport_num = 0 + for line in self._port_config_file: + line.strip() + if len(line.split()) > 0 and re.search("Eth", line.split()[0]): + lport_num = lport_num + 1 + phy_port_t = int(line.split()[1].split(',')[0]) + self.device_port_list.append(PortHsdkClass(lport=lport_num, + interface=line.split()[0], + phy_port=phy_port_t)) + + def __parse_yaml_data(self): + '''parse yaml port_id,phy_port_id of line configuration ''' + + log_debug("解析yaml") + unit_port = 0 + phy_port = 0 + curr_line_num = 0 + port_id_line = 0 + phy_port_id_line = 0 + reutil = PortHsdkUtil.ReUtil() + for line in self._config_yaml_file: + curr_line_num = curr_line_num + 1 + if reutil.is_port_id_line(line): + port_id_line = curr_line_num + unit_port = reutil.yaml_getre_unit_port(line) + if (curr_line_num == (port_id_line + 2)): + if reutil.is_pc_phys_port_id_line(line): + phy_port_id_line = curr_line_num + phy_port = reutil.yaml_getre_phy_port(line) + for port_obj in self.device_port_list: + if port_obj.phy_port == phy_port: + port_obj.set_unit_port(unit_port) + break + + def __get_global_bcmports(self): + '''get ps returns the result bcm_port, unit_port part''' + + cmd = get_sdk_cmd("ps") + ret, output = port_getstatusoutput(cmd) + lines = output.split("\n") + if ret == 0: + for line in lines: + if (re.search('(.*?)\((.*?)$', line.strip())): + unit_port = PortHsdkUtil.ReUtil.getre_output_unit_port(line) + bcm_port = PortHsdkUtil.ReUtil.getre_output_bcm_port(line) + for port_obj in self.device_port_list: + if port_obj.unit_port == unit_port: + port_obj.set_bcm_port(bcm_port) + break + for port_obj in self.device_port_list: + self.bcm_ports.append(str(port_obj.bcm_port)) + log_debug("bcm_ports:%s" % self.bcm_ports) + + def get_port_status(self, port): + '''get port up/down status, return up/down/!ena''' + + # get bcm_port + cmd = get_sdk_cmd("ps %s" % self.device_port_list[port - 1].bcm_port) + ret, output = port_getstatusoutput(cmd) + + if ret == 0: + return PortHsdkUtil.ReUtil.getre_port_status(output) + return False, output + + @classmethod + def clear_port_packets(cls): + '''clear SDK statistical message''' + + # use SDK command clear port_packets + # clear statistical message + cmd = get_sdk_cmd("clear c") + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + + log_debug("clear_port_packets success") + return True, output + + def start_send_port_packets(self, port, count, size, dst_mac): + '''use SDK command to send packets''' + + # ues tx Order contract + cmd = get_sdk_cmd("tx %d VLantag=4048 PortBitMap=%s Length=%d DestMac=%s" + % (count, self.device_port_list[port - 1].bcm_port, size, dst_mac)) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + return True, output + + def vlan_config(self, vlan): + '''test vlan configuration''' + + # Clear the previously configured vlan + ret, output = self.vlan_config_clear() + if ret is False: + log_warning("vlan_config fail, output:%s" % output) + return False, "vlan_config fail, output:%s" % output + + # Configure vlans for all ports + for i in range(len(self.device_port_list)): + bcm_port = self.device_port_list[i].bcm_port + if i == 0: + # set vlan,the first port create, And then add + cmd = get_sdk_cmd("vlan create %d PortBitMap=%s UntagBitMap=%s" % (vlan, + bcm_port, + bcm_port)) + else: + cmd = get_sdk_cmd("vlan add %d PortBitMap=%s UntagBitMap=%s" % (vlan, + bcm_port, + bcm_port)) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + log_warning("vlan_config vlan create or add fail, output:%s" % output) + return False, "vlan_config vlan create or add fail, output:%s" % output + + # set pvlan + cmd = get_sdk_cmd("pvlan set %s %d" % (bcm_port, vlan)) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + log_warning("vlan_config pvlan set fail, output:%s" % output) + return False, "vlan_config pvlan set fail, output:%s" % output + + log_debug("vlan_config success") + return True, "vlan_config success" + + @classmethod + def vlan_config_clear(cls): + '''ports test vlan environmental restoration''' + + cmd = get_sdk_cmd("vlan clear") + ret, output = port_getstatusoutput(cmd) + if ret != 0: + log_warning("vlan_config_clear fail, output:%s" % output) + return False, "vlan_config_clear fail, output:%s" % output + + log_debug("vlan_config_clear success") + return True, "vlan_config_clear success" + + def get_mgmt_bcmport(self, mgmt_eth): + '''get mgmt bcmport''' + + cmd = get_sdk_cmd("ps") + ret, output = port_getstatusoutput(cmd) + lines = output.split("\n") + if ret == 0: + unit_port = global_port_config["mgmt_kt_ports"][mgmt_eth] + for line in lines: + line.strip() + if PortHsdkUtil.ReUtil.is_unit_port_line(line, unit_port): + bcmport = PortHsdkUtil.ReUtil.getre_output_bcm_port(line) + log_debug("%s : %s" % (mgmt_eth, bcmport)) + return bcmport + return None + + def set_all_mgmt_enable(self, enable): + '''control all mgmt enable''' + + # perform operations on all internal management ports,set en=0/1 + # enable = 1 up down + # enable = 0 !ena + cmd = None + try: + cmd = get_sdk_cmd("port %s en=%d" % (",".join(self.get_mgmt_bcmport(item) + for item + in global_port_config["mgmt_kt_ports"]), enable)) + except Exception as except_result: + msg = traceback.format_exc() + log_error("Exception_info:\n%s" % msg) + return False, "set_all_mgmt_enable:%d fail, output:%s" % (enable, msg) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + log_warning("set_all_mgmt_enable:%d fail, output:%s" % (enable, output)) + return False, "set_all_mgmt_enable:%d fail, output:%s" % (enable, output) + + log_debug("set_all_mgmt_enable:%d success" % enable) + return True, "set_all_mgmt_enable:%d success" % enable + + def port_stp_config(self, enable): + '''Spanning tree protocol configuration''' + + if enable == 1: + log_debug("开启STP") + cmd = get_sdk_cmd("stg stp 1 all forward") + ret, output = port_getstatusoutput(cmd) + if ret == 0: + # turn off spanning tree protocol of the internal management interface + cmd = get_sdk_cmd("stg stp 1 %s disable" % (",".join(self.get_mgmt_bcmport(item) + for item + in global_port_config["mgmt_kt_ports"]))) + ret, output = port_getstatusoutput(cmd) + else: + log_debug("关闭STP") + cmd = get_sdk_cmd("stg stp 1 all disable") + ret, output = port_getstatusoutput(cmd) + + if ret != 0: + return False, "port_stp_config fail, output:%s" % output + return True, "port_stp_config success" + + def get_unit_port_list(self, port_list): + '''get up port unit_port list''' + + self.set_global_unit_port_list_null() + for port in port_list: + unit_port = self.device_port_list[port - 1].unit_port + global global_unit_port_list + global_unit_port_list.append(unit_port) + log_debug("unit_port_list:%s" % global_unit_port_list) + + @classmethod + def get_min_max_unit_port(cls): + '''get unit_port Smallest and largest in the list''' + + min_unit_port = 1 + max_unit_port = 1 + if len(global_unit_port_list) > 0: + min_unit_port = int(min(global_unit_port_list)) + max_unit_port = int(max(global_unit_port_list)) + log_debug("min_unit_port = %d max_unit_port = %d" % (min_unit_port, max_unit_port)) + return min_unit_port, max_unit_port + + def get_prbs_port_range(self): + '''obtain panel port unit_port range(exclusive mgmt port and loopback port)''' + + self.prbs_port_range = global_port_config.get("prbs_port_range", None) + if self.prbs_port_range is None: + min_unit_port, max_unit_port = self.get_min_max_unit_port() + self.prbs_port_range = "%s-%s" % (str(min_unit_port), str(max_unit_port)) + + @classmethod + def set_global_unit_port_list_null(cls): + global global_unit_port_list + global_unit_port_list = [] + + def get_factest_port_config_flag(self): + return global_port_config["flag"] + + def get_factest_port_config(self): + if self.get_factest_port_config_flag() is False: + port_config = { + "hsdk_device" : 1, + "mgmt_kt_ports" : {}, + "prbs_port_range" : "", + "extphy_device" : 0, + "prbs_ber" : PRBS_BER_DEFAULT, + "prbs_time" : PRBS_TIME_DEFAULT, + "port_frame_test_retrynum": 1,# Number of frame retries (internal retries) + "port_brcst_test_retrynum": 1,# Number of port broadcast test retries (internal retries) + "port_prbs_test_retrynum": 1,# Number of port PRBS test retries (internal retries) + "port_kr_test_retrynum": 1,# Internal management port Test Retry count (Internal retry) + "port_frame_del_time": 10,# Waiting time of recovering the test environment from sending and receiving frames on the port (s) + "port_brcst_del_time": 10,# Port Broadcast Test Recovery Test environment Waiting time (s) + "port_prbs_del_time": 10,# Port PRBS Test Recovery Test environment Waiting time (s) + "port_kr_del_time": 10,# Internal management interface Test Recovery Test environment Waiting time (s) + "port_log_level": LOG_ERROR_LEVEL,# PORT component log level + "flag" : False + } + try: + port_config["mgmt_kt_ports"] = copy.deepcopy(global_mgmt_kr_ports[global_onie_platform]) + log_debug("mgmt_kt_ports: %s" % port_config["mgmt_kt_ports"]) + + port_config["prbs_port_range"] = global_prbs_port_range.get(global_onie_platform, None) + log_debug("prbs_port_range: %s" % port_config["prbs_port_range"]) + + port_config["hsdk_device"] = global_hsdk_device.get(global_onie_platform, 0) + log_debug("hsdk_device: %s" % port_config["hsdk_device"]) + + port_config["extphy_device"] = global_extphy_device.get(global_onie_platform, 0) + log_debug("extphy_device: %s" % port_config["extphy_device"]) + + port_config["prbs_ber"] = global_prbs_ber.get(global_onie_platform, PRBS_BER_DEFAULT) + log_debug("prbs_ber: %s" % port_config["prbs_ber"]) + + port_config["prbs_time"] = global_prbs_time.get(global_onie_platform, PRBS_TIME_DEFAULT) + log_debug("prbs_time: %s" % port_config["prbs_time"]) + + port_config["port_frame_test_retrynum"] = PORT_FACTEST_CONFIG["port_frame_test_retrynum"] + log_debug("port_frame_test_retrynum: %s" % port_config["port_frame_test_retrynum"]) + + port_config["port_brcst_test_retrynum"] = PORT_FACTEST_CONFIG["port_brcst_test_retrynum"] + log_debug("port_brcst_test_retrynum: %s" % port_config["port_brcst_test_retrynum"]) + + port_config["port_prbs_test_retrynum"] = PORT_FACTEST_CONFIG["port_prbs_test_retrynum"] + log_debug("port_prbs_test_retrynum: %s" % port_config["port_prbs_test_retrynum"]) + + port_config["port_kr_test_retrynum"] = PORT_FACTEST_CONFIG["port_kr_test_retrynum"] + log_debug("port_kr_test_retrynum: %s" % port_config["port_kr_test_retrynum"]) + + port_config["port_frame_del_time"] = PORT_FACTEST_CONFIG["port_frame_del_time"] + log_debug("port_frame_del_time: %s" % port_config["port_frame_del_time"]) + + port_config["port_brcst_del_time"] = PORT_FACTEST_CONFIG["port_brcst_del_time"] + log_debug("port_brcst_del_time: %s" % port_config["port_brcst_del_time"]) + + port_config["port_prbs_del_time"] = PORT_FACTEST_CONFIG["port_prbs_del_time"] + log_debug("port_prbs_del_time: %s" % port_config["port_prbs_del_time"]) + + port_config["port_kr_del_time"] = PORT_FACTEST_CONFIG["port_kr_del_time"] + log_debug("port_kr_del_time: %s" % port_config["port_kr_del_time"]) + + port_config["port_log_level"] = PORT_FACTEST_CONFIG["port_log_level"] + log_debug("port_log_level: %s" % port_config["port_log_level"]) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + + port_config["flag"] = True + global global_port_config + global_port_config = copy.deepcopy(port_config) + log_debug("global_port_config: %s" % global_port_config) + +@singleton +class PortHsdkFrameTest(PortHsdkTest): + '''port frame''' + + def init_test(self): + '''port frame init test''' + + log_debug("init_test") + ret, output = self.clear_port_packets() + if ret is False: + log_error("clear_port_packets fail, output:%s" % output) + return False, "clear_port_packets fail, output:%s" % output + + ret, output = self.cpu_create() + if ret is False: + log_error("cpu_create fail, output:%s" % output) + return False, "cpu_create fail, output:%s" % output + + ret, output = self.port_stp_config(1) + if ret is False: + log_error("port_stp_config fail, output:%s" % output) + return False, "port_stp_config fail, output:%s" % output + + ret, output = self.vlan_config(PORT_TEST_VLAN) + if ret is False: + log_error("vlan_config fail, output:%s" % output) + return False, "vlan_config fail, output:%s" % output + + log_debug("init_test success") + return True, "init_test success" + + def start_test(self, **kwargs): + '''port frame start test''' + + port = kwargs["port"] + count = kwargs.get("count", PACKETS_COUNT) + size = kwargs.get("size", PACKETS_SIZE) + dst_mac = kwargs.get("dst_mac", PACKETS_DST_MAC) + + log_debug("start_test") + return self.start_send_port_packets(port, count, size, dst_mac) + + def check_test(self, **kwargs): + '''port frame check test''' + + port = kwargs["port"] + count = kwargs.get("count", PACKETS_COUNT) + direc = kwargs.get("direc", "tx") + + log_debug("check_test") + return self.check_port_packets(port, count, direc) + + def del_test(self): + '''port frame test environment recover''' + + log_debug("del_test") + ret, output = self.vlan_config_clear() + if ret is False: + log_error("vlan_config_clear fail, output:%s" % output) + return False, output + + ret, output = self.cpu_destroy() + if ret is False: + log_error("cpu_destroy fail,%s" % output) + return False, "cpu_destroy fail,%s" % output + + ret, output = self.port_stp_config(0) + if ret is False: + log_error("port_stp_config fail, output:%s" % output) + return False, output + + log_debug("del_test success") + return True, "cpu_destroy success" + + def check_port_packets(self, port, count, direc="tx"): + '''check port frame test result ''' + # Obtain the statistics result of a specific port,If the port receives the same number as it sends. + # return port succeeded. Otherwise, the port failed and the failure cause are displayed. + + if direc == "tx": + return self.check_port_packets_tx(port, count) + if direc == "rx": + return self.check_port_packets_rx(port, count) + + return False, "check_port_packets_fail" + + def check_port_packets_tx(self, port, count): + '''direc == "tx"''' + + # View statistics on sent and received packets + count_pkt = 0 + count_1518 = 0 + result_str = "" + bcm_port = self.device_port_list[port - 1].bcm_port + log_debug("bcm_port:%s direc:tx" % bcm_port) + + cmd = get_sdk_cmd("show c %s" % bcm_port) + ret, output = port_getstatusoutput(cmd) + lines = output.split("\n") + if ret == 0: + for line in lines: + if (re.search('XLMIB_TPKT(.*?)$', line.strip())): + count_pkt = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + elif (re.search('XLMIB_T1518(.*?)$', line.strip())): + count_1518 = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + else: + return False, output + + log_debug("count:%d" % count) + log_debug("count_pkt:%d" % count_pkt) + log_debug("count_1518:%d" % count_1518) + result_str += "count:%d\n" % count + result_str += "count_pkt:%d\n" % count_pkt + result_str += "count_1518:%d\n" % count_1518 + + if (count_pkt == 0 or count_1518 == 0): + result_str += "output:%s\n" % output + log_warning("output:%s" % output) + if (count == count_pkt and count == count_1518): + log_debug("check_port_packets tx success") + return True, result_str + + log_warning("check_port_packets_tx_fail, output:%s" % output) + return False, result_str + + def check_port_packets_rx(self, port, count): + '''direc == "rx"''' + + # View statistics on sent and received packets + count_pkt = 0 + count_1518 = 0 + result_str = "" + bcm_port = self.device_port_list[port - 1].bcm_port + log_debug("bcm_port:%s direc:rx" % bcm_port) + + cmd = get_sdk_cmd("show c %s" % bcm_port) + ret, output = port_getstatusoutput(cmd) + if ret == 0: + lines = output.split("\n") + for line in lines: + if (re.search('XLMIB_RPKT(.*?)$', line.strip())): + count_pkt = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + elif (re.search('XLMIB_R1518(.*?)$', line.strip())): + count_1518 = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + else: + return False, output + + log_debug("count:%d" % count) + log_debug("count_pkt:%d" % count_pkt) + log_debug("count_1518:%d" % count_1518) + result_str += "count:%d\n" % count + result_str += "count_pkt:%d\n" % count_pkt + result_str += "count_1518:%d\n" % count_1518 + + if (count_pkt == 0 or count_1518 == 0): + result_str += "output:%s\n" % output + log_warning("output:%s" % output) + if (count == count_pkt and count == count_1518): + log_debug("check_port_packets rx success") + return True, result_str + + log_warning("check_port_packets_rx_fail, output:%s" % output) + return False, result_str + + def cpu_create(self): + '''use cpu_create.cint''' + + cmd = get_sdk_cmd("cint /usr/share/sonic/device/%s/cpu_create.cint" % global_onie_platform) + ret, output = port_getstatusoutput(cmd) + if(ret != 0): + return False, output + + log_debug("cpu_create success") + return True, output + + def cpu_destroy(self): + '''use cpu_destroy.cint''' + + cmd = get_sdk_cmd("cint /usr/share/sonic/device/%s/cpu_destroy.cint" % global_onie_platform) + ret, output = port_getstatusoutput(cmd) + if(ret != 0): + return False, output + + log_debug("cpu_destroy success") + return True, output + +@singleton +class PortHsdkBrcstTest(PortHsdkTest): + '''port radio''' + + def init_test(self): + '''port radio init test''' + + ret, output = self.clear_port_packets() + if ret is False: + log_error("clear_port_packets fail, output:%s" % output) + return False, "clear_port_packets fail, output:%s" % output + + ret, output = self.port_stp_config(1) + if ret is False: + log_error("port_stp_config fail, output:%s" % output) + return False, "port_stp_config fail, output:%s" % output + + ret, output = self.vlan_config(PORT_TEST_VLAN) + if ret is False: + log_error("vlan_config fail, output:%s" % output) + return False, "vlan_config fail, output:%s" % output + + log_debug("init_test success") + return True, "init_test success" + + def start_test(self, **kwargs): + '''port radio start test''' + + port = kwargs["port"] + count = kwargs["count"] + size = kwargs.get("size", PACKETS_SIZE) + dst_mac = kwargs.get("dst_mac", PACKETS_DST_MAC) + + log_debug("start_test") + return self.start_send_port_packets(port, count, size, dst_mac) + + def check_test(self, **kwargs): + '''check port radio test results''' + + port = kwargs["port"] + + log_debug("check_test") + return self.get_port_fcs_status(port) + + def del_test(self): + '''port radio test test environment recover''' + + log_debug("del_test") + ret, output = self.vlan_config_clear() + if ret is False: + log_error("vlan_config_clear fail, output:%s" % output) + return False, output + + ret, output = self.stop_send_port_packets() + if ret is False: + log_error("stop_send_port_packets fail, output:%s" % output) + return False, output + + ret, output = self.port_stp_config(0) + if ret is False: + log_error("port_stp_config fail, output:%s" % output) + return False, output + + return True, "del_test success" + + def get_port_fcs_status(self, port): + '''check the port broadcast test result''' + + tfcs = 0 + rfcs = 0 + result_str = "" + # View statistics on sent and received packets + bcm_port = self.device_port_list[port - 1].bcm_port + cmd = get_sdk_cmd("show c %s" % bcm_port) + ret, output = port_getstatusoutput(cmd) + if ret == 0: + lines = output.split("\n") + for line in lines: + if (re.search('XLMIB_TFCS(.*?)$', line.strip())): + tfcs = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + log_warning("tfcs: %d" % tfcs) + elif (re.search('XLMIB_RFCS(.*?)$', line.strip())): + rfcs = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + log_warning("rfcs: %d" % rfcs) + + result_str += "tfcs:%d\n" % tfcs + result_str += "rfcs:%d\n" % rfcs + + if (tfcs == 0 and rfcs == 0): + ret, output = self.get_port_fcs_status_f(bcm_port, lines) + if ret is True: + return True, result_str + else: + result_str += output + return False, result_str + else: + return False, output + + def stop_send_port_packets(self): + '''The port broadcast test stopped sending packets''' + + # do xe,ce operate,set en=0/1 -> change to all + # enable = 1 up down + # enable = 0 !ena + cmd = get_sdk_cmd("port all en=0") + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + time.sleep(5) + + cmd = get_sdk_cmd("port all en=1") + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + + ret, output = self.set_all_mgmt_enable(0) + if ret is False: + log_error("stop_send_port_packets fail, output:%s" % output) + return False, "stop_send_port_packets fail, output:%s" % output + + time.sleep(5) + + log_debug("stop_send_port_packets success") + return True, "stop_send_port_packets success" + + def get_port_fcs_status_f(self, bcm_port, lines): + '''Check the port broadcast test result to check whether the port receives and sends packets''' + + tpkt = 0 + rpkt = 0 + # View statistics on sent and received packets + for line in lines: + if (re.search('XLMIB_TPKT(.*?)$', line.strip())): + tpkt = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + log_debug("%s tpkt: %d" % (bcm_port, tpkt)) + + elif (re.search('XLMIB_RPKT(.*?)$', line.strip())): + rpkt = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + log_debug("%s rpkt: %d" % (bcm_port, rpkt)) + + if tpkt > 0 and rpkt > 0: + log_debug("%s get_port_fcs_status_f success" % bcm_port) + return True, "%s get_port_fcs_status_f success" % bcm_port + else: + log_error("%s get_port_fcs_status_f fail, tpkt:%d rpkt:%d" % (bcm_port, rpkt, tpkt)) + return False, "%s get_port_fcs_status_f fail, tpkt:%d rpkt:%d" % (bcm_port, rpkt, tpkt) + +class PortHsdkPrbsTest(PortHsdkTest): + '''port PRBS parent class''' + + def init_test(self): + '''To inherit''' + + return None + + def start_test(self, **kwargs): + '''To inherit''' + + return None + + def check_test(self, **kwargs): + '''To inherit''' + + return None + + def del_test(self): + '''To inherit''' + + return None + +@singleton +class PortHsdkPrbsExtPhyTest(PortHsdkPrbsTest): + '''ExtPhy prbs''' + + def init_test(self): + '''port ExtPhy prbs init test''' + + log_debug("init_test") + return self.clear_port_prbs() + + def start_test(self, **kwargs): + '''port ExtPhy prbs start test''' + + test_type = kwargs["test_type"] + + log_debug("start_test") + return self.start_port_prbs(test_type) + + def check_test(self, **kwargs): + '''port ExtPhy prbs test result get''' + + test_type = kwargs["test_type"] + upports = kwargs["uprt"] + result_dict = kwargs["r_dict"] + + log_debug("check_test") + return self.get_port_prbs_ext_result(test_type=test_type, + uprt=upports, + r_dict=result_dict) + + def del_test(self): + ''' port ExtPhy prbs test environment recover''' + + log_debug("del_test") + return self.clear_port_prbs() + + def start_port_prbs(self, test_type): + '''ExtPhy prbs test result get''' + + if test_type == "prbs_mac": + return self.start_port_prbs_mac() + + if test_type == "prbs_sys": + return self.start_port_prbs_sys() + + if test_type == "prbs_line": + return self.start_port_prbs_line() + + log_warning("start_port_prbs fail, test_type=%s" % str(test_type)) + return False, "start_port_prbs fail, test_type=%s" % str(test_type) + + def start_port_prbs_mac(self): + '''start mac_sys port of prbs test,get mac port of prbs result''' + + # set mac port of PRBS,default configuration is PRBS31 + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbs set p=3'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, "start_port_prbs_mac fail %s" % output + + # set sys port of PRBS,default configuration is PRBS31 + cmd = get_sdk_cmd("dsh -c 'phy control %s setprbs lnside=1 p=5'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd, time_sleep=5) + if ret != 0: + return False, "start_port_prbs_mac fail %s" % output + + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbs get'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, "start_port_prbs_mac fail %s" % output + + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbsstat start interval=%d'" % (self.prbs_port_range, self.prbs_time)) + ret, output = port_getstatusoutput(cmd, time_sleep=(self.prbs_time + 10)) + if ret != 0: + return False, "start_port_prbs_mac fail %s" % output + + return True, "start_port_prbs_mac success" + + def start_port_prbs_sys(self): + '''start mac_sys port of prbs test,get sys port of prbs result''' + + # set mac pert of PRBS,default configuration is PRBS31 + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbs set p=3'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, "start_port_prbs_sys fail %s" % output + + # set sys port of PRBS,default configuration is PRBS31 + cmd = get_sdk_cmd("dsh -c 'phy control %s setprbs lnside=1 p=5'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd, time_sleep=5) + if ret != 0: + return False, "start_port_prbs_sys fail %s" % output + + # The newly packaged command to get PRBS test results contains get, so get is not needed here + + return True, "start_port_prbs_sys success" + + def start_port_prbs_line(self): + '''start line poart prbs test,get line port prbs result''' + + # set line port of PRBS,default configuration is PRBS31 + cmd = get_sdk_cmd("dsh -c 'phy control %s setprbs lnside=0 p=5'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd, time_sleep=5) + if ret != 0: + return False, "start_port_prbs_line fail %s" % output + + # The newly packaged command to get PRBS test results contains get, so get is not needed here + + return True, "start_port_prbs_line success" + + def get_port_prbs_ext_result(self, **kwargs): + '''ExtPhy prbs get test result''' + test_type = kwargs["test_type"] + upports = kwargs["uprt"] + result_dict = kwargs["r_dict"] + + if test_type == "prbs_mac": + return self.get_prbs_mac_result(upports, result_dict) + + if test_type == "prbs_sys": + return self.get_prbs_sys_result(upports, result_dict) + + if test_type == "prbs_line": + return self.get_prbs_line_result(upports, result_dict) + + log_warning("get_port_prbs_ext_result fail, test_type=%s" % str(test_type)) + return False, "get_port_prbs_ext_result fail, test_type=%s" % str(test_type) + + def get_prbs_mac_result(self, upports, result_dict): + '''get mac port prbsstat_ber''' + result_dict["successports"] = [] + result_dict["errorports"] = [] + + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbsstat ber'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + output + return False, result_dict + + lines = output.split("\n") + for port in upports: + prbs_ber_flag = 0 + prbs_ber_test_fail = 0 + output_content = "" + lport = self.device_port_list[port - 1].lport + unit_port = self.device_port_list[port - 1].unit_port + bcm_port = self.device_port_list[port - 1].bcm_port + output_content_port_info = "port:%-3d %s(%d)" % (lport, bcm_port, unit_port) + for line in lines: + if (re.search('.*].*e', line.strip())): + line_unit_port = int(line.split('[')[0]) + if unit_port == line_unit_port: + prbs_ber_flag = 1 + lane_num = int((line.split(']')[0]).split('[')[1]) + prbs_ber = line.split(' ')[-1] + if (float(prbs_ber) > float(self.standard_ber_val)): + prbs_ber_test_fail = 1 + output_content = output_content + "%-20s Lane[%d] prbs_ber:%s > %s, test fail\n" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val) + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + log_error("%-20s lane:%d, prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + else: + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + log_debug("%-20s lane:%d, prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + if prbs_ber_flag == 1 and prbs_ber_test_fail == 0: + result_dict["successports"].append(port) + elif prbs_ber_flag == 1 and prbs_ber_test_fail == 1: + result_dict["errorports"].append(port) + result_dict["port_info_dict"][port]["log"] = output_content + else: + result_dict["errorports"].append(port) + prbs_info_gather_fun("%-20s get prbs_ber fail, output:\n%s" % (output_content_port_info, output)) + result_dict["port_info_dict"][port]["log"] = "%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output) + log_error("%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output)) + prbs_info_gather_fun("") + + if len(result_dict["errorports"]) > 0: + return False, result_dict + return True, result_dict + + def get_prbs_sys_result(self, upports, result_dict): + '''Obtain the SYS prbsstat_ber''' + result_dict["successports"] = [] + result_dict["errorports"] = [] + + # The newly packaged command to get PRBS test results contains wait without additional wait + cmd = get_sdk_cmd("dsh -c 'phy control %s calprbs lnside=1 time=%d'" % (self.prbs_port_range, self.prbs_time), time_out=300, grep="] Ber") + ret, output = port_getstatusoutput(cmd) + if ret != 0: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + output + return False, result_dict + + lines = output.split("\n") + for port in upports: + prbs_ber_flag = 0 + prbs_ber_test_fail = 0 + output_content = "" + lport = self.device_port_list[port - 1].lport + unit_port = self.device_port_list[port - 1].unit_port + bcm_port = self.device_port_list[port - 1].bcm_port + output_content_port_info = "port:%-3d %s(%d)" % (lport, bcm_port, unit_port) + for line in lines: + if (re.search('.*] Ber', line.strip())): + line_unit_port = int((line.split('Lane')[0]).split('Port')[1]) + if unit_port == line_unit_port: + prbs_ber_flag = 1 + lane_num = int((line.split(']')[0]).split('[')[1]) + prbs_ber = line.split('Ber')[1] + if (float(prbs_ber) > float(self.standard_ber_val)): + prbs_ber_test_fail = 1 + output_content = output_content + "%-20s Lane[%d] prbs_ber:%s > %s, test fail\n" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val) + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + log_error("%-20s lane:%d, prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + else: + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + log_debug("%-20s lane:%d, prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + if prbs_ber_flag == 1 and prbs_ber_test_fail == 0: + result_dict["successports"].append(port) + elif prbs_ber_flag == 1 and prbs_ber_test_fail == 1: + result_dict["errorports"].append(port) + result_dict["port_info_dict"][port]["log"] = output_content + else: + result_dict["errorports"].append(port) + prbs_info_gather_fun("%-20s get prbs_ber fail, output:\n%s" % (output_content_port_info, output)) + result_dict["port_info_dict"][port]["log"] = "%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output) + log_error("%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output)) + prbs_info_gather_fun("") + + if len(result_dict["errorports"]) > 0: + return False, result_dict + return True, result_dict + + def get_prbs_line_result(self, upports, result_dict): + '''Get prbsstat_ber of the line end''' + result_dict["successports"] = [] + result_dict["errorports"] = [] + + # The newly packaged command to get PRBS test results contains wait without additional wait + cmd = get_sdk_cmd("dsh -c 'phy control %s calprbs lnside=0 time=%d'" % (self.prbs_port_range, self.prbs_time), time_out=300, grep="] Ber") + ret, output = port_getstatusoutput(cmd) + if ret != 0: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + output + return False, result_dict + + lines = output.split("\n") + for port in upports: + prbs_ber_flag = 0 + prbs_ber_test_fail = 0 + output_content = "" + lport = self.device_port_list[port - 1].lport + unit_port = self.device_port_list[port - 1].unit_port + bcm_port = self.device_port_list[port - 1].bcm_port + output_content_port_info = "port:%-3d %s(%d)" % (lport, bcm_port, unit_port) + for line in lines: + if (re.search('.*] Ber', line.strip())): + line_unit_port = int((line.split('Lane')[0]).split('Port')[1]) + if unit_port == line_unit_port: + prbs_ber_flag = 1 + lane_num = int((line.split(']')[0]).split('[')[1]) + prbs_ber = line.split('Ber')[1] + if (float(prbs_ber) > float(self.standard_ber_val)): + prbs_ber_test_fail = 1 + output_content = output_content + "%-20s Lane[%d] prbs_ber:%s > %s, test fail\n" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val) + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + log_error("%-20s lane:%d, prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + else: + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + log_debug("%-20s lane:%d, prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + if prbs_ber_flag == 1 and prbs_ber_test_fail == 0: + result_dict["successports"].append(port) + elif prbs_ber_flag == 1 and prbs_ber_test_fail == 1: + result_dict["errorports"].append(port) + result_dict["port_info_dict"][port]["log"] = output_content + else: + result_dict["errorports"].append(port) + prbs_info_gather_fun("%-20s get prbs_ber fail, output:\n%s" % (output_content_port_info, output)) + result_dict["port_info_dict"][port]["log"] = "%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output) + log_error("%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output)) + prbs_info_gather_fun("") + + if len(result_dict["errorports"]) > 0: + return False, result_dict + return True, result_dict + + def clear_port_prbs(self): + '''clear_port_prbs''' + + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbs clear'" % (self.prbs_port_range)) + ret, output = port_getstatusoutput(cmd, time_sleep=3) + if ret is False or "fail" in output: + log_error("mac prbs clear fail, output:%s" % output) + return False, "mac prbs clear fail, output:%s" % output + + cmd = get_sdk_cmd("dsh -c 'phy control %s clearprbs lnside=1'" % (self.prbs_port_range)) + ret, output = port_getstatusoutput(cmd, time_sleep=3) + if ret is False or "fail" in output: + log_error("sys prbs clear fail, output:%s" % output) + return False, "sys prbs clear fail, output:%s" % output + + cmd = get_sdk_cmd("dsh -c 'phy control %s clearprbs lnside=0'" % (self.prbs_port_range)) + ret, output = port_getstatusoutput(cmd, time_sleep=3) + if ret is False or "fail" in output: + log_error("line prbs clear fail, output:%s" % output) + return False, "line prbs clear fail, output:%s" % output + + log_debug("clear_port_prbs success") + return True, "clear_port_prbs success" + +@singleton +class PortHsdkPrbsIntPhyTest(PortHsdkPrbsTest): + '''IntPhy prbs''' + + def init_test(self): + '''Port internal PHY PRBS init test''' + + pass + + def start_test(self, **kwargs): + '''Port internal PHY PRBS start test''' + + log_debug("start_test") + return self.set_port_prbs(1) + + def check_test(self, **kwargs): + '''Port internal PHY PRBS get test result''' + + port = kwargs["port"] + + log_debug("check_test") + return self.get_port_prbs_int_result(port) + + def del_test(self): + '''Port internal PHY PRBS test environment recover''' + + log_debug("del_test") + return self.reset_port_prbs() + + def set_port_prbs(self, enable): + '''set port prbs, start test''' + + if enable == 1: + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbs set p=3'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbs get'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd) + if(ret != 0): + return False, output + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbsstat start interval=%d'" % (self.prbs_port_range, self.prbs_time)) + ret, output = port_getstatusoutput(cmd, time_sleep=(self.prbs_time + 10)) + if(ret != 0): + return False, output + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbsstat ber'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd, time_sleep=5) + if(ret != 0): + return False, output + return True, output + else: + cmd = get_sdk_cmd("dsh -c 'phy diag %s prbs clear'" % self.prbs_port_range) + ret, output = port_getstatusoutput(cmd) + if(ret != 0): + return False, output + return True, output + + def get_port_prbs_int_result(self, port): + '''get port PRBS test result''' + + prbs_ber_flag = 0 + prbs_ber_test_fail = 0 + output_content = "" + lport = self.device_port_list[port - 1].lport + bcm_port = self.device_port_list[port - 1].bcm_port + unit_port = self.device_port_list[port - 1].unit_port + output_content_port_info = "port:%-3d %s(%d)" % (lport, bcm_port, unit_port) + + cmd = get_sdk_cmd("dsh -c 'phy diag %d prbsstat ber'" % unit_port) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + log_debug(output) + + lines = output.split("\n") + for line in lines: + if (re.search('.*].*e', line.strip())): + prbs_ber_flag = 1 # return information have prbs_ber info + lane_num = int((line.split(']')[0]).split('[')[1]) + prbs_ber = line.split(' ')[-1] + if (float(prbs_ber) > float(self.standard_ber_val)): + prbs_ber_test_fail = 1 + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + output_content = output_content + "%-20s Lane[%d] prbs_ber:%s > %s, test fail\n" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val) + log_error("%-20s lane:%d, prbs_ber:%s > %s, test fail" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + else: + prbs_info_gather_fun("%-20s Lane[%d] prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + log_debug("%-20s lane:%d, prbs_ber:%s <= %s, test success" % (output_content_port_info, lane_num, prbs_ber, self.standard_ber_val)) + if prbs_ber_flag == 1 and prbs_ber_test_fail == 0: + prbs_info_gather_fun("") + return True, output + elif prbs_ber_flag == 1 and prbs_ber_test_fail == 1: + prbs_info_gather_fun("") + return False, output_content + else: + prbs_info_gather_fun("%-20s get prbs_ber fail, output:\n%s" % (output_content_port_info, output)) + prbs_info_gather_fun("") + log_error("%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output)) + return False, "%-20s get prbs_ber fail, output:%s" % (output_content_port_info, output) + + def reset_port_prbs(self): + '''reset port rbs''' + + ret, output = self.set_port_prbs(0) + if ret: + time.sleep(10) + log_debug("reset_port_prbs success") + return True, "reset_port_prbs success" + else: + log_error("reset_port_prbs fail, output:%s" % output) + return False, "reset_port_prbs fail, output:%s" % output + +@singleton +class PortHsdkKrTest(PortHsdkTest): + '''Internal management port receive and send packets''' + + def init_test(self): + '''The internal management port test is initialized''' + log_debug("init_test") + self.install_pktgen_mode() + ret, output = self.set_mgmt_antoneg_on() + if ret is False: + log_error("set_mgmt_antoneg_on fail, output:%s" % output) + return False, "set_mgmt_antoneg_on fail, output:%s" % output + + ret, output = self.set_all_mgmt_enable(1) + if ret is False: + log_error("set_all_mgmt_enable fail, output:%s" % output) + return False, "set_all_mgmt_enable fail, output:%s" % output + + ret, output = self.clear_all_mgmt_packets() + if ret is False: + log_error("clear_all_mgmt_packets fail, output:%s" % output) + return False, "clear_all_mgmt_packets fail, output:%s" % output + + log_debug("init_test success") + return True, "init_test success" + + def start_test(self, **kwargs): + '''start Internal management port test ''' + + mgmt_eth = kwargs["mgmt_eth"] + count = kwargs.get("count", PACKETS_COUNT) + size = kwargs.get("size", PACKETS_SIZE) + dst_mac = kwargs.get("dst_mac", PACKETS_DST_MAC) + vlan = kwargs.get("vlan", KR_VLAN) + + log_debug("start_test") + return self.kr_start_send_port_packets(mgmt_eth=mgmt_eth, count=count, size=size, + dst_mac=dst_mac, vlan=vlan) + + def check_test(self, **kwargs): + '''get Internal management port test result''' + + mgmt_eth = kwargs["mgmt_eth"] + count = kwargs.get("count", PACKETS_COUNT) + + log_debug("check_test") + return self.check_port_packets(mgmt_eth, count) + + def del_test(self): + '''The internal management port test environment is restored''' + + log_debug("del_test") + ret, output = self.set_all_mgmt_enable(0) + if ret is False: + log_error("set_all_mgmt_enable fail, output:%s" % output) + return False, "set_all_mgmt_enable fail, output:%s" % output + + ret, output = self.clear_all_mgmt_packets() + if ret is False: + log_error("clear_all_mgmt_packets fail, output:%s" % output) + return False, "clear_all_mgmt_packets fail, output:%s" % output + + return True, "del_test success" + + def kr_start_send_port_packets(self, **kwargs): + '''Began to contract''' + + mgmt_eth = kwargs["mgmt_eth"] + count = kwargs.get("count", PACKETS_COUNT) + size = kwargs.get("size", PACKETS_SIZE) + dst_mac = kwargs.get("dst_mac", PACKETS_DST_MAC) + vlan = kwargs.get("vlan", KR_VLAN) + + mgmt_bcmport = self.get_mgmt_bcmport(mgmt_eth) + if mgmt_bcmport is None: + return False, "kr_start_send_port_packets fail, get_mgmt_bcmport:%s None" % mgmt_eth + + ret, output = self.kr_vlan_config(vlan, mgmt_bcmport) + if ret is False: + return False, "kr_start_send_port_packets fail, output:%s" % output + + ret, output = self.kr_pktgen_config(mgmt_eth=mgmt_eth, + count=count, + size=size, + dst_mac=dst_mac, + vlan=vlan, + mgmt_bcmport=mgmt_bcmport) + if ret is False: + return False, "kr_start_send_port_packets fail, output:%s" % output + + ret, output = self.kr_pktgen_start(mgmt_eth, vlan, mgmt_bcmport) + if ret is False: + return False, "kr_start_send_port_packets fail, output:%s" % output + + log_debug("start_send_port_packets success") + return True, "start_send_port_packets success" + + def set_mgmt_antoneg_on(self): + '''Call mgmt.cint to enable auto-negotiation of the internal management interface''' + + cmd = get_sdk_cmd("cint /usr/share/sonic/device/%s/mgmt.cint" % global_onie_platform) + ret, output = port_getstatusoutput(cmd) + if(ret != 0): + log_error("set_mgmt_antoneg_on fail, output:%s" % output) + return False, "set_mgmt_antoneg_on fail, output:%s" % output + + log_debug("set_mgmt_antoneg_on success") + return True, output + + def get_kr_port_status(self, eth): + '''get kr port up/down status''' + + # get bcm_port + cmd = get_sdk_cmd("ps %s" % self.get_mgmt_bcmport(eth)) + ret, output = port_getstatusoutput(cmd) + + if ret == 0: + return PortHsdkUtil.ReUtil.getre_port_status(output) + return False, output + + def get_kr_unit_port_by_bcm(self, eth, bcm_port): + '''get unit_port''' + + unit_port = None + cmd = get_sdk_cmd("ps %s" % bcm_port) + ret, output = port_getstatusoutput(cmd) + + lines = output.split("\n") + if ret == 0: + for line in lines: + if (re.search('(.*?)\((.*?)$', line.strip())): + unit_port = PortHsdkUtil.ReUtil.getre_output_unit_port(line) + log_debug("port:%s bcm_port:%s unit_port:%d, get_kr_unit_port_by_bcm success" % (eth, bcm_port, unit_port)) + return True, unit_port + + log_error("port:%s bcm_port:%s, get_unit_port_by_bcm fail, output:%s" % (eth, bcm_port, output)) + return False, 0 + + def check_mgmt_speed_is_10G(self, eth, bcm_port): + '''check Internal management port speed whether is 10G''' + + cmd = get_sdk_cmd("ps %s" % bcm_port) + ret, output = port_getstatusoutput(cmd) + lines = output.split("\n") + mgmt_speed = None + if ret == 0: + for line in lines: + if (re.search('(.*?)\((.*?)$', line.strip())): + mgmt_speed = PortHsdkUtil.ReUtil.getre_output_speed(line) + if mgmt_speed == "10G": + log_debug("port:%s bcm_port:%s speed:%s, check_mgmt_speed_is_10G success" % (eth, bcm_port, mgmt_speed)) + return True, "port:%s bcm_port:%s speed:%s, check_mgmt_speed_is_10G success" % (eth, bcm_port, mgmt_speed) + else: + log_error("port:%s bcm_port:%s speed:%s, check_mgmt_speed_is_10G fail, output:%s" % (eth, bcm_port, mgmt_speed, output)) + return False, "port:%s bcm_port:%s speed:%s, check_mgmt_speed_is_10G fail, output:%s" % (eth, bcm_port, mgmt_speed, output) + + def check_port_packets(self, mgmt_eth, count=PACKETS_COUNT): + '''get Internal management port test result''' + + kr_count_pkt = 0 + pktgen_count_pkt = 0 + result_str = "" + # get pktgen send packets result + cmd = "cat /proc/net/pktgen/%s" % mgmt_eth + ret, output = port_getstatusoutput(cmd) + log_debug(output) + lines = output.split("\n") + for line in lines: + if (re.search('Result(.*?)$', line.strip())): + pktgen_count_pkt = int((line.split("usec,"))[1].split("(")[0]) + log_debug("pktgen_count_pkt:%d" % pktgen_count_pkt) + if (pktgen_count_pkt != 0): + result_str += "pktgen_count_pkt:%d\n" % pktgen_count_pkt + else: + result_str += (output + "\n") + # get show c result + cmd = get_sdk_cmd("show c %s" % self.get_mgmt_bcmport(mgmt_eth)) + ret, output = port_getstatusoutput(cmd) + lines = output.split("\n") + for line in lines: + if (re.search('XLMIB_RPOK(.*?)$', line.strip())): + kr_count_pkt = PortHsdkUtil.ReUtil.getre_output_packets_count(line) + log_debug("kr_count_pkt:%d" % kr_count_pkt) + result_str += "kr_count_pkt:%d\n" % kr_count_pkt + if (pktgen_count_pkt == kr_count_pkt): + return True, result_str + else: + result_str += "pktgen_count_pkt != kr_count_pkt\n" + return False, result_str + result_str += "kr_count_pkt:%d\n" % kr_count_pkt + result_str += "%s, output:\n%s" % (cmd, output) + return False, result_str + + def clear_all_mgmt_packets(self): + '''claer Internal management port port_packets''' + + cmd = get_sdk_cmd("clear c %s" % (",".join(self.get_mgmt_bcmport(item) + for item + in global_port_config["mgmt_kt_ports"]))) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + log_warning("clear_all_mgmt_packets fail, output:%s" % output) + return False, "clear_all_mgmt_packets fail, output:%s" % output + + log_debug("clear_all_mgmt_packets success") + return True, "clear_all_mgmt_packets success" + + @classmethod + def install_pktgen_mode(cls): + '''Check whether the pktgen module is loaded. If not, load the pktgen module''' + + cmd = "lsmod | grep pktgen" + ret, output = port_getstatusoutput(cmd) + if not output or ret != 0: + log_debug("载入pktgen模块") + cmd = "modprobe pktgen" + ret, output = port_getstatusoutput(cmd) + eth_list = list(global_port_config["mgmt_kt_ports"].keys()) + eth_list.sort() + for eth in eth_list: + cmd = "ls /proc/net/pktgen/%s" % eth + ret, output = port_getstatusoutput(cmd) + if "cannot" in output: + cmd = "ifconfig %s up" % eth + ret, output = port_getstatusoutput(cmd, time_sleep=1) + cmd = "echo \"add_device %s\" > /proc/net/pktgen/kpktgend_0" % eth + ret, output = port_getstatusoutput(cmd) + time.sleep(3) + + @classmethod + def kr_vlan_config(cls, vlan, mgmt_bcmport): + '''Internal management port send packets set vlan''' + + time.sleep(1) + cmd = get_sdk_cmd("vlan destroy %d" % vlan) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + cmd = get_sdk_cmd("vlan create %d PortBitMap=%s UntagBitMap=%s" % (vlan, + mgmt_bcmport, + mgmt_bcmport)) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + cmd = get_sdk_cmd("pvlan set %s %d" % (mgmt_bcmport, vlan)) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + + return True, "kr_vlan_config success" + + @classmethod + def kr_pktgen_config(cls, **kwargs): + '''Internal management port send packets set pktgen config''' + + mgmt_eth = kwargs["mgmt_eth"] + size = kwargs["size"] + count = kwargs["count"] + dst_mac = kwargs["dst_mac"] + vlan = kwargs["vlan"] + mgmt_bcmport = kwargs["mgmt_bcmport"] + + cmd = "echo \"pkt_size %d\" > /proc/net/pktgen/%s" % (size, mgmt_eth) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + cmd = "echo \"count %d\" > /proc/net/pktgen/%s" % (count, mgmt_eth) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + cmd = "echo \"dst_mac %s\" > /proc/net/pktgen/%s" % (dst_mac, mgmt_eth) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + cmd = "echo \"vlan_id %s\" > /proc/net/pktgen/%s" % (vlan, mgmt_eth) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + + cmd = get_sdk_cmd("clear c %s" % mgmt_bcmport) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + + return True, "kr_pktgen_config success" + + @classmethod + def kr_pktgen_start(cls, mgmt_eth, vlan, mgmt_bcmport): + '''Internal management port use pktgen satrt send packets''' + + # start pktgen send packets,sleep 5s + cmd = "echo \"start\" > /proc/net/pktgen/pgctrl" + ret, output = port_getstatusoutput(cmd, time_sleep=5) + if ret != 0: + return False, output + + # stop pktgen send packets + cmd = "echo \"stop\" > /proc/net/pktgen/pgctrl" + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + + # After packets are sent, the internal management port is removed from the VLAN + cmd = get_sdk_cmd("vlan remove %d PortBitMap=%s" % (vlan, mgmt_bcmport)) + ret, output = port_getstatusoutput(cmd) + if ret != 0: + return False, output + + return True, "start_send_port_packets_t success" + +class PortScene(): + '''port class''' + + @staticmethod + def port_frame_test(port_list=[], redirect=True): + '''Port frame test''' + + log_debug("开始端口收发帧测试") + pft = PortHsdkFrameTest() + psf = PortScnFn() + frmnm = PACKETS_COUNT + port_list = copy.deepcopy(port_list)# Prevents an operation on an incoming object when it is an object + cycle_num = global_port_config["port_frame_test_retrynum"]# cycles + del_sleep_time = global_port_config["port_frame_del_time"]# Restore the test environment waiting time + psf.sdk_cmd_redirect_judge(redirect) + log_debug("端口收发帧重试次数为%d次" % cycle_num) + + for c_i in range(cycle_num): + log_debug("端口收发帧第%d次测试" % (c_i + 1)) + global global_port_log_info + global_port_log_info = "port_log_info:\n" + + upports = [] + successports = [] + updownerrorports = [] + errorports = [] + result_dict = {} + ret_t = 0 + try: + ret_t, result_dict, upports, updownerrorports = psf.get_port_status_f(f_obj=pft, port_list=port_list) + log_debug("up_port:" + ", ".join(str(index) for index in upports)) + if ret_t < 0 or len(upports) == 0: + if (ret_t < 0): + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f ret_t < 0\n" + log_error("get_port_status_f ret_t < 0") + else: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f len(upports) == 0\n" + log_error("get_port_status_f len(upports) == 0") + else: + ret, result = pft.init_test() + if ret is False: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "init_test fail, result:%s\n" % result + log_error("init_test fail, result:%s" % result) + continue # Start the entire test item retry + ret_t, result_dict = psf.frame_start_f(f_obj=pft, + ret_t=ret_t, + uprt=upports, + frmnm=frmnm, + r_dict=result_dict) + time.sleep(5) + ret_t, result_dict, successports, errorports = psf.frame_check_f(f_obj=pft, + ret_t=ret_t, + uprt=upports, + frmnm=frmnm, + r_dict=result_dict) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + continue + finally: + ret, result = pft.del_test() + if ret is False: + log_error("del_test fail, result:%s" % result) + time.sleep(del_sleep_time) + ret_t, result_dict = psf.compare_start_end_ports(f_obj=pft, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict, + port_list=port_list) + result_dict["successports"] = successports + result_dict["updownerrorports"] = updownerrorports + result_dict["errorports"] = errorports + if len(updownerrorports) > 0: + ret_t -= 1 + if ret_t < 0: + continue + break + + return psf.test_return(ret_t=ret_t, result_dict=result_dict, test_type="frame") + + @staticmethod + def port_brcst_test(port_list=[], redirect=True): + '''Port broadcast test''' + + log_debug("开始端口广播测试") + pbt = PortHsdkBrcstTest() + psf = PortScnFn() + psf.sdk_cmd_redirect_judge(redirect) + port_list = copy.deepcopy(port_list)# Prevents an operation on an incoming object when it is an object + cycle_num = global_port_config["port_brcst_test_retrynum"]# cycle + del_sleep_time = global_port_config["port_brcst_del_time"]# Restore the test environment waiting time + log_debug("端口广播重试次数为%d次" % cycle_num) + + for c_i in range(cycle_num): + log_debug("端口广播帧第%d次测试" % (c_i + 1)) + global global_port_log_info + global_port_log_info = "port_log_info:\n" + + upports = [] + successports = [] + updownerrorports = [] + errorports = [] + result_dict = {} + ret_t = 0 + try: + ret_t, result_dict, upports, updownerrorports = psf.get_port_status_f(f_obj=pbt, port_list=port_list) + log_debug("up_port:" + ", ".join(str(index) for index in upports)) + if ret_t < 0 or len(upports) == 0: + if (ret_t < 0): + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f ret_t < 0\n" + log_error("get_port_status_f ret_t < 0") + else: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f len(upports) == 0\n" + log_error("get_port_status_f len(upports) == 0") + else: + ret, result = pbt.init_test() + if ret is False: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "init_test fail, result:%s\n" % result + log_error("init_test fail, result:%s" % result) + continue + # Broadcast packets are sent through the first up port + port=upports[0] + ret, output = pbt.start_test(port=port, count=PACKETS_COUNT) + if ret is True: + time.sleep(10)# Port broadcast test Wait for flooding 10 seconds + ret_t, result_dict, successports, errorports = psf.brcst_check_f(f_obj=pbt, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict) + else: + ret_t -= 1 + log_error("port %d:sending packet , output:%s" % (port, output)) + output_info = result_dict["port_info_dict"][port]["output"] + result_dict["port_info_dict"][port]["output"] = output_info + "port %d:sending packet , output:%s" % (port, output) + + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + continue + finally: + # Disable the broadcast and restore the environment + ret, result = pbt.del_test() + if ret is False: + log_error("del_test fail, result:%s" % result) + time.sleep(del_sleep_time) + ret_t, result_dict = psf.compare_start_end_ports(f_obj=pbt, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict, + port_list=port_list) + result_dict["successports"] = successports + result_dict["updownerrorports"] = updownerrorports + result_dict["errorports"] = errorports + if len(updownerrorports) > 0: + ret_t -= 1 + if ret_t < 0: + continue + break + + return psf.test_return(ret_t=ret_t, result_dict=result_dict, test_type="brcst") + + def port_prbs_test(self, port_list=[], test_type="", redirect=True): + '''port PRBS test''' + + # Initialize the production test configuration,Prevent external PHY devices + # When the first test item is PRBS, the production configuration is not initialized and the internal PHY PRBS interface is invoked + ppipt = PortHsdkPrbsIntPhyTest() + if global_port_config.get("extphy_device", 0) == 1:# have external phy + log_debug("PortHsdkPrbsExtPhyTest") + return self.test_port_prbs_extphy(port_list=port_list, test_type=test_type, redirect=redirect) + # no external phy + log_debug("PortHsdkPrbsIntPhyTest") + return self.test_port_prbs_intphy(port_list=port_list, test_type=test_type, redirect=redirect) + + @staticmethod + def port_kr_test(port_list=[], redirect=True): + '''Internal management port receiving and sending test''' + + log_debug("开始内部管理口收发包测试") + pkt = PortHsdkKrTest() + psf = PortScnFn() + packetcount = PACKETS_COUNT + port_list = copy.deepcopy(port_list)# Prevents an operation on an incoming object when it is an object + cycle_num = global_port_config["port_kr_test_retrynum"]# cycles + del_sleep_time = global_port_config["port_kr_del_time"]# Restore the test environment waiting time + psf.sdk_cmd_redirect_judge(redirect) + log_debug("内部管理口收发包重试次数为%d次" % cycle_num) + + for c_i in range(cycle_num): + log_debug("内部管理口收发包第%d次测试" % (c_i + 1)) + global global_port_log_info + global_port_log_info = "port_log_info:\n" + + upports = [] + successports = [] + updownerrorports = [] + errorports = [] + result_dict = {} + ret_t = 0 + try: + ret, result = pkt.init_test() + if ret is False: + ret_t = -1 + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "init_test fail, result:%s\n" % result + log_error("init_test fail, result:%s" % result) + ret_t, result_dict, upports, updownerrorports = psf.get_port_status_f(f_obj=pkt, kr_test=True, port_list=port_list) + log_debug("up_port:" + ", ".join(str(index) for index in upports)) + if ret_t < 0 or len(upports) == 0: + if (ret_t < 0): + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f ret_t < 0\n" + log_error("get_port_status_f ret_t < 0") + else: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f len(upports) == 0\n" + log_error("get_port_status_f len(upports) == 0") + else: + for eth in upports: + log_debug("内部管理口:%s 正在发包" % eth) + ret, output = pkt.start_test(mgmt_eth=eth, count=packetcount, vlan=2000) + if ret is False: + errorports.append(eth) + output_info = result_dict["port_info_dict"][eth]["log"] + result_dict["port_info_dict"][eth]["log"] = output_info + "port_kr_test start_test fail, output:%s" % output + log_warning("port_kr_test start_test fail, output:%s" % output) + else: + time.sleep(4) + ret, output = pkt.check_test(mgmt_eth=eth, count=packetcount) + if ret: + successports.append(eth) + else: + ret_t = -1 + errorports.append(eth) + output_info = result_dict["port_info_dict"][eth]["log"] + result_dict["port_info_dict"][eth]["log"] = output_info + "port_kr_test check_test fail, output:%s" % output + log_error("%s check_test fail, output:%s" % (eth, output)) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + continue + finally: + ret_t, result_dict = psf.compare_start_end_ports(f_obj=pkt, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict, + kr_test=True, + port_list=port_list) + ret, result = pkt.del_test() + if ret is False: + log_error("del_test fail, result:%s" % result) + time.sleep(del_sleep_time) + result_dict["successports"] = successports + result_dict["updownerrorports"] = updownerrorports + result_dict["errorports"] = errorports + if len(updownerrorports) > 0: + ret_t -= 1 + if ret_t < 0: + continue + break + + return psf.test_return(ret_t=ret_t, result_dict=result_dict, test_type="kr") + + @staticmethod + def test_port_prbs_extphy(port_list=[], test_type="", redirect=True): + '''ExtPhy prbs test''' + + log_debug("开始ExtPhy prbs测试") + if (test_type != ""): + log_debug("test_type: %s" % test_type) + else: + log_debug("test_type: prbs_mac、prbs_sys、prbs_line") + + psf = PortScnFn() + psf.sdk_cmd_redirect_judge(redirect) + ppept = PortHsdkPrbsExtPhyTest() + port_list = copy.deepcopy(port_list)# Prevents an operation on an incoming object when it is an object + cycle_num = global_port_config["port_prbs_test_retrynum"]# cycles + del_sleep_time = global_port_config["port_prbs_del_time"]# Restore the test environment waiting time + log_debug("ExtPhy prbs重试次数为%d次" % cycle_num) + + for c_i in range(cycle_num): + log_debug("ExtPhy prbs第%d次测试" % (c_i + 1)) + global global_port_log_info + global_port_log_info = "port_log_info:\n" + + upports = [] + updownerrorports = [] + result_dict = {} + # Keep pointing to the same object + prbs_mac_result_dict = result_dict + prbs_sys_result_dict = result_dict + prbs_line_result_dict = result_dict + prbs_all_result_dict = { + "prbs_mac_result_dict":prbs_mac_result_dict, + "prbs_sys_result_dict":prbs_sys_result_dict, + "prbs_line_result_dict":prbs_line_result_dict + } + ret_t = 0 + try: + ret_t, result_dict, upports, updownerrorports = psf.get_port_status_f(f_obj=ppept, port_list=port_list) + result_dict["updownerrorports"] = updownerrorports + log_debug("up_port:" + ", ".join(str(index) for index in upports)) + if ret_t < 0 or len(upports) == 0: + if (ret_t < 0): + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f ret_t < 0\n" + log_error("get_port_status_f ret_t < 0") + else: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f len(upports) == 0\n" + log_error("get_port_status_f len(upports) == 0") + else: + ret_t, prbs_all_result_dict = psf.prbs_mac_sys_line_start_check(f_obj=ppept, + ret_t=ret_t, + uprt=upports, + udeprt=updownerrorports, + test_type=test_type, + r_dict=result_dict) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + continue + finally: + ret, result = ppept.del_test() + if ret is False: + log_error("del_test fail, result:%s" % result) + time.sleep(del_sleep_time) + ret_t, result_dict = psf.compare_start_end_ports(f_obj=ppept, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict, + port_list=port_list) + prbs_all_result_dict = psf.prbs_ext_result_dict_dispose(r_dict=result_dict, + test_type=test_type, + prbs_all_r_dict=prbs_all_result_dict) + if len(updownerrorports) > 0: + ret_t -= 1 + if ret_t < 0: + continue + break + return PortScnFn.test_return(ret_t=ret_t, prbs_all_result_dict=prbs_all_result_dict, test_type=test_type) + + @staticmethod + def test_port_prbs_intphy(port_list=[], test_type="", redirect=True): + '''IntPhy prbs test''' + + log_debug("开始IntPhy prbs测试") + ppipt = PortHsdkPrbsIntPhyTest() + psf = PortScnFn() + psf.sdk_cmd_redirect_judge(redirect) + port_list = copy.deepcopy(port_list)# Prevents an operation on an incoming object when it is an object + cycle_num = global_port_config["port_prbs_test_retrynum"]# cycles + del_sleep_time = global_port_config["port_prbs_del_time"]# Restore the test environment waiting time + log_debug("IntPhy prbs重试次数为%d次" % cycle_num) + + for c_i in range(cycle_num): + log_debug("IntPhy prbs第%d次测试" % (c_i + 1)) + global global_port_log_info + global_port_log_info = "port_log_info:\n" + prbs_info_gather_fun("prbs_mac_test", clear=True) + + upports = [] + successports = [] + updownerrorports = [] + errorports = [] + result_dict = {} + prbs_all_result_dict = {} + ret_t = 0 + try: + ret_t, result_dict, upports, updownerrorports = psf.get_port_status_f(f_obj=ppipt, port_list=port_list) + log_debug("up_port:" + ", ".join(str(index) for index in upports)) + if ret_t < 0 or len(upports) == 0: + if (ret_t < 0): + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f ret_t < 0\n" + log_error("get_port_status_f ret_t < 0") + else: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status_f len(upports) == 0\n" + log_error("get_port_status_f len(upports) == 0") + else: + ret_t, result_dict = psf.prbs_int_start_f(f_obj=ppipt, ret_t=ret_t, uprt=upports, r_dict=result_dict) + ret_t, result_dict, successports, errorports = psf.prbs_int_check_f(f_obj=ppipt, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + continue + finally: + ret, result = ppipt.del_test() + if ret is False: + log_error("del_test fail, result:%s" % result) + time.sleep(del_sleep_time) + ret_t, result_dict = psf.compare_start_end_ports(f_obj=ppipt, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict, + port_list=port_list) + result_dict["successports"] = successports + result_dict["updownerrorports"] = updownerrorports + result_dict["errorports"] = errorports + if len(updownerrorports) > 0: + ret_t -= 1 + if ret_t < 0: + continue + break + prbs_all_result_dict["prbs_mac_result_dict"] = copy.deepcopy(result_dict) + prbs_all_result_dict["prbs_mac_result_dict"]["prbs_info"] = global_prbs_info + prbs_all_result_dict["prbs_sys_result_dict"] = {} + prbs_all_result_dict["prbs_line_result_dict"] = {} + prbs_all_result_dict["prbs_mac_result_dict"]["test_type"] = "prbs_mac" + if ret_t < 0: + prbs_all_result_dict["prbs_mac_result_dict"]["test_result"] = False + else: + prbs_all_result_dict["prbs_mac_result_dict"]["test_result"] = True + return psf.test_return(ret_t=ret_t, prbs_all_result_dict=prbs_all_result_dict, test_type="prbs_mac") + +class PortScnFn(): + '''PortScene function''' + + @staticmethod + def get_port_status_f(**kwargs): + '''get port status''' + + ret_t = 0 + upports = [] + updownerrorports = [] + result_dict = {"port_info_dict":{}, "other_info":"", "test_result": False, + "updownerrorports":[], "errorports":[], "successports":[]} + f_obj = kwargs["f_obj"] + kr_test_flag = kwargs.get("kr_test", False) + port_list = kwargs.get("port_list", []) + + log_debug("开始获取端口状态") + try: + if kr_test_flag is False: + # introduction port_list=[] or not introduction port_list, test all ports + # introduction port_list=[7,8,9,10], test panel port 7, 8, 9, 10 + log_debug("bcm_port数量:%d" % len(f_obj.device_port_list)) + if len(port_list) == 0: + for i in range(len(f_obj.device_port_list)): + port_list.append(i + 1) + + if type(port_list[0]) is int: + log_debug("port_list %s" % port_list) + else: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "not find port in port_list:%s\n" % port_list + log_error("not find port in port_list:%s " % port_list) + ret_t -= 1 + port_list = [] + + # for port_list init result_dict + for port in port_list: + result_dict["port_info_dict"][port] = { + "port_info":"", + "status":"", + "log":""} + for port in port_list: + # get port_info,add result_dict["port_info_dict"][port]["port_info"] + bcm_port = f_obj.device_port_list[port - 1].bcm_port + unit_port = f_obj.device_port_list[port - 1].unit_port + port_info = "port:%-3d %s(%d)" % (port, bcm_port, unit_port) + result_dict["port_info_dict"][port]["port_info"] = port_info + + # get port status,add result_dict["port_info_dict"][port]["status"],add the port status to the list + ret, output = f_obj.get_port_status(port) + if ret is True: + if output == "up": + upports.append(port) + result_dict["port_info_dict"][port]["status"] = "up" + log_debug("%-18s:up" % port_info) + elif output == "down": + updownerrorports.append(port) + result_dict["port_info_dict"][port]["status"] = "down" + log_warning("%-18s:down" % port_info) + elif output == "!ena": + updownerrorports.append(port) + result_dict["port_info_dict"][port]["status"] = "!ena" + log_warning("%-18s:!ena" % port_info) + else: + updownerrorports.append(port) + result_dict["port_info_dict"][port]["status"] = "NA" + log_warning("%-18s:NA, output:%s" % (port_info, output)) + else: + ret_t -= 1 + result_dict["port_info_dict"][port]["status"] = "NA" + result_dict["port_info_dict"][port]["log"] = "get_port_status abnormal, output:%s\n" % output + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status abnormal, output:%s\n" % output + log_error("%-18s:get_port_status abnormal, output:%s" % (port_info, output)) + break + else: # kr test: get is eth of bcm_port + # introduction port_list=[] or not introduction port_list, test all internal management ports + # introduction port_list=['eth1'], test internal management ports eth1 + # Internal management port Additional check whether the rate is 10G + if len(port_list) == 0: + eth_list = list(global_port_config["mgmt_kt_ports"].keys()) + eth_list.sort() + else: + eth_list = port_list + eth_list.sort() + + if type(eth_list[0]) is int: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "not find ethX in eth_list:%s\n" % eth_list + log_error("not find ethX in eth_list:%s " % eth_list) + ret_t -= 1 + eth_list = [] + else: + log_debug("eth_list %s" % eth_list) + + # for eth_list init result_dict + for eth in eth_list: + result_dict["port_info_dict"][eth] = { + "port_info":"", + "status":"", + "log":""} + for eth in eth_list: + # get port_info,add result_dict["port_info_dict"][eth]["port_info"] + bcm_port = f_obj.get_mgmt_bcmport(eth) + ret, unit_port = f_obj.get_kr_unit_port_by_bcm(eth, bcm_port) + port_info = "port:%s %s(%s)" % (eth, bcm_port, str(unit_port)) + result_dict["port_info_dict"][eth]["port_info"] = port_info + + # obtain the port rate and check whether it is 10G + ret, output = f_obj.check_mgmt_speed_is_10G(eth, bcm_port) + if ret is False: + ret_t -= 1 + result_dict["port_info_dict"][eth]["log"] = "%s\n" % output + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "%s\n" % output + break + # Obtaining port Status,add result_dict["port_info_dict"][eth]["status"],add the port status to the list + ret, output = f_obj.get_kr_port_status(eth)# Obtain the bcm_port status of the management port + if ret is True: + if output == "up": + upports.append(eth) + result_dict["port_info_dict"][eth]["status"] = "up" + log_debug("%-18s:up" % port_info) + elif output == "down": + updownerrorports.append(eth) + result_dict["port_info_dict"][eth]["status"] = "down" + log_warning("%-18s:down" % port_info) + elif output == "!ena": + updownerrorports.append(eth) + result_dict["port_info_dict"][eth]["status"] = "!ena" + log_warning("%-18s:!ena" % port_info) + else: + updownerrorports.append(eth) + result_dict["port_info_dict"][eth]["status"] = "NA" + log_warning("%-18s:NA, output:%s" % (port_info, output)) + else: + ret_t -= 1 + result_dict["port_info_dict"][eth]["status"] = "NA" + result_dict["port_info_dict"][eth]["log"] = "get_port_status abnormal, output:%s\n" % output + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "get_port_status abnormal, output:%s\n" % output + log_error("%-18s:get_port_status abnormal" % port_info) + break + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict, upports, updownerrorports + return ret_t, result_dict, upports, updownerrorports + + @staticmethod + def compare_start_end_ports(**kwargs): + '''Compare the port up status at the start and end of the test item''' + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + kr_test_flag = kwargs.get("kr_test", False) + port_list = kwargs.get("port_list", []) + result_dict = kwargs["r_dict"] + + try: + # When all the above tests are successful, the port up status at the start and end of the test item will be compared + if ret_t == 0: + if kr_test_flag is False: + s_ret_t, _, s_upports, _ = PortScnFn.get_port_status_f(f_obj=f_obj, port_list=port_list) + else: + # During the KR test, the ETH interface is obtained + s_ret_t, _, s_upports, _ = PortScnFn.get_port_status_f(f_obj=f_obj, port_list=port_list, kr_test=kr_test_flag) + if s_ret_t == 0: + if upports != s_upports: + ret_t -= 1 + temp_log = "first_uplist != second_uplist\nfirst_uplist:%s\nsecond_uplist:%s\n" % (upports, s_upports) + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + temp_log + log_error(temp_log) + else: + log_debug("两次端口up状态相同") + else: + ret_t -= 1 + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "test end:get_port_status abnormal" + log_warning("test end:get_port_status abnormal") + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict + return ret_t, result_dict + + @staticmethod + def frame_start_f(**kwargs): + '''Port frame send packets''' + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + framenum = kwargs["frmnm"] + result_dict = kwargs["r_dict"] + + try: + for port in upports: + bcm_port = f_obj.device_port_list[port - 1].bcm_port + unit_port = f_obj.device_port_list[port - 1].unit_port + port_info = "port:%d %s(%d)" % (port, bcm_port, unit_port) + log_debug("%-18s:sending packet" % port_info) + + ret, output = f_obj.start_test(port=port, count=framenum, size=1024) + if ret is False: + ret_t -= 1 + output_info = result_dict["port_info_dict"][port]["log"] + result_dict["port_info_dict"][port]["log"] = output_info + "sending packet fail, output:%s\n" % output + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "sending packet fail, output:%s\n" % output + log_warning("%-18s:sending packet fail, output:%s" % (port_info, output)) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict + return ret_t, result_dict + + @staticmethod + def frame_check_f(**kwargs): + '''Port frame results check''' + + successport = [] + errorport = [] + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + framenum = kwargs["frmnm"] + result_dict = kwargs["r_dict"] + + try: + # Verify the upports + for port in upports: + bcm_port = f_obj.device_port_list[port - 1].bcm_port + unit_port = f_obj.device_port_list[port - 1].unit_port + port_info = "port:%d %s(%d)" % (port, bcm_port, unit_port) + + ret, output = f_obj.check_test(port=port, count=framenum, direc="rx") + if ret is True: + successport.append(port) + log_debug("%-18s:test success" % port_info) + else: + ret_t -= 1 + errorport.append(port) + output_info = result_dict["port_info_dict"][port]["log"] + result_dict["port_info_dict"][port]["log"] = output_info + "frame_check_f fail, output:%s" % output + log_warning("%-18s:test fail, output:%s" % (port_info, output)) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict, successport, errorport + return ret_t, result_dict, successport, errorport + + @staticmethod + def brcst_check_f(**kwargs): + '''Port broadcast result detection''' + + successport = [] + errorport = [] + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + result_dict = kwargs["r_dict"] + + try: + for port in upports: + bcm_port = f_obj.device_port_list[port - 1].bcm_port + unit_port = f_obj.device_port_list[port - 1].unit_port + port_info = "port:%d %s(%d)" % (port, bcm_port, unit_port) + + ret, output = f_obj.check_test(port=port) + if ret is True: + successport.append(port) + log_debug("%-18s:test success" % port_info) + else: + ret_t -= 1 + errorport.append(port) + output_info = result_dict["port_info_dict"][port]["log"] + result_dict["port_info_dict"][port]["log"] = output_info + "brcst_check_f fail, output:%s\n" % output + log_warning("%-18s:test fail, output:%s" % (port_info, output)) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict, successport, errorport + return ret_t, result_dict, successport, errorport + + @staticmethod + def prbs_prepare_test(**kwargs): + '''ExtPhy prbs prepare test''' + + f_obj = kwargs["f_obj"] + upports = kwargs["uprt"] + try: + # Because the upports imported may be different each time,need to obtain the upports again + f_obj.get_unit_port_list(upports) + f_obj.get_prbs_port_range() + # test is for 3 sides, so prbs need to be cleared again before each side is tested + ret, output = f_obj.init_test() + if ret is False: + log_warning("prbs_prepare_test fail, output:%s" % output) + return False, "prbs_prepare_test fail, output:%s\n" % output + + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + return False, "Exception_info:\n%s" % msg + return True, "prbs_prepare_test success" + + @staticmethod + def prbs_mac_sys_line_start_check(**kwargs): + '''ExtPhy prbs mac、sys、line check''' + + psf = PortScnFn() + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + test_type = kwargs["test_type"] + result_dict = kwargs["r_dict"] + prbs_all_result_dict = { + "prbs_mac_result_dict":{}, + "prbs_sys_result_dict":{}, + "prbs_line_result_dict":{} + } + mac_flag = False + sys_flag = False + line_flag = False + all_flag = False + try: + if test_type == "prbs_mac": + mac_flag = True + elif test_type == "prbs_sys": + sys_flag = True + elif test_type == "prbs_line": + line_flag = True + else: + all_flag = True + # MAC port + if mac_flag or all_flag: + prbs_info_gather_fun("prbs_mac_test", clear=True) + log_debug("====================prbs_mac_test") + prbs_mac_result_dict = copy.deepcopy(result_dict) + ret_t, prbs_mac_result_dict = psf.prbs_mac_sys_line_result(f_obj=f_obj, + ret_t=ret_t, + uprt=upports, + r_dict=prbs_mac_result_dict, + test_type="prbs_mac") + + prbs_all_result_dict["prbs_mac_result_dict"] = copy.deepcopy(prbs_mac_result_dict) + prbs_all_result_dict["prbs_mac_result_dict"]["prbs_info"] = global_prbs_info + # SYS port + if sys_flag or all_flag: + prbs_info_gather_fun("prbs_sys_test", clear=True) + log_debug("====================prbs_sys_test") + prbs_sys_result_dict = copy.deepcopy(result_dict) + ret_t, prbs_sys_result_dict = psf.prbs_mac_sys_line_result(f_obj=f_obj, + ret_t=ret_t, + uprt=upports, + r_dict=prbs_sys_result_dict, + test_type="prbs_sys") + prbs_all_result_dict["prbs_sys_result_dict"] = copy.deepcopy(prbs_sys_result_dict) + prbs_all_result_dict["prbs_sys_result_dict"]["prbs_info"] = global_prbs_info + # Line port + if line_flag or all_flag: + prbs_info_gather_fun("prbs_line_test", clear=True) + log_debug("====================prbs_line_test") + prbs_line_result_dict = copy.deepcopy(result_dict) + ret_t, prbs_line_result_dict = psf.prbs_mac_sys_line_result(f_obj=f_obj, + ret_t=ret_t, + uprt=upports, + r_dict=prbs_line_result_dict, + test_type="prbs_line") + + prbs_all_result_dict["prbs_line_result_dict"] = copy.deepcopy(prbs_line_result_dict) + prbs_all_result_dict["prbs_line_result_dict"]["prbs_info"] = global_prbs_info + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, prbs_all_result_dict + return ret_t, prbs_all_result_dict + + @staticmethod + def prbs_mac_sys_line_result(**kwargs): + '''ExtPhy prbs mac、sys、line start test, and check test result''' + + psf = PortScnFn() + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + result_dict = kwargs["r_dict"] + test_type = kwargs["test_type"] + + try: + ret, output = psf.prbs_prepare_test(f_obj=f_obj, uprt=upports) + if ret is False: + ret_t -= 1 + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "output:%s\n" % output + log_error("prbs_mac_sys_line_result fail, output:%s\n") + return ret_t, result_dict + ret, output = f_obj.start_port_prbs(test_type) + if ret is False: + ret_t -= 1 + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "output:%s\n" % output + log_error("prbs_mac_sys_line_result fail, output:%s\n") + return ret_t, result_dict + ret_t, result_dict = psf.prbs_mac_sys_line_check(f_obj=f_obj, + ret_t=ret_t, + uprt=upports, + r_dict=result_dict, + test_type=test_type) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict + return ret_t, result_dict + + @staticmethod + def prbs_mac_sys_line_check(**kwargs): + '''ExtPhy prbs mac、sys、line check''' + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + result_dict = kwargs["r_dict"] + test_type = kwargs["test_type"] + + try: + ret, result_dict = f_obj.check_test(test_type=test_type, + uprt=upports, + r_dict=result_dict) + result_dict["test_type"] = test_type + if ret: + result_dict["test_result"] = True + log_debug("======================%s_test check success\n" % test_type) + else: + ret_t -= 1 + result_dict["test_result"] = False + log_warning("======================%s_test check fail\n" % test_type) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict + return ret_t, result_dict + + @staticmethod + def prbs_ext_result_dict_dispose(**kwargs): + '''ExtPhy return result dictionary processing''' + + result_dict = kwargs["r_dict"] + test_type = kwargs["test_type"] + prbs_all_result_dict = kwargs["prbs_all_r_dict"] + + try: + # During the test, the dictionary key is not assigned due to a sudden exception + if (test_type == "prbs_mac"): + if prbs_all_result_dict["prbs_mac_result_dict"] == {}: + prbs_all_result_dict["prbs_mac_result_dict"] = copy.deepcopy(result_dict) + prbs_all_result_dict["prbs_mac_result_dict"]["test_type"] = "prbs_mac" + result_dict_other_info = result_dict.get("other_info", "") + prbs_all_result_dict_other_info = prbs_all_result_dict["prbs_mac_result_dict"].get("other_info", "") + prbs_all_result_dict["prbs_mac_result_dict"]["other_info"] = result_dict_other_info + prbs_all_result_dict_other_info + elif (test_type == "prbs_sys"): + if prbs_all_result_dict["prbs_sys_result_dict"] == {}: + prbs_all_result_dict["prbs_sys_result_dict"] = copy.deepcopy(result_dict) + prbs_all_result_dict["prbs_sys_result_dict"]["test_type"] = "prbs_sys" + result_dict_other_info = result_dict.get("other_info", "") + prbs_all_result_dict_other_info = prbs_all_result_dict["prbs_sys_result_dict"].get("other_info", "") + prbs_all_result_dict["prbs_sys_result_dict"]["other_info"] = result_dict_other_info + prbs_all_result_dict_other_info + elif (test_type == "prbs_line"): + if prbs_all_result_dict["prbs_line_result_dict"] == {}: + prbs_all_result_dict["prbs_line_result_dict"] = copy.deepcopy(result_dict) + prbs_all_result_dict["prbs_line_result_dict"]["test_type"] = "prbs_line" + result_dict_other_info = result_dict.get("other_info", "") + prbs_all_result_dict_other_info = prbs_all_result_dict["prbs_line_result_dict"].get("other_info", "") + prbs_all_result_dict["prbs_line_result_dict"]["other_info"] = result_dict_other_info + prbs_all_result_dict_other_info + else: + if prbs_all_result_dict["prbs_mac_result_dict"] == {}: + prbs_all_result_dict["prbs_mac_result_dict"] = copy.deepcopy(result_dict) + if prbs_all_result_dict["prbs_sys_result_dict"] == {}: + prbs_all_result_dict["prbs_sys_result_dict"] = copy.deepcopy(result_dict) + if prbs_all_result_dict["prbs_line_result_dict"] == {}: + prbs_all_result_dict["prbs_line_result_dict"] = copy.deepcopy(result_dict) + + prbs_all_result_dict["prbs_mac_result_dict"]["test_type"] = "prbs_mac" + prbs_all_result_dict["prbs_sys_result_dict"]["test_type"] = "prbs_sys" + prbs_all_result_dict["prbs_line_result_dict"]["test_type"] = "prbs_line" + + result_dict_other_info = result_dict.get("other_info", "") + prbs_all_result_dict_other_info = prbs_all_result_dict["prbs_mac_result_dict"].get("other_info", "") + prbs_all_result_dict["prbs_mac_result_dict"]["other_info"] = result_dict_other_info + prbs_all_result_dict_other_info + + result_dict_other_info = result_dict.get("other_info", "") + prbs_all_result_dict_other_info = prbs_all_result_dict["prbs_sys_result_dict"].get("other_info", "") + prbs_all_result_dict["prbs_sys_result_dict"]["other_info"] = result_dict_other_info + prbs_all_result_dict_other_info + + result_dict_other_info = result_dict.get("other_info", "") + prbs_all_result_dict_other_info = prbs_all_result_dict["prbs_line_result_dict"].get("other_info", "") + prbs_all_result_dict["prbs_line_result_dict"]["other_info"] = result_dict_other_info + prbs_all_result_dict_other_info + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + return prbs_all_result_dict + return prbs_all_result_dict + + @staticmethod + def prbs_int_start_f(**kwargs): + '''IntPhy prbs test''' + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + result_dict = kwargs["r_dict"] + + try: + # Because the upports imported may be different each time, need to obtain the upports again + f_obj.get_unit_port_list(upports) + f_obj.get_prbs_port_range() + ret, output = f_obj.start_test() + if ret is False: + other_info = result_dict.get("other_info", "") + result_dict["other_info"] = other_info + "prbs_int_start_f fail, output:%s\n" % output + log_error("prbs_int_start_f fail, output:%s" % output) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict + return ret_t, result_dict + + @staticmethod + def prbs_int_check_f(**kwargs): + '''IntPhy prbs results check''' + + successport = [] + errorport = [] + + f_obj = kwargs["f_obj"] + ret_t = kwargs["ret_t"] + upports = kwargs["uprt"] + result_dict = kwargs["r_dict"] + + try: + for port in upports: + bcm_port = f_obj.device_port_list[port - 1].bcm_port + unit_port = f_obj.device_port_list[port - 1].unit_port + port_info = "port:%d %s(%d)" % (port, bcm_port, unit_port) + ret, output = f_obj.check_test(port=port) + if ret is True: + successport.append(port) + log_debug("%-18s:prbs check success" % port_info) + else: + ret_t -= 1 + errorport.append(port) + output_info = result_dict["port_info_dict"][port]["log"] + result_dict["port_info_dict"][port]["log"] = output_info + "prbs_int_check_f fail\noutput:%s" % output + log_error("%-18s:prbs check fail\noutput:%s" % (port_info, output)) + except Exception as except_result: + msg = traceback.format_exc() + print("Exception_info:\n%s" % msg) + ret_t = -999 + return ret_t, result_dict, successport, errorport + return ret_t, result_dict, successport, errorport + + @staticmethod + def sdk_cmd_redirect_judge(redirect): + '''determine whether input redirection is enabled and set the redirect based on the incoming redirect''' + + if redirect == False and sdk_cmd_redirect_console == True: + PortLog.set_sdk_cmd_redirect_console(False) + elif redirect == True and sdk_cmd_redirect_console == False: + PortLog.set_sdk_cmd_redirect_console(True) + + @staticmethod + def test_return(**kwargs): + '''test case return result judgment''' + ret_t = kwargs["ret_t"] + test_type = kwargs.get("test_type", "") + result_dict = kwargs.get("result_dict", {}) + prbs_all_result_dict = kwargs.get("prbs_all_result_dict", {}) + return_dict = {} + errorports_flag = False # errorports > 0 is True + + if prbs_all_result_dict: + # prbs tests with external PHY return dictionaries with 3 side results, so separate judgments are made + # test_type、test_result assignment, when testing results on one side or the other + return_dict = copy.deepcopy(prbs_all_result_dict) + if "errorports" in return_dict["prbs_mac_result_dict"]: + if (len(return_dict["prbs_mac_result_dict"]["errorports"])) > 0: + errorports_flag = True + elif "errorports" in return_dict["prbs_sys_result_dict"]: + if (len(return_dict["prbs_sys_result_dict"]["errorports"])) > 0: + errorports_flag = True + elif "errorports" in return_dict["prbs_line_result_dict"]: + if (len(return_dict["prbs_line_result_dict"]["errorports"])) > 0: + errorports_flag = True + else: + errorports_flag = False + else: + return_dict = copy.deepcopy(result_dict) + return_dict["test_type"] = test_type + if ret_t < 0: + return_dict["test_result"] = False + else: + return_dict["test_result"] = True + + if "errorports" in return_dict: + if (len(return_dict["errorports"])) > 0: + errorports_flag = True + if ret_t < 0: + if port_log_info_print_to_console and errorports_flag: + # Control macros enabled: prints the log of the entire test flow to the console when the test fails and errorports > 0 + print(global_port_log_info) + return return_dict + return return_dict + +class PortLog(): + '''port log macro control class''' + + @classmethod + def get_log_also_print_to_console(cls): + '''set control macros: print out the log at the same time''' + + log_debug("get_log_also_print_to_console: %r" % log_also_print_to_console) + return log_also_print_to_console + + @staticmethod + def set_log_also_print_to_console(console_val): + '''set control macros: print out the log at the same time''' + + global log_also_print_to_console + log_also_print_to_console = console_val + log_debug("set_log_also_print_to_console: %r" % log_also_print_to_console) + + @classmethod + def get_cmd_also_print_to_console(cls): + '''set control macros: print out the log at the same time''' + + log_debug("get_cmd_also_print_to_console: %r" % cmd_also_print_to_console) + return cmd_also_print_to_console + + @staticmethod + def set_cmd_also_print_to_console(console_val): + '''set control macros: print out the results of execute cmd at the same time''' + + global cmd_also_print_to_console + cmd_also_print_to_console = console_val + log_debug("set_cmd_also_print_to_console: %r" % cmd_also_print_to_console) + + @classmethod + def get_cmd_output_also_print_to_console(cls): + '''set control macros: print out the results of execute cmd at the same time''' + + log_debug("get_cmd_output_also_print_to_console: %r" % cmd_output_also_print_to_console) + return cmd_output_also_print_to_console + + @staticmethod + def set_cmd_output_also_print_to_console(console_val): + '''set control macros: print out the results of execute cmd at the same time''' + + global cmd_output_also_print_to_console + cmd_output_also_print_to_console = console_val + log_debug("set_cmd_output_also_print_to_console: %r" % cmd_output_also_print_to_console) + + @classmethod + def get_port_log_info_print_to_console(cls): + '''set control macros: prints the log of the entire test flow to the console when the test fails''' + + log_debug("get_port_log_info_print_to_console: %r" % port_log_info_print_to_console) + return port_log_info_print_to_console + + @staticmethod + def set_port_log_info_print_to_console(console_val): + '''set control macros: prints the log of the entire test flow to the console when the test fails''' + + global port_log_info_print_to_console + port_log_info_print_to_console = console_val + log_debug("set_port_log_info_print_to_console: %r" % port_log_info_print_to_console) + + @classmethod + def get_sdk_cmd_redirect_console(cls): + '''set control macros: enable input redirection cmd + < /dev/null''' + + log_debug("get_sdk_cmd_redirect_console: %r" % sdk_cmd_redirect_console) + return sdk_cmd_redirect_console + + @staticmethod + def set_sdk_cmd_redirect_console(console_val): + '''set control macros: enable input redirection cmd + < /dev/null''' + + global sdk_cmd_redirect_console + sdk_cmd_redirect_console = console_val + log_debug("set_sdk_cmd_redirect_console: %r" % sdk_cmd_redirect_console) + +def hsdk_check(): + if global_port_config.get("flag", False) is False: + pt = PortHsdkTest() + if global_port_config.get("hsdk_device", 0) == 1: + return True + else: + return False + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def test(): + pr = PortPrbsTest() + pr.clear_port_prbs() + pr.init_port_prbs() + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("mac", i + 1) + print (ret) + print (result) + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("sys", i + 1) + print (ret) + print (result) + for i in range(len(pr.bcm_ports)): + ret, result = pr.get_port_prbs_result("line", i + 1) + print (ret) + print (result) + pr.clear_port_prbs() + + +if __name__ == '__main__': + main() + + +''' +portts = PortTest() + + +portts.init_port_prbs() +for i in range(64): + portts.set_port_prbs((i+1),1) + # portts.set_port_prbs(2,1) + +time.sleep(5) + +for i in range(64): + print portts.get_port_prbs_result((i+1)) + # print portts.get_port_prbs_result(2) + +for i in range(64): + portts.set_port_prbs((i+1),0) + + +#status = get_port_status(i + 1) +''' diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/portutil.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/portutil.py new file mode 100644 index 000000000000..4ba910ac41b3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/portutil.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python + +import click +import re +import json +import collections + +from sfputil.main import * +from rjutil.baseutil import get_machine_info +from rjutil.baseutil import get_platform_info + +SAI_PROFILE = "sai.profile" +SAI_PROFILE_PREDIX = "SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/" +CONFIG_DB_JSON_PATH = "/etc/sonic/config_db.json" +LANE_MAX = 4 + +global_speed_preemphasis = { +"x86_64-ragile_b6520-64cq-r0":{ + "10G_40G":["0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", "0x135001", + "0x135001"], \ + "25g_100G":["0x154609", "0x154609", "0x154609", "0x154609", "0x12480a", "0x12480a", "0x154609", + "0x12480a", "0x0f4b0a", "0x0f4b0a", "0x12480a", "0x12480a", "0x0f4b0a", "0x0f4b0a", + "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", + "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", + "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", + "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", + "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", + "0x0f4b0a", "0x0f4b0a", "0x0f4b0a", "0x12480a", "0x12480a", "0x12480a", "0x12480a", + "0x12480a", "0x12480a", "0x12480a", "0x12480a", "0x154609", "0x154609", "0x154609", + "0x154609"] + }, +"x86_64-ragile_b6510-48vs8cq-r0":{ + "10G_40G":["0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", + "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", + "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", + "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", + "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", + "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", + "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", + "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02", "0x154d02"], \ + "25G_100G":["0x0f480d", "0x0f480d", "0x0f480d", "0x0f480d", "0x0f480d", "0x0f480d", "0x0d4b0c", + "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", + "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", + "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", + "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", + "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", + "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", + "0x0d4b0c", "0x0d4b0c", "0x0d4b0c", "0x0f480d", "0x0f480d", "0x0f480d", "0x0f480d"] + } +} + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + + +class PortClass(object): + + + def __init__(self, lport = 0, interface = "", logic_port = 0, phy_port = 0, cmd_speed = 0, + phy_speed = 0): + self._lport = lport + self._interface = interface + self._logic_port = logic_port + self._phy_port = phy_port + self._cmd_speed = cmd_speed + self._phy_speed = phy_speed + + @property + def lport(self): + return self._lport + + @property + def interface(self): + return self._interface + + @property + def logic_port(self): + return self._logic_port + + @property + def phy_port(self): + return self._phy_port + + @property + def cmd_speed(self): + return self._cmd_speed + + @property + def phy_speed(self): + return self._phy_speed + + def set_lport(self, lport): + self._lport = lport + + def set_interface(self, interface): + self._interface = interface + + def set_logic_port(self, logic_port): + self._logic_port = logic_port + + def set_phy_port(self, phy_port): + self._phy_port = phy_port + + def set_cmd_speed(self, cmd_speed): + self._cmd_speed = cmd_speed + + def set_phy_speed(self, phy_speed): + self._phy_speed = phy_speed + + +class ReUtil(object): + + + @staticmethod + def is_portmap_line(line): + if re.search('portmap_(.*?)=(.*?):(.*?)$', line): + return True + return False + + @staticmethod + def is_preemphasis_line(line): + if re.search('serdes_preemphasis_lane([0-9])_([0-9]+)=(.*?)$', line): + return True + return False + + @staticmethod + def getre_portmap_phy_port(line): + return int(re.findall(r"portmap_.*?=(.*?):.*?$", line)[0]) + + @staticmethod + def getre_portmap_logic_port(line): + return int(re.findall(r"portmap_(.*?)=.*?:.*?$", line)[0]) + + @staticmethod + def getre_portmap_phy_speed(line): + return int(re.findall(r"portmap_.*?=.*?:([0-9]+).*?$", line)[0]) + + @staticmethod + def getre_preemphasis_logic_port(line): + return int(re.findall(r"serdes_preemphasis_lane.*?_([0-9]+)=.*?$", line)[0]) + + @staticmethod + def getre_preemphasis_pree_value(line): + return re.findall(r"serdes_preemphasis_lane.*?_[0-9]+=(.*?)$", line)[0] + + @staticmethod + def setre_portmap_speed(line, speed): + return re.sub(r'portmap_(.*?)=(.*?):[0-9]+(.*?)$', r'portmap_\1=\2:%d\3' % speed, line) + + @staticmethod + def setre_preemphasis_pree_value(line, value): + return re.sub(r'serdes_preemphasis_lane([0-9])_([0-9]+)=(.*?)$', + r'serdes_preemphasis_lane\1_\2=%s' % value, line) + + + +class PortUtil(object): + + + _config_json_path = CONFIG_DB_JSON_PATH + _config_bcm_path = "" + _port_config_path = "" + _device_port_list = [] + + def __init__(self): + self._config_json_file = open(self.config_json_path, 'r+') + self._config_bcm_file = open(self.config_bcm_path, 'r+') + self._port_config_file = open(self.port_config_path, 'r+') + self._parse_port_config() + self._parse_config_json() + self._parse_config_bcm() + + def __del__(self): + self._config_json_file.flush() + self._config_bcm_file.flush() + self._port_config_file.flush() + self._config_json_file.close() + self._config_bcm_file.close() + self._port_config_file.close() + + @property + def device_port_list(self): + return self._device_port_list + + @property + def config_json_path(self): + return self._config_json_path + + @property + def config_bcm_path(self): + if self._config_bcm_path == "": + (platform, hwsku) = get_platform_and_hwsku() + platform_path = "/".join([PLATFORM_ROOT_PATH, platform]) + hwsku_path = "/".join([platform_path, hwsku]) + saiprofile_path = "/".join([hwsku_path, SAI_PROFILE]) + with open(saiprofile_path, "r") as saiprofile_f: + for line in saiprofile_f: + if(re.search('%s(.*?)$' % SAI_PROFILE_PREDIX, line)): + config_bcm = re.findall(r"%s(.*?)$" % SAI_PROFILE_PREDIX, line)[0] + self._config_bcm_path = "/".join([hwsku_path, config_bcm]) + return self._config_bcm_path + + @property + def port_config_path(self): + if self._port_config_path == "": + self._port_config_path = get_path_to_port_config_file() + return self._port_config_path + + def sync_cmd_speed(self): + self._config_bcm_file.seek(0) + lines = self._config_bcm_file.readlines() + self._config_bcm_file.seek(0) + for line in lines: + result = "" + if ReUtil.is_portmap_line(line): + phy_port = ReUtil.getre_portmap_phy_port(line) + logic_port = ReUtil.getre_portmap_logic_port(line) + phy_speed = ReUtil.getre_portmap_phy_speed(line) + for port in self._device_port_list: + port_index = self._device_port_list.index(port) + if port.phy_port == phy_port: + if self._get_speed_mask()[port_index] == 0 or port.cmd_speed == phy_speed: + break + port.set_phy_speed(phy_speed) + result = ReUtil.setre_portmap_speed(line, port.cmd_speed) + break + if result == "": + result = line + self._config_bcm_file.write(result) + return True + + def set_port_preem(self): + try: + speed_preemphasis = global_speed_preemphasis[get_platform_info(get_machine_info())] + except Exception, err: + return False + self._config_bcm_file.seek(0) + lines = self._config_bcm_file.readlines() + self._config_bcm_file.seek(0) + for line in lines: + result = "" + if ReUtil.is_preemphasis_line(line): + logic_port = ReUtil.getre_preemphasis_logic_port(line) + value = ReUtil.getre_preemphasis_pree_value(line) + for port in self._device_port_list: + port_index = self._device_port_list.index(port) + if port.logic_port == logic_port: + if port.phy_speed == 10 or port.phy_speed == 40: + preem_value = speed_preemphasis["10G_40G"] + elif port.phy_speed == 25 or port.phy_speed == 100: + preem_value = speed_preemphasis["25G_100G"] + else : + break + if preem_value[port_index] == value: + break + result = ReUtil.setre_preemphasis_pree_value(line, preem_value[port_index]) + break + if result == "": + result = line + self._config_bcm_file.write(result) + return True + + def _parse_port_config(self): + lport_num = 0 + for line in self._port_config_file: + line.strip() + if(len(line.split()) and re.search("Ethernet[0-9]+", line.split()[0])): + lport_num = lport_num + 1 + self._device_port_list.append(PortClass(lport = lport_num, + interface = line.split()[0], phy_port = int(line.split()[1].split(',')[0]))) + + def _parse_config_json(self): + config_json_dict = json.load(self._config_json_file, + object_pairs_hook = collections.OrderedDict) + for key in config_json_dict["PORT"].keys(): + if config_json_dict["PORT"][key].__contains__("speed"): + for port in self._device_port_list: + if port.interface == key: + port.set_cmd_speed(int(config_json_dict["PORT"][key]["speed"]) / 1000) + break + + def _parse_config_bcm(self): + for line in self._config_bcm_file: + if ReUtil.is_portmap_line(line): + phy_port = ReUtil.getre_portmap_phy_port(line) + logic_port = ReUtil.getre_portmap_logic_port(line) + phy_speed = ReUtil.getre_portmap_phy_speed(line) + for port in self._device_port_list: + if port.phy_port == phy_port: + port.set_logic_port(logic_port) + port.set_phy_speed(phy_speed) + break + + def _get_speed_mask(self): + interfaces_num = [int(port.interface[len("Ethernet"):]) for port in self._device_port_list] + interfaces_mask = [1 for port in self._device_port_list] + for port in self._device_port_list : + port_index = self._device_port_list.index(port) + port_num = interfaces_num[port_index] + if(port_num % LANE_MAX == 0 and (port_num + LANE_MAX - 1) in interfaces_num): + lane_ports = self._device_port_list[port_index:port_index + LANE_MAX] + interfaces_speed = [lane.cmd_speed for lane in lane_ports] + for interface_speed in interfaces_speed: + if interfaces_speed[0] != interface_speed: + for i in range(LANE_MAX): + interfaces_mask[port_index + i] = 0 + break + return interfaces_mask + + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def sync(): + pt = PortUtil() + pt.sync_cmd_speed() + click.echo("port sync success") + +@main.command() +def setpreem(): + pt = PortUtil() + pt.set_port_preem() + click.echo("port setpreem success") + +@main.command() +def start(): + '''start port control''' + pt = PortUtil() + pt.sync_cmd_speed() + pt.set_port_preem() + click.echo("port start success") + +@main.command() +def stop(): + '''stop port control ''' + pass + +if __name__ == '__main__': + main() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragilecommon.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragilecommon.py new file mode 100644 index 000000000000..05070f7b5820 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragilecommon.py @@ -0,0 +1,692 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +################################Driver load adaptation####################################################### +# load sysfs +################################################################################################### + +fancontrol_loc = "/usr/local/bin" +fancontrol_config_loc = "/usr/local/bin" + +PCA9548BUSEND = "PCA9548BUSEND" +DEVICE = "DEVICE" +GLOBALCONFIG = "GLOBALCONFIG" +PCA9548START = "PCA9548START" +DRIVERLISTS = "DRIVERLISTS" +INIT_PARAM = "INIT_PARAM" +RAGILE_CARDID = "RAGILE_CARDID" +RAGILE_PRODUCTNAME = "RAGILE_PRODUCTNAME" +E2_PROTECT = "E2_PROTECT" +FAN_PROTECT = "FAN_PROTECT" +MONITOR_CONST = "MONITOR_CONST" +MAC_LED_RESET = "MAC_LED_RESET" + +RAGILE_PART_NUMBER = "RJ000001" +RAGILE_LABEL_REVISION = "R01" +RAGILE_ONIE_VERSION = "2018.02" +RAGILE_MAC_SIZE = 3 +RAGILE_MANUF_NAME = "Ragile" +RAGILE_MANUF_COUNTRY = "CHN" +RAGILE_VENDOR_NAME = "Ragile" +RAGILE_DIAG_VERSION = "0.1.0.15" +RAGILE_SERVICE_TAG = "www.ragile.com.cn" + +DEV_LEDS = {} +MEM_SLOTS = [] + +LOCAL_LED_CONTROL = { + "CLOSE":{}, + "OPEN":{} +} + +FIRMWARE_TOOLS = {} +# Rev. Desktop module +STARTMODULE = { + "fancontrol":1, + "avscontrol":1 + } + +i2ccheck_params = {"busend":"i2c-66","retrytime":6} + +################################################################################################### +##### Fan card ID reference table +################################################################################################### +FANS_DEF = { + 0x8100:"M6500-FAN-F", + 0x8101:"M6510-FAN-F", + 0x8102:"M6520-FAN-F", + 0x8103:"M6510-FAN-R" +} + +factest_module = { + "sysinfo_showfanmsg":1, + "sysinfo_showPsumsg":1, + "sysinfo_showrestfanmsg":0, + "sysinfo_showrestpsumsg":0 +} + +#################Fan speed Adjustment Parameters############################## +MONITOR_TEMP_MIN = 38 # Speed regulating start temperature +MONITOR_K = 11 # Speed control strategy +MONITOR_MAC_IN = 35 # Temperature difference between MAC and chip (spare) +MONITOR_DEFAULT_SPEED = 0x60 # default speed +MONITOR_MAX_SPEED = 0xFF # maximum speed (full revolution) +MONITOR_MIN_SPEED = 0x33 # minimum speed +MONITOR_MAC_ERROR_SPEED = 0XBB # MAC abnormal speed +MONITOR_FAN_TOTAL_NUM = 4 # 3+1 Redundancy design, fault has been reported syslog +MONITOR_MAC_UP_TEMP = 50 # MAC compare with the temperature inlet up +MONITOR_MAC_LOWER_TEMP = -50 # MAC compare with the inlet temperature port down +MONITOR_MAC_MAX_TEMP = 100 # + +MONITOR_FALL_TEMP = 4 # Adjustable descent temperature +MONITOR_MAC_WARNING_THRESHOLD = 100 # 100 +MONITOR_OUTTEMP_WARNING_THRESHOLD = 85 +MONITOR_BOARDTEMP_WARNING_THRESHOLD = 85 +MONITOR_CPUTEMP_WARNING_THRESHOLD = 85 +MONITOR_INTEMP_WARNING_THRESHOLD = 70 # 70 + +MONITOR_MAC_CRITICAL_THRESHOLD = 105 # 105 +MONITOR_OUTTEMP_CRITICAL_THRESHOLD = 90 # 90 +MONITOR_BOARDTEMP_CRITICAL_THRESHOLD = 90 # 90 +MONITOR_CPUTEMP_CRITICAL_THRESHOLD = 100 # 100 +MONITOR_INTEMP_CRITICAL_THRESHOLD = 80 # 80 +MONITOR_CRITICAL_NUM = 3 # Restart the number +MONITOR_SHAKE_TIME = 20 # Stabilization interval +MONITOR_INTERVAL = 60 + +MONITOR_MAC_SOURCE_SYSFS = 0 # 1 is get mac temperature from sysfs, 0 is get mac temperature from bcmcmd +MONITOR_MAC_SOURCE_PATH = None # sysfs file path + +################################################################### + + +#####################MAC regulating parameters(B6510)#################################### +MAC_AVS_PARAM ={ + 0x72:0x0384 , + 0x73:0x037e , + 0x74:0x0378 , + 0x75:0x0372 , + 0x76:0x036b , + 0x77:0x0365 , + 0x78:0x035f , + 0x79:0x0359 , + 0x7a:0x0352 , + 0x7b:0x034c , + 0x7c:0x0346 , + 0x7d:0x0340 , + 0x7e:0x0339 , + 0x7f:0x0333 , + 0x80:0x032d , + 0x81:0x0327 , + 0x82:0x0320 , + 0x83:0x031a , + 0x84:0x0314 , + 0x85:0x030e , + 0x86:0x0307 , + 0x87:0x0301 , + 0x88:0x02fb , + 0x89:0x02f5 , + 0x8A:0x02ee +} + +# defaule 6520 template configuration +MAC_DEFAULT_PARAM = { + "type": 1, # type 1 ndicates that the default is not in scope / 0 dicates that the adjustment is not in the range + "default":0x74, # Used with Type + "loopaddr":0x00, # AVS loop address + "loop":0x00, # AVS loop value + "open":0x00, # close write protected value + "close":0x40, # open write protected value + "bus":2, # AVSI2C bus address + "devno":0x60, # AVS address + "addr":0x21, # AVS regulating the address + "protectaddr":0x10, # AVS write protected address + "sdkreg":"DMU_PCU_OTP_CONFIG_8", # SDK register name + "sdktype": 1, # type 0 means no shift is required / 1 means it needs to shift + "macregloc":24 , # Shift operation + "mask": 0xff # Post-shift mask +} + +MONITOR_SYS_LED = [ + {"bus":2,"devno":0x33, "addr":0xb2, "yellow":0x06, "red":0x02,"green":0x04}, + {"bus":2,"devno":0x32, "addr":0x72, "yellow":0x06, "red":0x02,"green":0x04}] + +MONITOR_SYS_FAN_LED =[ + {"bus":2,"devno":0x33, "addr":0xb4, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FANS_LED = [ + {"bus":2,"devno":0x32, "addr":0x23, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x24, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x25, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x26, "green":0x09, "red":0x0a}] + + +MONITOR_SYS_PSU_LED =[ + {"bus":2,"devno":0x33, "addr":0xb3, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FAN_STATUS = [ + {'status':'green' , 'minOkNum':4,'maxOkNum':4}, + {'status':'yellow', 'minOkNum':3,'maxOkNum':3}, + {'status':'red' , 'minOkNum':0,'maxOkNum':2}, + ] + +MONITOR_PSU_STATUS = [ + {'status':'green' , 'minOkNum':2,'maxOkNum':2}, + {'status':'yellow', 'minOkNum':1,'maxOkNum':1}, + {'status':'red' , 'minOkNum':0,'maxOkNum':0}, + ] + +MONITOR_DEV_STATUS = {} +MONITOR_DEV_STATUS_DECODE = {} +DEV_MONITOR_PARAM = {} +SLOT_MONITOR_PARAM = {} +MANUINFO_CONF = {} + + +fanloc = {"name":"fanset","location":"0-0032/fan_speed_set"} +#####################MAC Regulating parameters#################################### + + +####================================Adapter area================================ +# RAGILE_COMMON Universal configuration head +# platform Personality configuration header + +PCA9548START = 11 +PCA9548BUSEND = 74 + +RAGILE_CARDID = 0x00004040 +RAGILE_PRODUCTNAME = "ragile_b6510" + +FAN_PROTECT = {"bus":0, "devno":0x32, "addr":0x19, "open":0x00, "close":0x0f} +rg_eeprom = "1-0056/eeprom" +E2_LOC = {"bus":1, "devno":0x56} +E2_PROTECT ={"bus":1, "devno":0x33, "addr":0xb0, "open":0, "close":1} +MAC_LED_RESET = {"pcibus":8, "slot":0, "fn":0, "bar":0, "offset":64, "reset":0x98} + +INIT_PARAM = [ + {"loc":"1-0034/sfp_enable","value": "01"}, + {"loc":"2-0035/sfp_enable2","value":"ff"}, + {"loc":"2-0033/mac_led", "value":"ff"}, + {"loc":"1-0034/sfp_txdis1","value":"00"}, + {"loc":"1-0034/sfp_txdis2","value":"00"}, + {"loc":"1-0034/sfp_txdis3","value":"00"}, + {"loc":"1-0036/sfp_txdis4","value":"00"}, + {"loc":"1-0036/sfp_txdis5","value":"00"}, + {"loc":"1-0036/sfp_txdis6","value":"00"}, + {"loc":fanloc["location"], "value":"80"} +] + +INIT_COMMAND = [ +] + +CPLDVERSIONS = [ + {"loc":"2-0033/cpld_version","des":"MAC板上CPLDA"}, + {"loc":"2-0035/cpld_version","des":"MAC板上CPLDB"}, + {"loc":"2-0037/cpld_version","des":"CPU板上cpld"} +] + +# drivers list +DRIVERLISTS = [ + "i2c_dev", + "i2c_algo_bit", + "i2c_gpio", + "i2c_mux", + "i2c_mux_pca9641", + "i2c_mux_pca954x", # force_deselect_on_exit=1 + "eeprom", + "at24", + "rg_sff", + "ragile_b6510_platform", + "ragile_platform", + "rg_avs", + "rg_cpld", + "rg_fan", + "rg_psu", + "csu550", + "rg_gpio_xeon", + # IPMIdriver + "ipmi_msghandler", + "ipmi_devintf", + "ipmi_si", +] + +DEVICE = [ + {"name":"pca9641","bus":0 ,"loc":0x10 }, + {"name":"pca9548","bus":2 ,"loc":0x70 }, + {"name":"lm75","bus": 2, "loc":0x48 }, + {"name":"lm75","bus": 2, "loc":0x49 }, + {"name":"lm75","bus": 2, "loc":0x4a }, + {"name":"24c02","bus":1 , "loc":0x56 }, + {"name":"rg_cpld","bus":2 ,"loc":0x33 }, + {"name":"rg_cpld","bus":2 ,"loc":0x35 }, + {"name":"rg_cpld","bus":2 ,"loc":0x37 }, + {"name":"rg_avs","bus": 2 ,"loc":0x60 }, + {"name":"pca9548","bus":0,"loc":0x70 }, + {"name":"pca9548","bus":1,"loc":0x71 }, + {"name":"pca9548","bus":1,"loc":0x72 }, + {"name":"pca9548","bus":1,"loc":0x73 }, + {"name":"pca9548","bus":1,"loc":0x74 }, + {"name":"pca9548","bus":1,"loc":0x75 }, + {"name":"pca9548","bus":1,"loc":0x76 }, + {"name":"pca9548","bus":1,"loc":0x77 }, + {"name":"rg_fan","bus":3,"loc":0x53 }, + {"name":"rg_fan","bus":4,"loc":0x53 }, + {"name":"rg_fan","bus":5,"loc":0x53 }, + #{"name":"rg_fan","bus":6,"loc":0x53 }, # Fan processing separately + {"name":"rg_psu","bus":7 ,"loc":0x50 }, + {"name":"csu550","bus":7 ,"loc":0x58 }, + {"name":"rg_psu","bus":8 ,"loc":0x53 }, + {"name":"csu550","bus":8 ,"loc":0x5b }, +] + +#####################FRU information adaptation################################# +E2TYPE = {"1": "tlveeprom", + "2": "x86cpueeprom", + "3": "bmceeprom", + "4": "cpueeprom", + "5": "maceeprom", + "6": "sloteeprom", + "7": "fanconnecteeprom", + "8": "M1HFANI-F", + "9": "M1HFANI-R", + "A": "M2HFANI-F", + "B": "M2HFANI-R", + "C": "psu"} +FRULISTS = [] +################################Test fit area####################################################### +# need load sysfs +fanlevel_6510 = { + "level":[51,150,255], + "low_speed":[500,7500,17000], + "high_speed":[11000,22500,28500] +} + +fanlevel_6520 = { + "level":[75,150,255], + "low_speed":[750,4250,6750], + "high_speed":[4500,7500,10000] +} + +fanlevel = fanlevel_6520 + +TEMPIDCHANGE = { + "lm75in":"入风口", + "lm75out":"出风口", + "lm75hot":"最热点", + "入风口":"lm75in", + "出风口":"lm75out", + "最热点":"lm75hot", +} + +# Raw measurement module +FACTESTMODULE = { } + +##################################Test menu item +item1 = {"name":"单项测试", "deal" :"test_signal", "childid":1} +test_sys_reload_item = {"name":"整机复位", "deal" :"test_sys_reload"} + +test_sys_item = { "name":"产品信息检测", "deal" :"test_sysinfo"} +test_temp_item = { "name":"温度检测", "deal" :"test_tempinfo"} +test_mem_item = { "name":"内存测试", "deal" :"test_cpumemoryinfo"} +test_hd_item = { "name":"硬盘测试", "deal" :"test_hard"} +test_rtc_item = { "name":"RTC测试 ", "deal" :"test_rtc"} +test_i2c_item = { "name":"I2c测试 ", "deal" :"test_i2c"} +test_cpld_item = { "name":"CPLD测试", "deal" :"test_cpld"} +test_portframe_item = { "name":"端口收发帧测试", "deal" :"test_portframe"} +test_sysled_item = { "name":"指示灯测试", "deal" :"test_led"} +test_fan_item = { "name":"风扇状态检测", "deal" :"test_fan"} +test_power_item = { "name":"电源状态检测", "deal" :"test_power"} +test_usb_item = { "name":"USB测试", "deal" :"test_usb"} +test_prbs_item = { "name":"PRBS测试", "deal" :"test_prbs"} +test_portbroadcast_item = { "name":"端口广播", "deal" :"test_portbroadcast"} + +test_debug_level = {"name":"调试更改", "deal" :"test_setdebug"} +test_log_level = {"name":"日志输出等级", "deal" :"test_loginfolevel"} +test_setmac = {"name":"setmac", "deal" :"test_setmac"} +test_setrtc = {"name":"设置RTC", "deal" :"test_set_rtc"} + +log_level_critical = {"name":"CRITICAL", "deal" :"test_log_critical"} +log_level_debug = {"name":"DEBUG", "deal" :"test_log_debug"} +log_level_error = {"name":"ERROR", "deal" :"test_log_error"} +log_level_info = {"name":"INFO", "deal" :"test_log_info"} +log_level_notset = {"name":"NOTSET", "deal" :"test_log_notset"} +log_level_warning = {"name":"WARNING", "deal" :"test_log_warning"} + + +test_e2_setmac_item = {"name":"E2SETMAC", "deal" :"test_e2_setmac"} +test_bmc_setmac_item = {"name":"BMCSETMAC", "deal" :"test_bmc_setmac"} +test_fan_setmac_item = {"name":"风扇SETMAC", "deal" :"test_fan_setmac"} + +alltest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_sysled_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item + ] + +looptest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item , +] + +diagtestall = [ +] + +menuList =[ + { + "menuid":0, "value":[ + {"name":"单项测试", "deal" :"test_signal", "childid":1}, + {"name":"所有测试", "deal" :"test_all"}, + {"name":"自动循环测试", "deal" :"test_loop"}, + #{"name":"拷机结果查看", "deal" :"test_loop_read"}, + #{"name":"拷机结果删除", "deal" :"test_loop_delete"}, + #{"name":"配置加载", "deal" :"test_config"}, + test_sys_reload_item, + {"name":"系统配置", "deal" :"test_sysconfig","childid":2}, + ] + }, + { + "menuid":1, "parentid":0, "value":[ + test_sys_item , + test_temp_item , + test_mem_item , + test_hd_item , + test_rtc_item , + test_i2c_item , + test_cpld_item , + test_portframe_item , + test_sysled_item , + test_fan_item , + test_power_item , + test_usb_item , + test_prbs_item , + test_portbroadcast_item , + ]}, + { + "menuid":2, "parentid":0, "value":[ + test_debug_level, + test_log_level , + test_setmac , + test_setrtc , + ]}, + { + "menuid":3, "parentid":2, "value":[ + log_level_critical , + log_level_debug , + log_level_error , + log_level_info , + log_level_notset , + log_level_warning , + ]}, + { + "menuid":4, "parentid":2, "value":[ + test_e2_setmac_item , + test_bmc_setmac_item, + test_fan_setmac_item, + ]}, +] + + +TESTCASE={ + "CPLD":[ + {"name":"CONNECT板CPLD-A" ,"cases":[ + {"name":"cpld32", "cmd":"grtd_test.py cpld_check 0 0x32 0xAA"}, + {"name":"cpld37", "cmd":"grtd_test.py cpld_check 2 0x37 0xAC"}, + ] + }, + {"name":"MAC板CPLD-A" ,"cases":[ + {"name":"cpld33", "cmd":"grtd_test.py cpld_check 2 0x33 0xAB"}, + {"name":"cpld34", "cmd":"grtd_test.py cpld_check 1 0x34 0xAA"}, + ] + }, + {"name":"MAC板CPLD-B" ,"cases":[ + {"name":"cpld36", "cmd":"grtd_test.py cpld_check 1 0x36 0xAA"}, + {"name":"cpld35", "cmd":"grtd_test.py cpld_check 2 0x35 0xAB"}, + ] + }, + ], + "TEMPERATURE":[ + { + "name":"-->温度测试" , "cases":[ + {"name":"入风口","cmd":"grtd_test.py temp 2-0048/hwmon/hwmon1/temp1_input"}, + {"name":"出风口","cmd":"grtd_test.py temp 2-0049/hwmon/hwmon2/temp1_input"}, + {"name":"最热点","cmd":"grtd_test.py temp 2-004a/hwmon/hwmon3/temp1_input"}, + ] + } + ], + "MEMTORY":{ + "cases":[ + {"name":"->内存测试 1M","cmd":"memtester 1M 1"}, + {"name":"->内存测试 2M","cmd":"memtester 2M 1"}, + {"name":"->内存测试 8M","cmd":"memtester 8M 1"}, +# {"name":"->内存测试 16M","cmd":"memtester 16M 1"}, +# {"name":"->内存测试 256M","cmd":"memtester 256M 1"}, + ] + }, + "SMARTCTLCMDS":{ + "cases":[ + {"name":"->硬盘信息查看", "cmd":"smartctl -i /dev/sda"}, + {"name":"->检查硬盘监控状态", "cmd":"smartctl -H /dev/sda"}, + ] + }, + "LED":[ + {"name":"端口点灯测试","cases":[ + {"name":"-> 红灯灭", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> 红灯亮", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> 恢复红灯灭", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + + {"name":"-> 黄灯灭", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> 黄灯亮", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> 恢复黄灯灭", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + ] + }, + {"name":"风扇1灯" ,"cases":[ + {"name":"-> 灯灭", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0b"}, + {"name":"-> 红灯", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0a"}, + {"name":"-> 绿灯", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + {"name":"-> 黄灯", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x08"}, + {"name":"-> 红灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0e"}, + {"name":"-> 绿灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0d"}, + {"name":"-> 黄灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0c"}, + {"name":"-> 恢复绿灯", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + ] + }, + {"name":"风扇2灯" ,"cases":[ + {"name":"-> 灯灭", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0b"}, + {"name":"-> 红灯", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0a"}, + {"name":"-> 绿灯", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + {"name":"-> 黄灯", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x08"}, + {"name":"-> 红灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0e"}, + {"name":"-> 绿灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0d"}, + {"name":"-> 黄灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0c"}, + {"name":"-> 恢复绿灯", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + ] + }, + {"name":"风扇3灯" ,"cases":[ + {"name":"-> 灯灭", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0b"}, + {"name":"-> 红灯", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0a"}, + {"name":"-> 绿灯", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + {"name":"-> 黄灯", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x08"}, + {"name":"-> 红灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0e"}, + {"name":"-> 绿灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0d"}, + {"name":"-> 黄灯闪烁", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0c"}, + {"name":"-> 恢复绿灯", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + ] + }, + {"name":"前面板CPU灯", "cases":[ + {"name":"-> 灯灭", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x00"}, + {"name":"-> 绿灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + {"name":"-> 红灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x02"}, + {"name":"-> 黄灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x03"}, + {"name":"-> 绿灯1/4s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x11"}, + {"name":"-> 绿灯1/2s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x21"}, + {"name":"-> 绿灯1s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x41"}, + {"name":"-> 绿灯2s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x81"}, + {"name":"-> 红灯1/4s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x12"}, + {"name":"-> 红灯1/2s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x22"}, + {"name":"-> 红灯1s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x42"}, + {"name":"-> 红灯2s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x82"}, + {"name":"-> 黄灯1/4s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x13"}, + {"name":"-> 黄灯1/2s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x23"}, + {"name":"-> 黄灯1s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x43"}, + {"name":"-> 黄灯2s闪烁 ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x83"}, + {"name":"-> 恢复绿灯", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + ] + }, + {"name":"前面板BMC灯" ,"cases":[ + {"name":"-> 灯灭", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x00"}, + {"name":"-> 红灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x01"}, + {"name":"-> 红灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x02"}, + {"name":"-> 绿灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x03"}, + {"name":"-> 绿灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + {"name":"-> 黄灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x05"}, + {"name":"-> 黄灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x06"}, + {"name":"-> 恢复绿灯", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + ] + }, + {"name":"前面板定位灯" , "cases":[ + {"name":"->灯灭","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + {"name":"->灯亮","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xfe"}, + {"name":"->恢复灯灭","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + ] + }, + + {"name":"前面板pwr灯" ,"cases":[ + {"name":"-> 灯灭", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x00"}, + {"name":"-> 红灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x01"}, + {"name":"-> 红灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x02"}, + {"name":"-> 绿灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x03"}, + {"name":"-> 绿灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + {"name":"-> 黄灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x05"}, + {"name":"-> 黄灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x06"}, + {"name":"-> 恢复绿灯", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + ] + }, + {"name":"前面板fan灯" ,"cases":[ + {"name":"-> 灯灭", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x00"}, + {"name":"-> 红灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x01"}, + {"name":"-> 红灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x02"}, + {"name":"-> 绿灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x03"}, + {"name":"-> 绿灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + {"name":"-> 黄灯闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x05"}, + {"name":"-> 黄灯不闪烁", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x06"}, + {"name":"-> 恢复绿灯", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + ] + }, + + ], + "I2C":[ + # type 1 represents the fetched value compared to value + # type 2 represents return vaule is True or False + {"name":"I2C设备检测" ,"cases":[ + {"name":" PCA9641测试", "cmd":"grtd_test.py dev_rd 0 10 0","deal_type":2}, + {"name":" cpld32测试", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld33测试", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld34测试", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld35测试", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld36测试", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld37测试", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" 入风口LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" 出风口LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" 最热点LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" EEPROM", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" 端口1", "cmd":"grtd_test.py dev_rd 11 0050 0","deal_type":2}, + {"name":" 端口2", "cmd":"grtd_test.py dev_rd 12 0050 0","deal_type":2}, + {"name":" 端口3", "cmd":"grtd_test.py dev_rd 13 0050 0","deal_type":2}, + {"name":" 端口4", "cmd":"grtd_test.py dev_rd 14 0050 0","deal_type":2}, + {"name":" 端口5", "cmd":"grtd_test.py dev_rd 15 0050 0","deal_type":2}, + {"name":" 端口6", "cmd":"grtd_test.py dev_rd 16 0050 0","deal_type":2}, + {"name":" 端口7", "cmd":"grtd_test.py dev_rd 17 0050 0","deal_type":2}, + {"name":" 端口8", "cmd":"grtd_test.py dev_rd 18 0050 0","deal_type":2}, + {"name":" 端口9", "cmd":"grtd_test.py dev_rd 19 0050 0","deal_type":2}, + {"name":" 端口10", "cmd":"grtd_test.py dev_rd 20 0050 0","deal_type":2}, + {"name":" 端口11", "cmd":"grtd_test.py dev_rd 21 0050 0","deal_type":2}, + {"name":" 端口12", "cmd":"grtd_test.py dev_rd 22 0050 0","deal_type":2}, + {"name":" 端口13", "cmd":"grtd_test.py dev_rd 23 0050 0","deal_type":2}, + {"name":" 端口14", "cmd":"grtd_test.py dev_rd 24 0050 0","deal_type":2}, + {"name":" 端口15", "cmd":"grtd_test.py dev_rd 25 0050 0","deal_type":2}, + {"name":" 端口16", "cmd":"grtd_test.py dev_rd 26 0050 0","deal_type":2}, + {"name":" 端口17", "cmd":"grtd_test.py dev_rd 27 0050 0","deal_type":2}, + {"name":" 端口18", "cmd":"grtd_test.py dev_rd 28 0050 0","deal_type":2}, + {"name":" 端口19", "cmd":"grtd_test.py dev_rd 29 0050 0","deal_type":2}, + {"name":" 端口20", "cmd":"grtd_test.py dev_rd 30 0050 0","deal_type":2}, + {"name":" 端口21", "cmd":"grtd_test.py dev_rd 31 0050 0","deal_type":2}, + {"name":" 端口22", "cmd":"grtd_test.py dev_rd 32 0050 0","deal_type":2}, + {"name":" 端口23", "cmd":"grtd_test.py dev_rd 33 0050 0","deal_type":2}, + {"name":" 端口24", "cmd":"grtd_test.py dev_rd 34 0050 0","deal_type":2}, + {"name":" 端口25", "cmd":"grtd_test.py dev_rd 35 0050 0","deal_type":2}, + {"name":" 端口26", "cmd":"grtd_test.py dev_rd 36 0050 0","deal_type":2}, + {"name":" 端口27", "cmd":"grtd_test.py dev_rd 37 0050 0","deal_type":2}, + {"name":" 端口28", "cmd":"grtd_test.py dev_rd 38 0050 0","deal_type":2}, + {"name":" 端口29", "cmd":"grtd_test.py dev_rd 39 0050 0","deal_type":2}, + {"name":" 端口30", "cmd":"grtd_test.py dev_rd 40 0050 0","deal_type":2}, + {"name":" 端口31", "cmd":"grtd_test.py dev_rd 41 0050 0","deal_type":2}, + {"name":" 端口32", "cmd":"grtd_test.py dev_rd 42 0050 0","deal_type":2}, + {"name":" 端口33", "cmd":"grtd_test.py dev_rd 43 0050 0","deal_type":2}, + {"name":" 端口34", "cmd":"grtd_test.py dev_rd 44 0050 0","deal_type":2}, + {"name":" 端口35", "cmd":"grtd_test.py dev_rd 45 0050 0","deal_type":2}, + {"name":" 端口36", "cmd":"grtd_test.py dev_rd 46 0050 0","deal_type":2}, + {"name":" 端口37", "cmd":"grtd_test.py dev_rd 47 0050 0","deal_type":2}, + {"name":" 端口38", "cmd":"grtd_test.py dev_rd 48 0050 0","deal_type":2}, + {"name":" 端口39", "cmd":"grtd_test.py dev_rd 49 0050 0","deal_type":2}, + {"name":" 端口40", "cmd":"grtd_test.py dev_rd 50 0050 0","deal_type":2}, + {"name":" 端口41", "cmd":"grtd_test.py dev_rd 51 0050 0","deal_type":2}, + {"name":" 端口42", "cmd":"grtd_test.py dev_rd 52 0050 0","deal_type":2}, + {"name":" 端口43", "cmd":"grtd_test.py dev_rd 53 0050 0","deal_type":2}, + {"name":" 端口44", "cmd":"grtd_test.py dev_rd 54 0050 0","deal_type":2}, + {"name":" 端口45", "cmd":"grtd_test.py dev_rd 55 0050 0","deal_type":2}, + {"name":" 端口46", "cmd":"grtd_test.py dev_rd 56 0050 0","deal_type":2}, + {"name":" 端口47", "cmd":"grtd_test.py dev_rd 57 0050 0","deal_type":2}, + {"name":" 端口48", "cmd":"grtd_test.py dev_rd 58 0050 0","deal_type":2}, + {"name":" 端口49", "cmd":"grtd_test.py dev_rd 59 0050 0","deal_type":2}, + {"name":" 端口50", "cmd":"grtd_test.py dev_rd 60 0050 0","deal_type":2}, + {"name":" 端口51", "cmd":"grtd_test.py dev_rd 61 0050 0","deal_type":2}, + {"name":" 端口52", "cmd":"grtd_test.py dev_rd 62 0050 0","deal_type":2}, + {"name":" 端口53", "cmd":"grtd_test.py dev_rd 63 0050 0","deal_type":2}, + {"name":" 端口54", "cmd":"grtd_test.py dev_rd 64 0050 0","deal_type":2}, + {"name":" 端口55", "cmd":"grtd_test.py dev_rd 65 0050 0","deal_type":2}, + {"name":" 端口56", "cmd":"grtd_test.py dev_rd 66 0050 0","deal_type":2}, + {"name":" 端口57", "cmd":"grtd_test.py dev_rd 67 0050 0","deal_type":2}, + {"name":" 端口58", "cmd":"grtd_test.py dev_rd 68 0050 0","deal_type":2}, + {"name":" 端口59", "cmd":"grtd_test.py dev_rd 69 0050 0","deal_type":2}, + {"name":" 端口60", "cmd":"grtd_test.py dev_rd 70 0050 0","deal_type":2}, + {"name":" 端口61", "cmd":"grtd_test.py dev_rd 71 0050 0","deal_type":2}, + {"name":" 端口62", "cmd":"grtd_test.py dev_rd 72 0050 0","deal_type":2}, + {"name":" 端口63", "cmd":"grtd_test.py dev_rd 73 0050 0","deal_type":2}, + {"name":" 端口64", "cmd":"grtd_test.py dev_rd 74 0050 0","deal_type":2}, + ] + }, + ], +} + +PCIe_DEV_LIST = [] +PCIe_SPEED_ITEM = [] + +################################Test fit area####################################################### + + + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileconfig.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileconfig.py new file mode 100644 index 000000000000..ded98c5cfcd6 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileconfig.py @@ -0,0 +1,178 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +import sys +import os +import subprocess +import time +from rjutil.baseutil import get_machine_info +from rjutil.baseutil import get_platform_info +import binascii +import termios +import multiprocessing + + +def getdeviceplatform(): + x = get_platform_info(get_machine_info()) + if x != None: + filepath = "/usr/share/sonic/device/" + x + return filepath + + +platform = get_platform_info(get_machine_info()) # platform Obtaining platform information x86_64-ragile_b6520-64cq-r0 +platformpath = getdeviceplatform() # platformpath Gets the mapable Docker directory /usr/share/sonic/device/x86_64-ragile_b6520-64cq-r0 +MAILBOX_DIR = "/sys/bus/i2c/devices/" # sysfs Top-level directory +grtd_productfile = (platform + "_config").replace("-","_") +common_productfile = "ragilecommon" +configfile_pre = "/usr/local/bin/" # py path, use /usr/local/bin to subsequent revision +import sys +sys.path.append(platformpath) +sys.path.append(configfile_pre) + +def get_rjconfig_info(attr_key): + rjconf_filename = platformpath + "/plugins" + "/rj.conf" + if not os.path.isfile(rjconf_filename): + return None + with open(rjconf_filename) as rjconf_file: + for line in rjconf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0] == attr_key: + return tokens[1].strip() + return None + +##### BMC password ### +OPENBMC_PASSWORD = get_rjconfig_info("OPENBMC_PASSWORD") +OPENBMC_PASSWORD = OPENBMC_PASSWORD if(OPENBMC_PASSWORD != None) else "0penBmc" + +############################################################################################ +## When no personalization file exists, use a generic file +global module_product +if os.path.exists(configfile_pre + grtd_productfile + ".py"): + module_product = __import__(grtd_productfile, globals(), locals(), [], 0) +elif os.path.exists(configfile_pre + common_productfile + ".py"): + module_product = __import__(common_productfile, globals(), locals(), [], 0) +else: + print ("不存在配置文件,退出") + exit(-1) +############################################################################################ + +DEVICE = module_product.DEVICE + +########## Driver loading requires variables +# Get the differential platform configuration +RAGILE_GLOBALCONFIG ={ + "DRIVERLISTS":module_product.DRIVERLISTS, + "QSFP": {"startbus":module_product.PCA9548START, "endbus":module_product.PCA9548BUSEND},#顽固分子单独处理 + "DEVS": DEVICE +} +GLOBALCONFIG = RAGILE_GLOBALCONFIG +GLOBALINITPARAM = module_product.INIT_PARAM +GLOBALINITCOMMAND = module_product.INIT_COMMAND + +fancontrol_loc = module_product.fancontrol_loc +fancontrol_config_loc = module_product.fancontrol_config_loc +MAC_LED_RESET = module_product.MAC_LED_RESET +########### Starting die block variable +STARTMODULE = module_product.STARTMODULE +FIRMWARE_TOOLS = module_product.FIRMWARE_TOOLS + + +########## Production requires variables +FACTESTMODULE = module_product.FACTESTMODULE +TESTCASE = module_product.TESTCASE +menuList = module_product.menuList +alltest = module_product.alltest +diagtestall = module_product.diagtestall +looptest = module_product.looptest +fanloc = module_product.fanloc +fanlevel = module_product.fanlevel # Fan number adjustment level +TEMPIDCHANGE = module_product.TEMPIDCHANGE +CPLDVERSIONS = module_product.CPLDVERSIONS +RAGILE_CARDID = module_product.RAGILE_CARDID +RAGILE_PRODUCTNAME = module_product.RAGILE_PRODUCTNAME + +RAGILE_PART_NUMBER = module_product.RAGILE_PART_NUMBER +RAGILE_LABEL_REVISION = module_product.RAGILE_LABEL_REVISION +RAGILE_ONIE_VERSION = module_product.RAGILE_ONIE_VERSION +RAGILE_MAC_SIZE = module_product.RAGILE_MAC_SIZE +RAGILE_MANUF_NAME = module_product.RAGILE_MANUF_NAME +RAGILE_MANUF_COUNTRY = module_product.RAGILE_MANUF_COUNTRY +RAGILE_VENDOR_NAME = module_product.RAGILE_VENDOR_NAME +RAGILE_DIAG_VERSION = module_product.RAGILE_DIAG_VERSION +RAGILE_SERVICE_TAG = module_product.RAGILE_SERVICE_TAG + +E2_PROTECT = module_product.E2_PROTECT +E2_LOC = module_product.E2_LOC +FAN_PROTECT = module_product.FAN_PROTECT + +FANS_DEF = module_product.FANS_DEF +MONITOR_SYS_LED = module_product.MONITOR_SYS_LED +MONITOR_FANS_LED = module_product.MONITOR_FANS_LED +MONITOR_SYS_FAN_LED = module_product.MONITOR_SYS_FAN_LED +MONITOR_SYS_PSU_LED = module_product.MONITOR_SYS_PSU_LED +MONITOR_FAN_STATUS = module_product.MONITOR_FAN_STATUS +MONITOR_PSU_STATUS = module_product.MONITOR_PSU_STATUS +MONITOR_DEV_STATUS = module_product.MONITOR_DEV_STATUS +MONITOR_DEV_STATUS_DECODE = module_product.MONITOR_DEV_STATUS_DECODE +DEV_MONITOR_PARAM = module_product.DEV_MONITOR_PARAM +SLOT_MONITOR_PARAM = module_product.SLOT_MONITOR_PARAM + + +DEV_LEDS = module_product.DEV_LEDS +MEM_SLOTS = module_product.MEM_SLOTS + +MAC_AVS_PARAM = module_product.MAC_AVS_PARAM +MAC_DEFAULT_PARAM = module_product.MAC_DEFAULT_PARAM +E2TYPE = module_product.E2TYPE +FRULISTS = module_product.FRULISTS +rg_eeprom = "%d-%04x/eeprom" % (E2_LOC["bus"], E2_LOC["devno"]) +factest_module = module_product.factest_module + +LOCAL_LED_CONTROL = module_product.LOCAL_LED_CONTROL + +PCIe_DEV_LIST = module_product.PCIe_DEV_LIST +PCIe_SPEED_ITEM = module_product.PCIe_SPEED_ITEM +i2ccheck_params = module_product.i2ccheck_params +MANUINFO_CONF = module_product.MANUINFO_CONF + +class MONITOR_CONST: + TEMP_MIN = module_product.MONITOR_TEMP_MIN + K =module_product.MONITOR_K + MAC_IN =module_product.MONITOR_MAC_IN + DEFAULT_SPEED =module_product.MONITOR_DEFAULT_SPEED + MAX_SPEED =module_product.MONITOR_MAX_SPEED + MIN_SPEED =module_product.MONITOR_MIN_SPEED + MAC_ERROR_SPEED =module_product.MONITOR_MAC_ERROR_SPEED + FAN_TOTAL_NUM =module_product.MONITOR_FAN_TOTAL_NUM + MAC_UP_TEMP =module_product.MONITOR_MAC_UP_TEMP + MAC_LOWER_TEMP =module_product.MONITOR_MAC_LOWER_TEMP + MAC_MAX_TEMP = module_product.MONITOR_MAC_MAX_TEMP + + MAC_WARNING_THRESHOLD = module_product.MONITOR_MAC_WARNING_THRESHOLD + OUTTEMP_WARNING_THRESHOLD = module_product.MONITOR_OUTTEMP_WARNING_THRESHOLD + BOARDTEMP_WARNING_THRESHOLD = module_product.MONITOR_BOARDTEMP_WARNING_THRESHOLD + CPUTEMP_WARNING_THRESHOLD = module_product.MONITOR_CPUTEMP_WARNING_THRESHOLD + INTEMP_WARNING_THRESHOLD = module_product.MONITOR_INTEMP_WARNING_THRESHOLD + + MAC_CRITICAL_THRESHOLD = module_product.MONITOR_MAC_CRITICAL_THRESHOLD + OUTTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_OUTTEMP_CRITICAL_THRESHOLD + BOARDTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_BOARDTEMP_CRITICAL_THRESHOLD + CPUTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_CPUTEMP_CRITICAL_THRESHOLD + INTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_INTEMP_CRITICAL_THRESHOLD + CRITICAL_NUM = module_product.MONITOR_CRITICAL_NUM + SHAKE_TIME = module_product.MONITOR_SHAKE_TIME + MONITOR_INTERVAL= module_product.MONITOR_INTERVAL + MONITOR_FALL_TEMP = module_product.MONITOR_FALL_TEMP + + MONITOR_MAC_SOURCE_SYSFS = module_product.MONITOR_MAC_SOURCE_SYSFS + MONITOR_MAC_SOURCE_PATH = module_product.MONITOR_MAC_SOURCE_PATH + +FANCTROLDEBUG = 0 # 1 is open +DEVMONITORDEBUG = 0 # 1 is open + + + + + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileutil.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileutil.py new file mode 100644 index 000000000000..2d7b9b513143 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/ragileutil.py @@ -0,0 +1,2011 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +import sys +import os +import re +import subprocess +import syslog +import time +import binascii +import tty +import termios +import threading +import click +import mmap +from ragileconfig import * +# from fruutil import fru +from tabulate import tabulate +import readline +try: + from eepromutil.fru import * +except: + pass + +import logging.handlers +import shutil +import gzip +import glob + +MENUID = "menuid" +MENUPARENT = "parentid" +MENUVALUE = "value" +CHILDID = "childid" +MENUITEMNAME = "name" +MENUITEMDEAL = "deal" +GOBACK = "goBack" +GOQUIT = "quit" + +file_name = "/etc/init.d/opennsl-modules-3.16.0-5-amd64" +########################################################################## +# Error log level +########################################################################## +CRITICAL = 50 +FATAL = CRITICAL +ERROR = 40 +WARNING = 30 +WARN = WARNING +INFO = 20 +DEBUG = 10 +NOTSET = 0 + +levelNames = { + CRITICAL: 'CRITICAL', + ERROR: 'ERROR', + WARNING: 'WARNING', + INFO: 'INFO', + DEBUG: 'DEBUG', + NOTSET: 'NOTSET', + 'CRITICAL': CRITICAL, + 'ERROR': ERROR, + 'WARN': WARNING, + 'WARNING': WARNING, + 'INFO': INFO, + 'DEBUG': DEBUG, + 'NOTSET': NOTSET, +} + +TLV_INFO_ID_STRING = "TlvInfo\x00" +TLV_INFO_VERSION = 0x01 +TLV_INFO_LENGTH = 0x00 +TLV_INFO_LENGTH_VALUE = 0xba + +########################################################################## +# eeprom Information index definition +########################################################################## +TLV_CODE_PRODUCT_NAME = 0x21 +TLV_CODE_PART_NUMBER = 0x22 +TLV_CODE_SERIAL_NUMBER = 0x23 +TLV_CODE_MAC_BASE = 0x24 +TLV_CODE_MANUF_DATE = 0x25 +TLV_CODE_DEVICE_VERSION = 0x26 +TLV_CODE_LABEL_REVISION = 0x27 +TLV_CODE_PLATFORM_NAME = 0x28 +TLV_CODE_ONIE_VERSION = 0x29 +TLV_CODE_MAC_SIZE = 0x2A +TLV_CODE_MANUF_NAME = 0x2B +TLV_CODE_MANUF_COUNTRY = 0x2C +TLV_CODE_VENDOR_NAME = 0x2D +TLV_CODE_DIAG_VERSION = 0x2E +TLV_CODE_SERVICE_TAG = 0x2F +TLV_CODE_VENDOR_EXT = 0xFD +TLV_CODE_CRC_32 = 0xFE +_TLV_DISPLAY_VENDOR_EXT = 1 +TLV_CODE_RJ_CARID = 0x01 +_TLV_INFO_HDR_LEN = 11 + + +SYSLOG_IDENTIFIER = "UTILTOOL" + +# ========================== Syslog wrappers ========================== + +def log_info(msg, also_print_to_console=False): + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + + +def log_debug(msg, also_print_to_console=False): + try: + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + except Exception as e: + pass + + +def log_warning(msg, also_print_to_console=False): + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + + +def log_error(msg, also_print_to_console=False): + # msg = msg.decode('utf-8').encode('gb2312') + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +# bmc-console.log bmc_feed_watchdog.log log compression +class CompressedRotatingFileHandler(logging.handlers.RotatingFileHandler): + def doRollover(self): + """ + Do a rollover, as described in __init__(). + """ + if self.stream: + self.stream.close() + self.stream = None + if self.backupCount > 0: + for i in range(self.backupCount - 1, 0, -1): + sfn = "%s.%d.gz" % (self.baseFilename, i) + dfn = "%s.%d.gz" % (self.baseFilename, i + 1) + if os.path.exists(sfn): + if os.path.exists(dfn): + os.remove(dfn) + os.rename(sfn, dfn) + dfn = self.baseFilename + ".1.gz" + if os.path.exists(dfn): + os.remove(dfn) + # These two lines below are the only new lines. I commented out the os.rename(self.baseFilename, dfn) and + # replaced it with these two lines. + with open(self.baseFilename, 'rb') as f_in, gzip.open(dfn, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + self.mode = 'w' + self.stream = self._open() + + +class SETMACException(Exception): + def __init__(self, param='错误', errno="-1"): + err = "setmac出错[%s]: %s" % (errno, param) + Exception.__init__(self, err) + self.param = param + self.errno = errno + +def checkinput(b): + if b.isdigit() == False: + raise Exception("非法数字") + if int(b) > 0xff or int(b) < 100: + raise Exception("不在区间内") + +def checkinputproduct(b): + if b.isalnum() ==False: + raise Exception("非法字符串") + +def getInputSetmac(val): + bia = val.boardInfoArea + pia = val.productInfoArea + if bia != None: + a = raw_input("[板卡区]产品序列号:") + if len(a) != 13: + raise Exception("序列号长度不对") + checkinputproduct(a) + bia.boardSerialNumber = a + b = raw_input("[板卡区]产品版本号:(从100-255)") + checkinput(b) + b = "%0x" % int(b) + bia.boardextra1 = b.upper() + if pia != None: + a = raw_input("[产品区]产品序列号:") + if len(a) != 13: + raise Exception("序列号长度不对") + checkinputproduct(a) + pia.productSerialNumber = a + b = raw_input("[产品区]产品版本号:(从100-255)") + checkinput(b) + b = "%0x" % int(b) + pia.productVersion = b.upper() + return val + +''' +class FruUtil(): + def test(self): + ret = fru.E2Util.decodeBinName("/sys/bus/i2c/devices/4-0051/eeprom") + bia = ret.boardInfoArea + pia = ret.productInfoArea + print bia + print pia + + def setmac_InputBoardArea(self, bia): + if bia != None: + a = raw_input("[板卡区]产品序列号:") + bia.boardSerialNumber = a + b = raw_input("[板卡区]产品版本号:(从1-255)") + bia.boardextra1 = b.upper() + return bia + + def getInputSetmac(self, val): + bia = val.boardInfoArea + pia = val.productInfoArea + if bia != None: + a = raw_input("[板卡区]产品序列号:") + bia.boardSerialNumber = a + b = raw_input("[板卡区]产品版本号:(从1-255)") + bia.boardextra1 = b.upper() + if pia != None: + a = raw_input("[产品区]产品序列号:") + pia.productSerialNumber = a + b = raw_input("[产品区]产品版本号:(从1-255)") + pia.productVersion = b.upper() + if pia.productExtra2 != None: + b = raw_input("[产品区]MAC地址:") + pia.productExtra2 = fru.E2Util.encodeMac(b.upper()) + + if pia.productExtra3 != None: + b = raw_input("[产品区]MAC数量:") + pia.productExtra3 = fru.E2Util.encodeMacLen(b) + result = fru.E2Util.generateBinBySetMac(bia, pia) + return result + + def globalsetmac(self, type1): + msg = type1[0] + fruMsg = self.getfruMsg(msg['bus'], msg['loc']) + result = self.getInputSetmac(fruMsg) + I2CUTIL.writeToE2(msg['bus'], msg['loc'], result.bindata) + + def dumpValueByI2c(self, bus, loc): + str = "" + for i in range(256): + ret,val = rji2cget(bus, loc, i) + str += chr(strtoint(val)) + return str + + def fansetmac(self, vals): + x = sorted(vals,lambda x,y: cmp(x["name"], y["name"])) + for item in x: + fruMsg = self.getfruMsg(item['bus'], item['loc']) + print "%s:"% item['name'] + result = self.getInputSetmac(fruMsg) + I2CUTIL.writeToE2(item['bus'], item['loc'], result.bindata) + pass + + def getsyseepromDict(self): + ret = get_sys_eeprom() + ret_t = {} + for item in ret: + ret_t[item['code']] = item['value'] + return ret_t + + def cpufrusetmac(self, vals): + msg = vals[0] + fruMsg = self.getfruMsg(msg['bus'], msg['loc']) + bia = fruMsg.boardInfoArea + pia = fruMsg.productInfoArea + + bia = self.setmac_InputBoardArea(bia) + sysee = self.getsyseepromDict() + pia.productName = sysee[33] + pia.productPartModelName = sysee[34] + pia.productVersion = sysee[38] + pia.productSerialNumber = sysee[35] + pia.productExtra2 = fru.E2Util.encodeMac(sysee[36].replace(":","")) + pia.productExtra3 = fru.E2Util.encodeMacLen(sysee[42]) + result = fru.E2Util.generateBinBySetMac(bia, pia) + I2CUTIL.writeToE2(msg['bus'], msg['loc'], result.bindata) + pass + + def slotmac(self, vals): + x = sorted(vals,lambda x,y: cmp(x["name"], y["name"])) + for item in x: + fruMsg = self.getfruMsg(item['bus'], item['loc']) + print "%s:"% item['name'] + result = self.getInputSetmac(fruMsg) + I2CUTIL.writeToE2(item['bus'], item['loc'], result.bindata) + pass + + def showmac(self, type): + vals = [ elem for elem in FRULISTS if type == elem["E2TYPE"]] + val_ts = sorted(vals,lambda x,y: cmp(x["name"], y["name"])) + for val in val_ts: + print "####################%s####################" % val["name"] + filename = I2CUTIL.getE2File(val['bus'], val['loc']) + ret = FruUtil.fru_decode_eeprom(filename) + head = ["key","value"] + if ret.boardInfoArea!= None: + print "=================board=================" + print tabulate(ret.boardInfoArea.todict().items(), head, tablefmt="simple") + + if ret.productInfoArea!= None: + print"=================product=================" + print tabulate(ret.productInfoArea.todict().items(), head, tablefmt="simple") + + def setmac(self, type1): + vals = [ elem for elem in FRULISTS if (type1 == elem["E2TYPE"] and elem["CANRESET"] == '1' )] + if len(vals) <= 0: + return None + if type1 == "8" or type1 == "A": + I2CUTIL.openFanE2Protect() + self.fansetmac(vals) + I2CUTIL.closeFanE2Protect() + return + elif type1 == "6": + return self.slotmac(vals) + elif type1 == "4": + return self.cpufrusetmac(vals) + else: + return self.globalsetmac(vals) + + def getfruMsg(self, bus, loc): + filename = I2CUTIL.getE2File(bus, loc) + ret = FruUtil.fru_decode_eeprom(filename) + return ret + + def getfruMsgByI2C(self, bus,loc): + retval = self.dumpValueByI2c(bus,loc) + return FruUtil.fru_decode_eepromByValue(retval) + + @staticmethod + def fru_getdefault_eeprom(product, type1): + return fru.E2Util.defaultBinByConfig(product,type1) + + @staticmethod + def fru_decode_eeprom(filename): + return fru.E2Util.decodeBinName(filename) + + @staticmethod + def fru_decode_eepromByValue(val): + return fru.E2Util.decodeBinByValue(val) +''' + +class fan_tlv(): + VERSION = 0x01 # E2PROM version number of the file definition,the initial version is0x01 + FLAG = 0x7E # new version E2PROM Identified as 0x7E + HW_VER = 0X01 # consists of a major version number and a revised version + TYPE = 0xf1 # hardware type definition information + TLV_LEN = 00 # effective data length(16bit) + _FAN_TLV_HDR_LEN = 6 + _FAN_TLV_CRC_LEN = 2 + + _FAN_TLV_TYPE_NAME = 0x02 + _FAN_TLV_TYPE_SN = 0x03 + _FAN_TLV_TYPE_HW_INFO = 0x05 + _FAN_TLV_TYPE_DEV_TYPE = 0x06 + + _fandecodetime = 0 + + @property + def dstatus(self): + return self._dstatus + + @property + def typename(self): + return self._typename + + @property + def typesn(self): + return self._typesn + + @property + def typehwinfo(self): + return self._typehwinfo + + @property + def typedevtype(self): + return self._typedevtype + + @property + def fanbus(self): + return self._fanbus + + @property + def fanloc(self): + return self._fanloc + + @property + def fandecodetime(self): + return self._fandecodetime + + def __init__(self): + self._typename = "" + self._typesn = "" + self._typehwinfo = "" + self._typedevtype = "" + self._dstatus = 0 + + def strtoarr(self, str): + s = [] + for index in str: + s.append(index) + return s + + def generate_fan_value(self): + bin_buffer = [chr(0xff)] * 256 + bin_buffer[0] = chr(self.VERSION) + bin_buffer[1] = chr(self.FLAG) + bin_buffer[2] = chr(self.HW_VER) + bin_buffer[3] = chr(self.TYPE) + + temp_t = "%08x" % self.typedevtype # do devtype first + typedevtype_t = hex_to_str(temp_t) + total_len = len(self.typename) + len(self.typesn) + \ + len(self.typehwinfo) + len(typedevtype_t) + 8 + + bin_buffer[4] = chr(total_len >> 8) + bin_buffer[5] = chr(total_len & 0x00FF) + + index_start = 6 + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME) + bin_buffer[index_start + 1] = chr(len(self.typename)) + bin_buffer[index_start + 2: index_start + 2 + + len(self.typename)] = self.strtoarr(self.typename) + index_start = index_start + 2 + len(self.typename) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN) + bin_buffer[index_start + 1] = chr(len(self.typesn)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typesn)] = self.strtoarr(self.typesn) + index_start = index_start + 2 + len(self.typesn) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO) + bin_buffer[index_start + 1] = chr(len(self.typehwinfo)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typehwinfo)] = self.strtoarr(self.typehwinfo) + index_start = index_start + 2 + len(self.typehwinfo) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE) + bin_buffer[index_start + 1] = chr(len(typedevtype_t)) + bin_buffer[index_start + 2:index_start + 2 + + len(typedevtype_t)] = self.strtoarr(typedevtype_t) + index_start = index_start + 2 + len(typedevtype_t) + + crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start])) # 2 Byte test + bin_buffer[index_start] = chr(crcs >> 8) + bin_buffer[index_start + 1] = chr(crcs & 0x00ff) + # printvalue(bin_buffer) + return bin_buffer + + def encode(self): + e = [] + # Add the head + + def decode(self, e2): + ret = [] + self.VERSION = ord(e2[0]) + self.FLAG = ord(e2[1]) + self.HW_VER = ord(e2[2]) + self.TYPE = ord(e2[3]) + self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5]) + + tlv_index = self._FAN_TLV_HDR_LEN + tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN + + # Judgment checksum + if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2: + self._dstatus = -2 + return ret + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN] + ) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1]) + if sumcrc != readcrc: + self._dstatus = -1 + return ret + else: + self._dstatus = 0 + while (tlv_index + 2) < len(e2) and tlv_index < tlv_end: + s = self.decoder( + e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])]) + tlv_index += ord(e2[tlv_index + 1]) + 2 + ret.append(s) + # Computing checksum + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + + return ret + + @staticmethod + def fancrc(t): + sum = 0 + for index in range(len(t)): + sum += ord(t[index]) + return sum + + def decoder(self, t): + try: + name = "" + value = "" + if ord(t[0]) == self._FAN_TLV_TYPE_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + self._typename = value + elif ord(t[0]) == self._FAN_TLV_TYPE_SN: + name = "serial Number" + value = str(t[2:2 + ord(t[1])]) + self._typesn = value + elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO: + name = "hardware info" + value = str(t[2:2 + ord(t[1])]) + self._typehwinfo = value + elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE: + name = "dev type" + value = str(t[2:2 + ord(t[1])]) + value = str_to_hex(value) + self._typedevtype = value + value = "0x08%x" % value + except Exception as e: + print (e) + return {"name": name, "code": ord(t[0]), "value": value} + + def __str__(self): + formatstr = "VERSION : 0x%02x \n" \ + " FLAG : 0x%02x \n" \ + " HW_VER : 0x%02x \n" \ + " TYPE : 0x%02x \n" \ + "typename : %s \n" \ + "typesn : %s \n" \ + "typehwinfo : %s \n" + return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE, self.typename, self.typesn, self.typehwinfo) + + +class AVSUTIL(): + @staticmethod + def mac_avs_chip(bus, devno, loc, open, close, loop, protectaddr, level, loopaddr): + ret = -1 + # Close the protection + rji2cset(bus, devno, protectaddr, open) + rji2cset(bus, devno, loopaddr, loop) + rji2csetWord(bus, devno, loc, level) + ret, value = rji2cgetWord(bus, devno, loc) + if strtoint(value) == level: + ret = 0 + # Open the protection + rji2cset(bus, devno, protectaddr, close) + if ret == 0: + return True + return False + + @staticmethod + def macPressure_adj(macavs, avs_param, mac_def_param): + # Determine if it is in range + max_adj = max(avs_param.keys()) + min_adj = min(avs_param.keys()) + type = mac_def_param["type"] + level = 0 + if type == 0: + if macavs not in range(min_adj, max_adj + 1): + return False + else: + level = macavs + else: + if macavs not in range(min_adj, max_adj + 1): + level = mac_def_param["default"] + else: + level = macavs + ret = AVSUTIL.mac_avs_chip(mac_def_param["bus"], mac_def_param["devno"], mac_def_param["addr"], mac_def_param["open"], + mac_def_param["close"], mac_def_param["loop"], mac_def_param["protectaddr"], avs_param[level], mac_def_param["loopaddr"]) + return ret + + @staticmethod + def mac_adj(): + macavs = 0 + cpldavs = 0 + name = MAC_DEFAULT_PARAM["sdkreg"] + ret, status = getSdkReg(name) + if ret == False: + return False + status = strtoint(status) + # Shift operation + if MAC_DEFAULT_PARAM["sdktype"] != 0: + status = ( + status >> MAC_DEFAULT_PARAM["macregloc"]) & MAC_DEFAULT_PARAM["mask"] + macavs = status + ret = AVSUTIL.macPressure_adj(macavs, MAC_AVS_PARAM, MAC_DEFAULT_PARAM) + return ret + + +class I2CUTIL(): + @staticmethod + def getvaluefromdevice(name): + ret = [] + for item in DEVICE: + if item["name"] == name: + ret.append(item) + return ret + + @staticmethod + def openFanE2Protect(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + + @staticmethod + def closeFanE2Protect(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + + @staticmethod + def writeToFanE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def writeToE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def getE2File(bus, loc): + return "/sys/bus/i2c/devices/%d-00%02x/eeprom" % (bus, loc) + + +class BMC(): + _instance_lock = threading.Lock() + + def __init__(self): + pass + + def __new__(cls, *args, **kwargs): + if not hasattr(Singleton, "_instance"): + with Singleton._instance_lock: + if not hasattr(Singleton, "_instance"): + Singleton._instance = object.__new__(cls) + return Singleton._instance + +# The internal interface + + +def getSdkReg(reg): + try: + cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg + ret, result = rj_os_system(cmd) + result_t = result.strip().replace("\r", "").replace("\n", "") + if ret != 0 or "Error:" in result_t: + return False, result + patt = r"%s.(.*):(.*)>drivshell" % reg + rt = re.findall(patt, result_t, re.S) + test = re.findall("=(.*)", rt[0][0])[0] + except Exception as e: + return False, 'getsdk register error' + return True, test + + +def getfilevalue(location): + try: + with open(location, 'r') as fd: + value = fd.read() + return True, value.strip() + except Exception as e: + return False, "error" + + +def get_sysfs_value(location): + pos_t = str(location) + name = get_pmc_register(pos_t) + return name + + +def write_sysfs_value(reg_name, value): + retval = 'ERR' + fileLoc = MAILBOX_DIR + reg_name + try: + if not os.path.isfile(fileLoc): + print (fileLoc, 'not found !') + return False + with open(fileLoc, 'w') as fd: + fd.write(value) + except Exception as error: + log_error("Unable to open " + fileLoc + "file !") + return False + return True + + +def RJPRINTERR(str): + print("\033[0;31m%s\033[0m" % str) + + +def strtoint(str): # The hexadecimal string is converted to int, such as"4040"/"0x4040"/"0X4040" = 16448 + value = 0 + rest_v = str.replace("0X", "").replace("0x", "") + for index in range(len(rest_v)): + value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4) + return value + +def inttostr(vl,len): # Convert int to string,such as 0x3030 = 00 + if type(vl) != int: + raise Exception(" type error") + index = 0 + ret_t = "" + while index < len: + ret = 0xff & (vl >> index * 8) + ret_t += chr(ret) + index += 1; + return ret_t + +def str_to_hex(rest_v): + value = 0 + for index in range(len(rest_v)): + value |= ord(rest_v[index]) << ((len(rest_v) - index - 1) * 8) + return value + + +def hex_to_str(s): + len_t = len(s) + if len_t % 2 != 0: + return 0 + ret = "" + for t in range(0, len_t / 2): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + return ret + + +def str_to_bin(s): + return ' '.join([bin(ord(c)).replace('0b', '') for c in s]) + + +def bin_to_str(s): + return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]]) + + +def getMacTemp(): + result = {} + # waitForDocker() + # Run the command twice in a row and take the second time + ret, log = rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + ret, log = rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + if ret: + return False, result + else: + # Parse the read information + logs = log.splitlines() + for line in logs: + if "average" in line: + b = re.findall(r'\d+.\d+', line) + result["average"] = b[0] + elif "maximum" in line: + b = re.findall(r'\d+.\d+', line) + result["maximum"] = b[0] + return True, result + +def getMacTemp_sysfs(mactempconf): + try: + temp = -1000000 + temp_list = [] + mac_temp_loc = mactempconf.get("loc", []) + mac_temp_flag = mactempconf.get("flag",None) + if mac_temp_flag is not None: # Determine the MAC temperature label + gettype = mac_temp_flag.get('gettype') + okbit = mac_temp_flag.get('okbit') + okval = mac_temp_flag.get('okval') + if gettype == "io": + io_addr = mac_temp_flag.get('io_addr') + val = io_rd(io_addr) + if val is None: + raise Exception("get mac_flag by io failed.") + else: + bus = mac_temp_flag.get('bus') + loc = mac_temp_flag.get('loc') + offset = mac_temp_flag.get('offset') + ind, val = rji2cget(bus, loc, offset) + if ind is not True: + raise Exception("get mac_flag by i2c failed.") + val_t = (int(val,16) & (1<< okbit)) >> okbit + if val_t != okval: + raise Exception("mac_flag invalid, val_t:%d." % val_t) + for loc in mac_temp_loc: + temp_s = get_sysfs_value(loc) + if isinstance(temp_s, str) and temp_s.startswith("ERR"): + raise Exception("get mac temp error. loc:%s" % loc) + temp_t = int(temp_s) + if temp_t == -1000000: + raise Exception("mac temp invalid.loc:%s" % loc) + temp_list.append(temp_t) + temp_list.sort(reverse=True) + temp = temp_list[0] + except Exception as e: + return False, temp + return True, temp + +def restartDockerService(force=False): + container_name = ["database","snmp","syncd","swss","dhcp_relay","radv","teamd","pmon"] + ret, status = rj_os_system("docker ps") + if ret == 0 : + for tmpname in container_name: + if (tmpname not in status): + if (force == True): + rj_os_system("docker restart %s"%tmpname) + else: + rj_os_system("systemctl restart %s"%tmpname) + + +def waitForDhcp(timeout): + time_cnt = 0 + while True: + try: + ret, status = rj_os_system("systemctl status dhcp_relay.service") + if (ret == 0 and "running" in status) or "SUCCESS" in status: + break + else: + sys.stdout.write(".") + sys.stdout.flush() + time_cnt = time_cnt + 1 + if time_cnt > timeout: + raise Exception("waitForDhcp timeout") + time.sleep(1) + except Exception as e: + return False + return True + +def waitForSdk(sdk_fpath ,timeout): + time_cnt = 0 + while True: + try: + if os.path.exists(sdk_fpath): + break + else: + sys.stdout.write(".") + sys.stdout.flush() + time_cnt = time_cnt + 1 + if time_cnt > timeout: + raise Exception("waitForSdk timeout") + time.sleep(1) + except Exception as e: + return False + return True + +def waitForDocker(need_restart=False,timeout=180): + sdkcheck_params = STARTMODULE.get("sdkcheck",{}) + if sdkcheck_params.get("checktype") == "file": # Judge by file + sdk_fpath = sdkcheck_params.get("sdk_fpath") + return waitForSdk(sdk_fpath,timeout) + return waitForDhcp(timeout) + + +def getTLV_BODY(type, productname): + x = [] + temp_t = "" + if type == TLV_CODE_MAC_BASE: + arr = productname.split(':') + for tt in arr: + temp_t += chr(int(tt, 16)) + elif type == TLV_CODE_DEVICE_VERSION: + temp_t = chr(productname) + elif type == TLV_CODE_MAC_SIZE: + temp_t = chr(productname >> 8) + chr(productname & 0x00ff) + else: + temp_t = productname + x.append(chr(type)) + x.append(chr(len(temp_t))) + for i in temp_t: + x.append(i) + return x + + +def _crc32(v): + return '0x%08x' % (binascii.crc32(v) & 0xffffffff) # Take the octet data %x of CRC32 to return hexadecimal + +def printvalue(b): + index = 0 + for i in range(0, len(b)): + if index % 16 == 0: + print (" ") + print ("%02x " % ord(b[i]),) + index += 1 + print ("\n") + + +def generate_value(_t): + ret = [] + for i in TLV_INFO_ID_STRING: + ret.append(i) + ret.append(chr(TLV_INFO_VERSION)) + ret.append(chr(TLV_INFO_LENGTH)) + ret.append(chr(TLV_INFO_LENGTH_VALUE)) + + total_len = 0 + for key in _t: + x = getTLV_BODY(key, _t[key]) + ret += x + total_len += len(x) + ret[10] = chr(total_len + 6) + + ret.append(chr(0xFE)) + ret.append(chr(0x04)) + s = _crc32(''.join(ret)) + for t in range(0, 4): + ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16))) + totallen = len(ret) + if (totallen < 256): + for left_t in range(0, 256 - totallen): + ret.append(chr(0x00)) + return (ret, True) + + +def getsyseeprombyId(id): # Obtain the system system by ID + ret = get_sys_eeprom() + for item in ret: + if item["code"] == id: + return item + return None + + +def fac_init_cardidcheck(): + rest = getsyseeprombyId(TLV_CODE_RJ_CARID) # Check whether cardId are the same + if rest == None: + print ("需要烧写bin文件") + return False + else: + rest_v = rest['value'] + value = strtoint(rest_v) + if value == RAGILE_CARDID: + log_debug("板卡ID检测通过") + else: + log_debug("板卡ID有误") + return False + return True + + +def isValidMac(mac): + if re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$", mac): + return True + return False + +# network card setmac + + +def util_setmac(eth, mac): + rulefile = "/etc/udev/rules.d/70-persistent-net.rules" + if isValidMac(mac) == False: + return False, "MAC非法" + ifconfigcmd = "ifconfig eth0 down" + log_debug(ifconfigcmd) + ret, status = rj_os_system(ifconfigcmd) + if ret: + return False, "软件停用eth0出错" + ifconfigcmd = "ifconfig eth0 hw ether %s" % mac + log_debug(ifconfigcmd) + ret, status = rj_os_system(ifconfigcmd) + if ret: + return False, "软件设置网卡MAC出错" + ifconfigcmd = "ifconfig eth0 up" + log_debug(ifconfigcmd) + ret, status = rj_os_system(ifconfigcmd) + if ret: + return False, "软件启用eth0出错" + if os.path.exists(rulefile): + os.remove(rulefile) + print ("MGMT MAC【%s】" % mac) + return True + + +def getInputCheck(tips): + err = 0 + str = raw_input(tips) + if astrcmp(str, "y") or astrcmp(str, "ye") or astrcmp(str, "yes") or astrcmp(str, ""): + return True + else: + return False + +def getrawch(): + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + +def upper_input(tips): + sys.stdout.write(tips) + sys.stdout.flush() + passwd = [] + while True: + ch = getrawch().upper() + if ch == "\r" or ch == "\n": + print + return "".join(passwd) + elif ch == '\b' or ord(ch) == 127: + if passwd: + del passwd[-1] + sys.stdout.write('\b \b') + else: + sys.stdout.write(ch) + passwd.append(ch) + +def changeTypeValueLiquid(_value, type1, tips, example): + if type1 == TLV_CODE_PRODUCT_NAME: + while True: + print ("请确认 (1)前后进风/(2)液冷集中供电/(3)液冷非集中供电:" ,) + option = raw_input() + if option == "1": + _value[type1] = example + "-F-RJ" + print ("确认该产品为前后进风设备,产品名称:%s"%_value[type1]) + break + elif option == "2": + _value[type1] = example + "-LC-RJ" + print ("确认该产品为液冷集中供电设备,产品名称:%s"%_value[type1]) + break + elif option == "3": + _value[type1] = example + "-LD-RJ" + print ("确认该产品为液冷非集中供电设备,产品名称:%s"%_value[type1]) + break + else: + print ("输入错误,请认真核对") + return True + print ("请输入【%s】如(%s):" % (tips, example),) + name = upper_input("") + if type1 == TLV_CODE_MAC_BASE: + if len(name) != 12: + raise Exception("MAC地址长度不对,请认真核对") + return False + release_mac = "" + for i in range(len(name) / 2): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + _value[type1] = release_mac + else: + raise Exception("MAC地址非法,请认真核对") + return False + elif type1 == TLV_CODE_DEVICE_VERSION: + if name.isdigit(): + _value[type1] = int(name) + else: + raise Exception("版本号非数字,请认真核对") + elif type1 == TLV_CODE_MAC_SIZE: + if name.isdigit(): + _value[type1] = int(name, 16) + else: + raise Exception("版本号非数字,请认真核对") + elif type1 == TLV_CODE_SERIAL_NUMBER: + if name.isalnum() == False: + raise Exception("序列号非法字符串,请认真核对") + elif len(name) != 13: + raise Exception("序列号长度不对,请认真核对") + else: + _value[type1] = name + elif type1 == TLV_CODE_VENDOR_EXT: + _value[type1] = name + else: + _value[type1] = name + return True + +def changeTypeValue(_value, type1, tips, example): + if type1 == TLV_CODE_PRODUCT_NAME: + while True: + print ("请确认 (1)前后进风/(2)后前进风:",) + option = raw_input() + if option == "1": + _value[type1] = example + "-F-RJ" + print ("确认该产品为前后进风设备,产品名称:%s"%_value[type1]) + break + elif option == "2": + _value[type1] = example + "-R-RJ" + print ("确认该产品为后前进风设备,产品名称:%s"%_value[type1]) + break + else: + print ("输入错误,请认真核对") + return True + print ("请输入【%s】如(%s):" % (tips, example),) + name = upper_input("") + if type1 == TLV_CODE_MAC_BASE: + if len(name) != 12: + raise SETMACException("MAC地址长度不对,请认真核对") + return False + release_mac = "" + for i in range(len(name) / 2): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + _value[type1] = release_mac + else: + raise SETMACException("MAC地址非法,请认真核对") + return False + elif type1 == TLV_CODE_DEVICE_VERSION: + if name.isdigit(): + _value[type1] = int(name) + else: + raise SETMACException("版本号非数字,请认真核对") + elif type1 == TLV_CODE_MAC_SIZE: + if name.isdigit(): + _value[type1] = int(name, 16) + else: + raise SETMACException("版本号非数字,请认真核对") + elif type1 == TLV_CODE_SERIAL_NUMBER: + if name.isalnum() == False: + raise SETMACException("序列号非法字符串,请认真核对") + elif len(name) != 13: + raise SETMACException("序列号长度不对,请认真核对") + else: + _value[type1] = name + elif type1 == TLV_CODE_VENDOR_EXT: + _value[type1] = name + else: + _value[type1] = name + return True +# Compare strings regardless of size + + +def astrcmp(str1, str2): + return str1.lower() == str2.lower() + + +def generate_ext(cardid): + s = "%08x" % cardid + ret = "" + for t in range(0, 4): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + ret = chr(0x01) + chr(len(ret)) + ret + return ret + + +def rji2cget(bus, devno, address, word=None): + if word == None: + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + else: + command_line = "i2cget -f -y %d 0x%02x 0x%02x %s" % (bus, devno, address, word) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + + +def rji2cset(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + +def rjpcird(pcibus , slot , fn, bar, offset): + '''read pci register''' + if offset % 4 != 0: + return + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + with open(filename, "r+") as file: + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + data.close() + return "0x%08x" % val + + +def rjpciwr(pcibus , slot ,fn, bar, offset, data): + '''write pci register''' + ret = inttostr(data, 4) + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + with open(filename, "r+") as file: + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + data[offset: offset + 4] = ret + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + data.close() + + +def rjsysset(location, value): + command_line = "echo 0x%02x > %s" % (value, location) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + +def rji2cgetWord(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x w" % (bus, devno, address) + retrytime = 3 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + +def rji2csetWord(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%x w" % ( + bus, devno, address, byte) + rj_os_system(command_line) + + +def fan_setmac(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + + +def checkfansninput(fan_sn, fansntemp): + if fan_sn in fansntemp: + RJPRINTERR("存在相同序列号,请重新输入!") + return False + if(len(fan_sn) != 13): + RJPRINTERR("序列号长度错误,请重新输入!") + return False + return True + +# Check the input hardware version number + + +def checkfanhwinput(hw): + if len(hw) != 4: + RJPRINTERR("硬件版本号长度不正确,请重新输入!") + return False + if hw.find(".") != 1: + RJPRINTERR("硬件版本号不正确,请重新输入!") + return False + return True + + +def util_show_fanse2(fans): + formatstr = "%-8s %-20s %-20s %-20s %-20s" + print (formatstr % ("id", "名称", "硬件版本号", "序列号", "时间")) + print (formatstr % ("------", "---------------", "---------------", "---------------", "----")) + for fan in fans: + # print fan.dstatus + if fan.dstatus < 0: + print ("%-8s" % ("风扇%d" % (fans.index(fan) + 1)),) + RJPRINTERR(" 解析e2出错") + else: + print (formatstr % ("风扇%d" % (fans.index(fan) + 1), fan.typename.replace(chr(0x00), ""), + fan.typehwinfo.replace(chr(0x00), ""), fan.typesn.replace(chr(0x00), ""), fan.fandecodetime)) + + +def get_fane2_sysfs(bus, loc): + rg_fan_e2 = "%d-%04x/fan" % (bus, loc) + eeprom = get_sysfs_value(rg_fan_e2) + return eeprom + + +def util_show_fane2(): + ret = sorted(I2CUTIL.getvaluefromdevice("rg_fan")) + if len(ret) <=0: + return None + fans = [] + for index in range(len(ret)): + t1 = (int(round(time.time() * 1000))) + eeprom = get_fane2_sysfs(ret[index]["bus"], ret[index]["loc"]) + t2 = (int(round(time.time() * 1000))) + fane2 = fan_tlv() + fane2.fandecodetime = t2 - t1 + fane2.decode(eeprom) + fans.append(fane2) + util_show_fanse2(fans) + + +def getPid(name): + ret = [] + for dirname in os.listdir('/proc'): + if dirname == 'curproc': + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='rb') as fd: + content = fd.read() + except Exception: + continue + if name in content: + ret.append(dirname) + return ret + +def fac_fans_setmac_tlv(ret): + if len(ret) <=0: + return None + fans = [] + fansntemp = [] + for index in range(len(ret)): + item = ret[index] + log_debug(item) + eeprom = get_fane2_sysfs(item["bus"], item["loc"]) + fane2 = fan_tlv() + fane2.decode(eeprom) + fane2.fanbus = item["bus"] + fane2.fanloc = item["loc"] + log_debug("decode eeprom success") + + print ("风扇【%d】-【%s】setmac" % ((index + 1), FANS_DEF[fane2.typedevtype])) + while True: + print ("请输入[%s]:" % "序列号",) + fan_sn = raw_input() + if checkfansninput(fan_sn, fansntemp) == False: + continue + fansntemp.append(fan_sn) + fan_sn = fan_sn + chr(0x00) + fane2.typesn = fan_sn + chr(0x00) + break + while True: + print ("请输入[%s]:" % "硬件版本号",) + hwinfo = raw_input() + if checkfanhwinput(hwinfo) == False: + continue + fan_hwinfo = hwinfo + chr(0x00) + fane2.typehwinfo = fan_hwinfo + chr(0x00) + break + log_debug(fane2.typedevtype) + fane2.typename = FANS_DEF[fane2.typedevtype] + chr(0x00) + fans.append(fane2) + print ("\n") + print ("\n*******************************\n") + + util_show_fanse2(fans) + if getInputCheck("确认是否输入正确(Yes/No):") == True: + for fan in fans: + log_debug("ouput fan") + fac_fan_setmac(fan) + else: + print ("setmac退出") + return False + + +def fac_fan_setmac_fru(ret): + fans = FRULISTS.get('fans') + + fanfrus = {} + newfrus = {} + + # getmsg + try: + for fan in fans: + print ("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + fanfrus[fan.get('name')] = fru + except Exception as e: + print (str(e)) + return False + + # setmsg + for fan in fans: + print ("===============%s ================setmac" % fan.get('name')) + fruold = fanfrus.get(fan.get('name')) + newfru = getInputSetmac(fruold) + newfru.recalcute() + newfrus[fan.get('name')] = newfru + # writemsg + for fan in fans: + print ("===============%s ================writeToE2" % fan.get('name')) + ret_t = newfrus.get(fan.get('name')) + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(fan.get('bus'), fan.get('loc'), ret_t.bindata) + I2CUTIL.closeFanE2Protect() + # check + try: + for fan in fans: + print ("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + except Exception as e: + print (str(e)) + return False + return True + +def fac_fans_setmac(): + ret = I2CUTIL.getvaluefromdevice("rg_fan") + if ret is not None and len(ret) > 0: + return fac_fans_setmac_tlv(ret) + fans = FRULISTS.get('fans', None) + if fans is not None and len(fans)>0: + return fac_fan_setmac_fru(ret) + return False + +def fac_fan_setmac(item): + + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(item.fanbus, item.fanloc, item.generate_fan_value()) + I2CUTIL.closeFanE2Protect() + + pass + + +def writeToEEprom(rst_arr): + dealtype = E2_PROTECT.get('gettype',None) + bus = E2_PROTECT.get('bus', None) + if (dealtype is None) and (bus is not None): + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["open"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["open"]) + index = 0 + for item in rst_arr: + rji2cset(E2_LOC["bus"], E2_LOC["devno"], index, ord(item)) + index += 1 + + if (dealtype is None) and (bus is not None): + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["close"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["close"]) + # Finally, the system driver is dealt with + os.system("rmmod at24 ") + os.system("modprobe at24 ") + os.system("rm -f /var/cache/sonic/decode-syseeprom/syseeprom_cache") + + +def get_local_eth0_mac(): + cmd = "ifconfig eth0 |grep HWaddr" + print (rj_os_system(cmd)) + +def getonieversion(): + if not os.path.isfile('/host/machine.conf'): + return "" + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars.get("onie_version") + +def createbmcMac(cpumac , num = 2): + bcmvalue = strtoint(cpumac[cpumac.rindex(":")+ 1:len(cpumac)]) + num + # bmcmac = + t = cpumac.split(":") + t[5] = "%02x" % bcmvalue + bmcmac = ":".join(t) + return bmcmac.upper() + + +def fac_board_setmac(): + _value = {} + # default value + _value[TLV_CODE_VENDOR_EXT] = generate_ext(RAGILE_CARDID) # Generates an ID unique to RAGILE + _value[TLV_CODE_PRODUCT_NAME] = RAGILE_PRODUCTNAME + _value[TLV_CODE_PART_NUMBER] = RAGILE_PART_NUMBER + _value[TLV_CODE_LABEL_REVISION] = RAGILE_LABEL_REVISION + _value[TLV_CODE_PLATFORM_NAME] = platform + _value[TLV_CODE_ONIE_VERSION] = getonieversion() + _value[TLV_CODE_MAC_SIZE] = RAGILE_MAC_SIZE + _value[TLV_CODE_MANUF_NAME] = RAGILE_MANUF_NAME + _value[TLV_CODE_MANUF_COUNTRY] = RAGILE_MANUF_COUNTRY + _value[TLV_CODE_VENDOR_NAME] = RAGILE_VENDOR_NAME + _value[TLV_CODE_DIAG_VERSION] = RAGILE_DIAG_VERSION + _value[TLV_CODE_SERVICE_TAG] = RAGILE_SERVICE_TAG + try: + if (RAGILE_CARDID in [0x00004065]): + changeTypeValueLiquid(_value, TLV_CODE_PRODUCT_NAME, "产品名称", RAGILE_PRODUCTNAME) + elif (RAGILE_CARDID in [0x00004066,0x00004087,0x00004088]): + changeTypeValue(_value, TLV_CODE_PRODUCT_NAME, "产品名称", RAGILE_PRODUCTNAME) + else: + _value[TLV_CODE_PRODUCT_NAME] = RAGILE_PRODUCTNAME + "-RJ" + + changeTypeValue(_value, TLV_CODE_SERIAL_NUMBER, + "SN", "0000000000000") # Add serial number + changeTypeValue(_value, TLV_CODE_DEVICE_VERSION, + "硬件版本号", "101") # Hardware Version number + changeTypeValue(_value, TLV_CODE_MAC_BASE, + "MAC地址", "58696cfb2108") # MAC address + _value[TLV_CODE_MANUF_DATE] = time.strftime( + '%m/%d/%Y %H:%M:%S', time.localtime()) # automatically add setmac time + rst, ret = generate_value(_value) + if util_setmac("eth0", _value[TLV_CODE_MAC_BASE]) == True: # set network card IP + writeToEEprom(rst) # write value to e2 + # set BMC MAC + if FACTESTMODULE.__contains__("bmcsetmac") and FACTESTMODULE['bmcsetmac'] == 1: + bmcmac = createbmcMac(_value[TLV_CODE_MAC_BASE]) + if ipmi_set_mac(bmcmac) == True: + print("BMC MAC【%s】"%bmcmac) + else: + print("SET BMC MAC FAILED") + return False + else: + return False + except SETMACException as e: + # print e + RJPRINTERR("\n\n%s\n\n" % e) + return False + except ValueError as e: + return False + return True + + +def ipmi_set_mac(mac): + macs = mac.split(":") + cmdinit = "ipmitool raw 0x0c 0x01 0x01 0xc2 0x00" + cmdset = "ipmitool raw 0x0c 0x01 0x01 0x05" + for ind in range(len(macs)): + cmdset += " 0x%02x" % int(macs[ind], 16) + rj_os_system(cmdinit) + ret, status = rj_os_system(cmdset) + if ret: + RJPRINTERR("\n\n%s\n\n" % status) + return False + return True + + +def getInputValue(title, tips): + print ("请输入【%s】如(%s):" % (title, tips),) + name = raw_input() + + return name + + +def bmc_setmac(): + tips = "BMC MAC" + print ("请输入你要改的值[%s]:" % tips,) + name = raw_input() + if len(name) != 12: + RJPRINTERR("\nMAC地址非法,请重新输入\n") + return False + release_mac = "" + for i in range(len(name) / 2): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + if ipmi_set_mac(release_mac) == True: + return True + else: + RJPRINTERR("\nMAC地址非法,请重新输入\n") + return False + + +def closeProtocol(): + # close LLDP + log_info("关闭LLDP") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop lldp.service") + log_info("关闭网关边界服务") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop bgp.service") + log_info("关闭生成树") + sys.stdout.write(".") + sys.stdout.flush() + # ret, status = rj_os_system('bcmcmd "port ce,xe stp=disable"') + +# detection SDK memory must be 256M + + +def checkSdkMem(): + ind = 0 + file_data = "" + with open(file_name, "r") as f: + for line in f: + if "dmasize=16M" in line: + line = line.replace("dmasize=16M", "dmasize=256M") + ind = -1 + file_data += line + if ind == 0: + return + with open(file_name, "w") as f: + f.write(file_data) + print ("修订SDK内存为256,需要重启生效") + rj_os_system("sync") + rj_os_system("reboot") + +########################################################################## +# The window receives a character setting +########################################################################## + + +def getch(msg): + ret = "" + fd = sys.stdin.fileno() + old_ttyinfo = termios.tcgetattr(fd) + new_ttyinfo = old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + sys.stdout.write(msg) + sys.stdout.flush() + try: + termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo) + ret = os.read(fd, 1) + finally: + # print "try to setting" + termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo) + return ret + +def get_raw_input(): + ret="" + fd=sys.stdin.fileno() + old_ttyinfo=termios.tcgetattr(fd) + new_ttyinfo=old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + try: + termios.tcsetattr(fd,termios.TCSANOW,new_ttyinfo) + ret=raw_input("") + except Exception as e: + print (e) + finally: + termios.tcsetattr(fd,termios.TCSANOW,old_ttyinfo) + return ret + + +def getsysvalue(location): + retval = None + mb_reg_file = location + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + try: + if (not os.path.isfile(mb_reg_file)): + print (mb_reg_file, 'not found !') + return retval + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + log_error("Unable to open " + mb_reg_file + "file !") + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + # log_debug(retval) + return retval + +# Get file value + + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR + reg_name + filepath = glob.glob(mb_reg_file) + if(len(filepath) == 0): + return "%s %s notfound"% (retval , mb_reg_file) + mb_reg_file = filepath[0] # If multiple matching paths are found, the first matching path is selected by default. + if (not os.path.isfile(mb_reg_file)): + return "%s %s notfound"% (retval , mb_reg_file) + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + pass + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + +# According to RAGILE rule analysis EEPROM + + +def decoder(s, t): + if ord(t[0]) == TLV_CODE_PRODUCT_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + elif ord(t[0]) == TLV_CODE_PART_NUMBER: + name = "Part Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERIAL_NUMBER: + name = "Serial Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_BASE: + name = "Base MAC Address" + value = ":".join([binascii.b2a_hex(T) for T in t[2:8]]).upper() + elif ord(t[0]) == TLV_CODE_MANUF_DATE: + name = "Manufacture Date" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DEVICE_VERSION: + name = "Device Version" + value = str(ord(t[2])) + elif ord(t[0]) == TLV_CODE_LABEL_REVISION: + name = "Label Revision" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_PLATFORM_NAME: + name = "Platform Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_ONIE_VERSION: + name = "ONIE Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_SIZE: + name = "MAC Addresses" + value = str((ord(t[2]) << 8) | ord(t[3])) + elif ord(t[0]) == TLV_CODE_MANUF_NAME: + name = "Manufacturer" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MANUF_COUNTRY: + name = "Manufacture Country" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_NAME: + name = "Vendor Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DIAG_VERSION: + name = "Diag Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERVICE_TAG: + name = "Service Tag" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_EXT: + name = "Vendor Extension" + value = "" + if _TLV_DISPLAY_VENDOR_EXT: + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_CRC_32 and len(t) == 6: + name = "CRC-32" + value = "0x%08X" % (((ord(t[2]) << 24) | ( + ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) + elif ord(t[0]) == TLV_CODE_RJ_CARID: + name = "rj_cardid" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + else: + name = "Unknown" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "0x%02X " % (ord(c),) + return {"name": name, "code": ord(t[0]), "value": value} + + +def decode_eeprom(e): + total_len = (ord(e[9]) << 8) | ord(e[10]) + tlv_index = _TLV_INFO_HDR_LEN + tlv_end = _TLV_INFO_HDR_LEN + total_len + ret = [] + while (tlv_index + 2) < len(e) and tlv_index < tlv_end: + rt = decoder(None, e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])]) + ret.append(rt) + if ord(e[tlv_index]) == TLV_CODE_CRC_32: + break + tlv_index += ord(e[tlv_index + 1]) + 2 + for item in ret: + if item['code'] == TLV_CODE_VENDOR_EXT: + rt = decoder(None, item["value"] + [0: 0 + 2 + ord(item["value"][0 + 1])]) + ret.append(rt) + return ret + + +def get_sys_eeprom(): + eeprom = get_sysfs_value(rg_eeprom) + return decode_eeprom(eeprom) + +# get catd ID +def getCardId(): + ret = get_sys_eeprom() + for item in ret: + if item['code'] == TLV_CODE_RJ_CARID: + return item.get('value',None) + return None + +# ==================================== +# do shell command +# ==================================== +def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + +########################################### +# Run the DMI command to obtain the number of memory slots and slots +########################################### +def getsysmeminfo(): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + "|grep -P -A5 \"Memory\s+Device\"|grep Size|grep -v Range" + # Get the total first + result = [] + ret1, log1 = rj_os_system(cmd) + if ret == 0 and len(log1): + log1 = log1.lstrip() + arr = log1.split("\n") + total = len(arr) # Total number of slots + for i in range(len(arr)): + val = re.sub("\D", "", arr[i]) + if val == "": + val = arr[i].lstrip() + val = re.sub('Size:', '', val).lstrip() + # print val + result.append({"slot": i + 1, "size": val}) + return True, result + return False, "error" + +########################################### +# Run the DMI command to obtain the number of memory slots and slots +# return value contains multiple arrays +########################################### +def getsysmeminfo_detail(): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t 17 | grep -A21 \"Memory Device\"" # 17 + # Get the total first + ret1, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + result_t = log1.split("--") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets + + +########################################### +# Run the DMI command to obtain the BIOS information +########################################### +def getDmiSysByType(type_t): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t %s" % type_t + # Get the total first + ret1, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + its = log1.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + return True, ret + + +def gethwsys(): + return getDmiSysByType(1) + +########################################### +# Run the DMI command to obtain the BIOS information + + +def getsysbios(): + return getDmiSysByType(0) + + +def searchDirByName(name, dir): + result = [] + try: + files = os.listdir(dir) + for file in files: + if name in file: + result.append(os.path.join(dir, file)) + except Exception as e: + pass + return result + + +def getUsbLocation(): + dir = "/sys/block/" + spect = "sd" + usbpath = "" + result = searchDirByName(spect, dir) + if len(result) <= 0: + return False, usbpath + for item in result: + with open(os.path.join(item, "removable"), 'r') as fd: + value = fd.read() + if value.strip() == "1": # USB flash drive is found + usbpath = item + break + if usbpath == "": # No flash drive was found + log_debug("no usb found") + return False, usbpath + return True, usbpath + +# Judge USB file lookup +def getusbinfo(): + ret, path = getUsbLocation() + if ret == False: + return False, "not usb exists" + str = os.path.join(path, "size") + ret, value = getfilevalue(str) + if ret == True: + return True, {"id": os.path.basename(path), "size": float(value) * 512 / 1024 / 1024 / 1024} + else: + return False, "Err" + +def get_cpu_info(): + cmd = "cat /proc/cpuinfo |grep processor -A18" # 17 + + ret, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + result_t = log1.split("\n\n") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets +# Reading file contents +def get_version_config_info(attr_key, file_name=None): + if file_name == None: + version_conf_filename = "/root/version.json" + else: + version_conf_filename = file_name + if not os.path.isfile(version_conf_filename): + return None + with open(version_conf_filename) as rjconf_file: + for line in rjconf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0] == attr_key: + return tokens[1].strip() + return None + + +def io_rd(reg_addr, len =1): + '''io read''' + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str = os.read(fd, len) + return "".join(["%02x"% ord(item) for item in str]) + except ValueError: + return None + except Exception as e: + print (e) + return None + finally: + os.close(fd) + return None + + +def io_wr(reg_addr, reg_data): + '''io write''' + try: + regdata = 0 + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + if type(reg_data) == int: + regdata = reg_data + else: + regdata = int(reg_data, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + ret = os.write(fd, chr(regdata)) + return True + except ValueError as e: + print (e) + return False + except Exception as e: + print (e) + return False + finally: + os.close(fd) + return False + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/script/slot_monitor.py b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/slot_monitor.py new file mode 100644 index 000000000000..09f4c70915a7 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/script/slot_monitor.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import sys +import click +import os +import subprocess +import time +from ragileutil import * +import syslog +import traceback +import json + +SLOTMONITORDEBUG = 0 # 1 is open + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def slotwarninglog(s): + # s = s.decode('utf-8').encode('gb2312') + syslog.openlog("SLOTMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_WARNING,s) + +def slotcriticallog(s): + # s = s.decode('utf-8').encode('gb2312') + syslog.openlog("SLOTMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_CRIT,s) + +def sloterror(s): + # s = s.decode('utf-8').encode('gb2312') + syslog.openlog("SLOTMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR,s) + +def slotdebuglog(s): + # s = s.decode('utf-8').encode('gb2312') + if SLOTMONITORDEBUG == 1: + syslog.openlog("SLOTMONITOR",syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG,s) + +class SlotMonitor(): + def __init__(self): + self.preSlotStatus = [] + + def checkslot(self,ret): + '''Obtain the status of the subcard''' + slots_conf = SLOT_MONITOR_PARAM.get('slots', None) + slotpresent = MONITOR_DEV_STATUS_DECODE.get('slotpresent',None) + + if slots_conf is None or slotpresent is None: + return False + for item_slot in slots_conf: + totalerr = 0 + try: + ret_t = {} + ret_t["id"] = item_slot.get('name') + ret_t["status"] = "" + presentattr = item_slot.get('present') + gettype = presentattr.get('gettype') + presentbit = presentattr.get('presentbit') + if gettype == "io": + io_addr = presentattr.get('io_addr') + val = io_rd(io_addr) + if val is not None: + retval = val + else: + totalerr -= 1 + sloterror(" %s %s" % (item_slot.get('name'), "lpc读取失败")) + else: + bus = presentattr.get('bus') + loc = presentattr.get('loc') + offset = presentattr.get('offset') + ind, val = rji2cget(bus, loc,offset) + if ind == True: + retval = val + else: + totalerr -= 1 + sloterror(" %s %s" % (item_slot.get('name'), "i2c读取失败")) + if totalerr < 0 : + ret_t["status"] = "NOT OK" + ret.append(ret_t) + continue + val_t = (int(retval,16) & (1<< presentbit)) >> presentbit + slotdebuglog("%s present:%s" % (item_slot.get('name'),slotpresent.get(val_t))) + if val_t != slotpresent.get('okval'): + ret_t["status"] = "ABSENT" + else: + ret_t["status"] = "PRESENT" + except Exception as e: + ret_t["status"] = "NOT OK" + totalerr -= 1 + sloterror("checkslot error") + sloterror(str(e)) + ret.append(ret_t) + return True + + def dealslotplugin(self, name): + slotdebuglog("enter dealslotplugin %s" % name) + # wait for slot stable + time.sleep(5) + slots_conf = SLOT_MONITOR_PARAM.get('slots', None) + if slots_conf is None: + return False + for item_slot in slots_conf: + try: + slotdebuglog("name %s, item_slot.get('name') %s" % (name, item_slot.get('name'))) + if (name == item_slot.get('name')): + actattr = item_slot.get('act') + for item_act in actattr: + gettype = item_act.get('gettype') + if gettype == "io": + io_addr = item_act.get('io_addr') + value = item_act.get('value') + mask = item_act.get('mask') + val = io_rd(io_addr) + if val is None: + sloterror(" %s %s" % (name, "lpc读取失败")) + continue + set_val = (int(val, 16) & mask) | value + ret = io_wr(io_addr, set_val) + if ret != True: + sloterror(" %s %s" % (name, "lpc设置失败")) + continue + slotdebuglog("io set io_addr:0x%x value:0x%x success" % (io_addr, set_val)) + elif gettype == "i2c": + bus = item_act.get('bus') + loc = item_act.get('loc') + offset = item_act.get('offset') + value = item_act.get('value') + ret, log = rji2cset(bus, loc, offset, value) + if ret != True: + sloterror(" %s %s %s" % (name, "i2c设置失败", log)) + continue + slotdebuglog("i2c set bus:%d loc:0x%x offset:0x%x value:0x%x success" % (bus, loc, offset, value)) + else: + sloterror("gettype error") + break + except Exception as e: + sloterror("dealslotplugin failed") + sloterror(str(e)) + return False + return True + + def updateSlotStatus(self): + ''' + Only two status: PRESENT and ABSENT + ''' + curSlotStatus = [] + self.checkslot(curSlotStatus) + slotdebuglog('curSlotStatus: {}\n preSlotStatus: {}'.format(curSlotStatus, self.preSlotStatus)) + if cmp(self.preSlotStatus, curSlotStatus) != 0: + if len(self.preSlotStatus) == 0: + # first time + for i,item in enumerate(curSlotStatus): + if cmp(item['status'], 'PRESENT') == 0: + slotdebuglog('SLOT_PLUG_IN: %s'%(item['id'])) + elif cmp(item['status'], 'ABSENT') == 0: + slotdebuglog('SLOT_ABSENT: %s'%(item['id'])) + else: + slotdebuglog('SLOT_FAILED: %s status %s not support yet'%(item['id'], item['status'])) + self.preSlotStatus.append(item) + else: + for i,item in enumerate(curSlotStatus): + if cmp(item['status'], self.preSlotStatus[i]['status']) == 0: + continue + else: + if cmp(item['status'], 'PRESENT') == 0 and cmp(self.preSlotStatus[i]['status'], 'ABSENT') == 0: + self.dealslotplugin(item['id']) + slotwarninglog('SLOT_PLUG_IN: %s'%(item['id'])) + elif cmp(item['status'], 'ABSENT') == 0 and cmp(self.preSlotStatus[i]['status'], 'PRESENT') == 0: + slotwarninglog('SLOT_PLUG_OUT: %s'%(item['id'])) + else: + slotwarninglog('SLOT_PLUG_OUT: %s status change from %s to %s not support'%(item['id'], self.preSlotStatus[i]['status'], item['status'])) + self.preSlotStatus.remove(self.preSlotStatus[i]) + self.preSlotStatus.insert(i, item) + + def slotmonitor(self): + self.updateSlotStatus() + return 0 + +def doSlotMonitor(slotMonitor): + slotMonitor.slotmonitor() + +def run(interval, slotMonitor): + # slotMonitor.devattrinit() + while True: + try: + doSlotMonitor(slotMonitor) + except Exception as e: + traceback.print_exc() + sloterror(str(e)) + time.sleep(interval) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''slot monitor operator''' + pass + +@main.command() +def start(): + '''start slot monitor''' + slotwarninglog("slot_monitor start") + slotMonitor = SlotMonitor() + interval = SLOT_MONITOR_PARAM.get('polling_time', 1)# The polling time in the configuration file is 1s by default + run(interval, slotMonitor) + +@main.command() +def stop(): + '''stop slot monitor ''' + slotwarninglog("stop") + +# device_i2c operation +if __name__ == '__main__': + main() + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/service/device_i2c.service b/platform/centec-arm64/sonic-platform-modules-ragile/common/service/device_i2c.service new file mode 100644 index 000000000000..c7f5776cb5a9 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/service/device_i2c.service @@ -0,0 +1,15 @@ +[Unit] +Description= Ragile Global Initialize I2c drivers. +After=local-fs.target +Before=pmon.service ntp.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/device_i2c.py start +ExecStop=/usr/local/bin/device_i2c.py stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common/service/fancontrol.service b/platform/centec-arm64/sonic-platform-modules-ragile/common/service/fancontrol.service new file mode 100644 index 000000000000..2f88ade171a3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common/service/fancontrol.service @@ -0,0 +1,12 @@ +[Unit] +Description= Fancontrol for Device. +After=local-fs.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/fancontrol.py start +Restart=on-failure + +[Install] +WantedBy=multi-user.target + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/Makefile new file mode 100644 index 000000000000..084751ff6296 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/Makefile @@ -0,0 +1,24 @@ +PWD = $(shell pwd) +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +SUB_BUILD_DIR = $(PWD)/build +SERVICE_DIR = $(PWD)/service +INSTALL_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) +INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin +INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3.9/dist-packages +INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system +INSTALL_ETC_DIR = $(SUB_BUILD_DIR)/etc +UNSUPPORT_KERVER = 4.9.189 + +all: + @if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi + @if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi + @if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi + @if [ -d $(PWD)/script/ ]; then cp -r $(PWD)/script/* ${INSTALL_SCRIPT_DIR} ;fi + @if [ ! -d ${INSTALL_ETC_DIR} ]; then mkdir -p ${INSTALL_ETC_DIR} ;fi + @if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi + @if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi + if [ -d $(SERVICE_DIR) ]; then cp -r $(SERVICE_DIR)/* $(INSTALL_SERVICE_DIR) ;fi +clean: + rm -rf $(SUB_BUILD_DIR) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/fru.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/fru.py new file mode 100644 index 000000000000..ae56a82418a1 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/fru.py @@ -0,0 +1,1294 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from bitarray import bitarray +from datetime import datetime, timedelta +import requests +import ConfigParser +import sys +import os +import collections + +CONFIG_FILE = "product.conf" +__DEBUG__ = "N" +conf = None + + +def e_print(err): + print("ERROR: " + err) + + +def d_print(debug_info): + if(__DEBUG__ == "Y"): + print(debug_info) + + +def r_print(debug_info): + if True: + print(debug_info) + + +def p_print(prompt): + print("PROMPT: " + prompt) + + +class E2Exception(Exception): + + def __init__(self, message='e2异常', code=-100): + self.code = code + self.message = message + + +class BaseArea(): + SUGGESTED_SIZE_COMMON_HEADER = 8 + SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 + SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 + SUGGESTED_SIZE_BOARD_INFO_AREA = 80 + SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 + + INITVALUE = b'\x00' + resultvalue = INITVALUE * 256 + COMMON_HEAD_VERSION = b'\x01' + __childList = None + + def __init__(self, name="", size=0, offset=0): + self.__childList = [] + self._offset = offset + self.name = name + self._size = size + self._isPresent = False + self._data = b'\x00' * size + self.__dataoffset = 0 + + @property + def childList(self): + return self.__childList + + @property + def offset(self): + return self._offset + + @property + def size(self): + return self._size + + @property + def data(self): + return self._data + + @property + def isPresent(self): + return self._isPresent + + @isPresent.setter + def isPresent(self, value): + self._isPresent = value + + +class InternalUseArea(BaseArea): + pass + + +class ChassisInfoArea(BaseArea): + pass + + +class BoardInfoArea(BaseArea): + + _boardextra1 = None + + def __str__(self): + formatstr = "version: %x\n" \ + "length: %d \n" \ + "language:%x \n" \ + "mfg_date:%s \n" \ + "boardManufacturer:%s \n" \ + "boardProductName:%s \n" \ + "boardSerialNumber:%s \n" \ + "boardPartNumber:%s \n" \ + "fruFileId:%s \n" \ + "boardextra1:%d \n" + + return formatstr % (ord(self.boardversion), self.size, self.language, self.getMfgRealData(), self.boardManufacturer, + self.boardProductName, self.boardSerialNumber, self.boardPartNumber, + self.fruFileId, int(self.boardextra1,16)) + # return json.load(self.__dict__) + def todict(self): + dic = collections.OrderedDict() + dic["boardversion"]= ord(self.boardversion) + dic["boardlength"]= self.size + dic["boardlanguage"]=self.language + dic["boardmfg_date"]=self.getMfgRealData() + dic["boardManufacturer"]=self.boardManufacturer + dic["boardProductName"]=self.boardProductName + dic["boardSerialNumber"]=self.boardSerialNumber + dic["boardPartNumber"]=self.boardPartNumber + dic["boardfruFileId"]=self.fruFileId + dic["boardextra1"]= int(self.boardextra1,16) + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] + index += 1 + d_print("decode length :%d class size:%d" % + ((ord(self.data[index]) * 8), self.size)) + index += 2 + + timetmp = self.data[index: index + 3] + self.mfg_date = ord(timetmp[0]) | ( + ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) + d_print("decode getMfgRealData :%s" % self.getMfgRealData()) + index += 3 + + templen = E2Util.decodeLength(self.data[index]) + self.boardManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardManufacturer:%s" % self.boardManufacturer) + + templen = E2Util.decodeLength(self.data[index]) + self.boardProductName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardProductName:%s" % self.boardProductName) + + templen = E2Util.decodeLength(self.data[index]) + self.boardSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) + + templen = E2Util.decodeLength(self.data[index]) + self.boardPartNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardPartNumber:%s" % self.boardPartNumber) + + templen = E2Util.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + templen = E2Util.decodeLength(self.data[index]) + self.boardextra1 = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardextra1:%s" % self.boardextra1) + + pass + + def recalcute(self): + d_print("boardInfoArea version:%x" % ord(self.boardversion)) + d_print("boardInfoArea length:%d" % self.size) + d_print("boardInfoArea language:%x" % self.language) + self.mfg_date = E2Util.minToData() + d_print("boardInfoArea mfg_date:%x" % self.mfg_date) + + self.data = chr(ord(self.boardversion)) + \ + chr(self.size / 8) + chr(self.language) + + self.data += chr(self.mfg_date & 0xFF) + self.data += chr((self.mfg_date >> 8) & 0xFF) + self.data += chr((self.mfg_date >> 16) & 0xFF) + + d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) + typelength = E2Util.getTypeLength(self.boardManufacturer) + self.data += chr(typelength) + self.data += self.boardManufacturer + + d_print("boardInfoArea boardProductName:%s" % self.boardProductName) + self.data += chr(E2Util.getTypeLength(self.boardProductName)) + self.data += self.boardProductName + + d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) + self.data += chr(E2Util.getTypeLength(self.boardSerialNumber)) + self.data += self.boardSerialNumber + + d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) + self.data += chr(E2Util.getTypeLength(self.boardPartNumber)) + self.data += self.boardPartNumber + + d_print("boardInfoArea fruFileId:%s" % self.fruFileId) + self.data += chr(E2Util.getTypeLength(self.fruFileId)) + self.data += self.fruFileId + + if self.boardextra1 != None: + d_print("boardInfoArea boardextra1:%s" % self.boardextra1) + self.data += chr(E2Util.getTypeLength(self.boardextra1)) + self.data += self.boardextra1 + + self.data += chr(0xc1) + d_print("self.data:%d" % len(self.data)) + d_print("self.size:%d" % self.size) + + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + + for tianchong in range(self.size - len(self.data) - 1): + self.data += self.INITVALUE + + test = 0 + for index in range(len(self.data)): + test += ord(self.data[index]) + + # checksum + checksum = (0x100 - (test % 256)) if (test % 256) != 0 else 0 + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + def getMfgRealData(self): + starttime = datetime(1996, 1, 1, 0, 0, 0) + mactime = starttime + timedelta(minutes=self.mfg_date) + return mactime + + @property + def language(self): + self._language = 25 + return self._language + + @property + def mfg_date(self): + return self._mfg_date + + @property + def boardversion(self): + self._boardversion = self.COMMON_HEAD_VERSION + return self._boardversion + + @property + def fruFileId(self): + return self._FRUFileID + + @property + def boardextra1(self): + return self._boardextra1 + + @property + def boardPartNumber(self): + return self._boardPartNumber + + @property + def boardSerialNumber(self): + return self._boardSerialNumber + + @property + def boardProductName(self): + return self._boradProductName + + @property + def boardManufacturer(self): + return self._boardManufacturer + + @property + def boardTime(self): + return self._boardTime + + @property + def fields(self): + return self._fields + + +class ProductInfoArea(BaseArea): + _productExtra1 = None + _productExtra2 = None + _productExtra3 = None + _productManufacturer = None + _productAssetTag = None + _FRUFileID = None + + def __str__(self): + formatstr = "version: %x\n" \ + "length: %d \n" \ + "language::%x \n" \ + "productManufacturer:%s \n" \ + "productName:%s \n" \ + "productPartModelName:%s \n" \ + "productVersion:%d \n" \ + "productSerialNumber:%s \n" \ + "productAssetTag:%s \n" \ + "fruFileId:%s \n" \ + "productExtra1:%s \n"\ + "productExtra2:%s \n"\ + "productExtra3:%s \n" + + return formatstr % (ord(self.areaversion), self.size, self.language, self.productManufacturer, self.productName, + self.productPartModelName, int(self.productVersion, 16), self.productSerialNumber, + self.productAssetTag,self.fruFileId, self.productExtra1, + E2Util.decodeMac(self.productExtra2), E2Util.decodeMacLen(self.productExtra3)) + + def todict(self): + dic = collections.OrderedDict() + dic["productversion"]= ord(self.areaversion) + dic["productlength"]= self.size + dic["productlanguage"]=self.language + dic["productManufacturer"]=self.productManufacturer + dic["productName"]=self.productName + dic["productPartModelName"]=self.productPartModelName + dic["productVersion"]= int(self.productVersion, 16) + dic["productSerialNumber"]=self.productSerialNumber + dic["productAssetTag"]=self.productAssetTag + dic["productfruFileId"]= self.fruFileId + dic["productExtra1"]=self.productExtra1 + dic["productExtra2"]=E2Util.decodeMac(self.productExtra2) + dic["productExtra3"]= E2Util.decodeMacLen(self.productExtra3) + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] # 0 + index += 1 + d_print("decode length %d" % (ord(self.data[index]) * 8)) + d_print("class size %d" % self.size) + index += 2 + + templen = E2Util.decodeLength(self.data[index]) + self.productManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productManufacturer:%s" % self.productManufacturer) + + templen = E2Util.decodeLength(self.data[index]) + self.productName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productName:%s" % self.productName) + + templen = E2Util.decodeLength(self.data[index]) + self.productPartModelName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productPartModelName:%s" % self.productPartModelName) + + templen = E2Util.decodeLength(self.data[index]) + self.productVersion = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productVersion:%s" % self.productVersion) + + templen = E2Util.decodeLength(self.data[index]) + self.productSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productSerialNumber:%s" % self.productSerialNumber) + + + templen = E2Util.decodeLength(self.data[index]) + self.productAssetTag = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productAssetTag:%s" % self.productAssetTag) + + + templen = E2Util.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + if index < self.size and self.data[index] != chr(0xC1): # end + templen = E2Util.decodeLength(self.data[index]) + self.productExtra1 = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productExtra1:%s" % self.productExtra1) + if index < self.size and self.data[index] != chr(0xC1): # end + templen = E2Util.decodeLength(self.data[index]) + self.productExtra2 = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productExtra2:%s" % + E2Util.decodeMac(self.productExtra2)) + if index < self.size and self.data[index] != chr(0xC1): # end + templen = E2Util.decodeLength(self.data[index]) + self.productExtra3 = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productExtra3:%s" % + E2Util.decodeMacLen(self.productExtra3)) + + @property + def productVersion(self): + return self._productVersion + + @property + def areaversion(self): + self._areaversion = self.COMMON_HEAD_VERSION + return self._areaversion + + @property + def language(self): + self._language = 25 + return self._language + + @property + def productManufacturer(self): + return self._productManufacturer + + @property + def productName(self): + return self._productName + + @property + def productPartModelName(self): + return self._productPartModelName + + @property + def productSerialNumber(self): + return self._productSerialNumber + + @property + def productAssetTag(self): + return self._productAssetTag + + @property + def fruFileId(self): + return self._FRUFileID + + @property + def productExtra1(self): + return self._productExtra1 + + @property + def productExtra2(self): + return self._productExtra2 + + @property + def productExtra3(self): + return self._productExtra3 + + def recalcute(self): + d_print("product version:%x" % ord(self.areaversion)) + d_print("product length:%d" % self.size) + d_print("product language:%x" % self.language) + self.data = chr(ord(self.areaversion)) + \ + chr(self.size / 8) + chr(self.language) + + typelength = E2Util.getTypeLength(self.productManufacturer) + self.data += chr(typelength) + self.data += self.productManufacturer + + self.data += chr(E2Util.getTypeLength(self.productName)) + self.data += self.productName + + self.data += chr(E2Util.getTypeLength(self.productPartModelName)) + self.data += self.productPartModelName + + self.data += chr(E2Util.getTypeLength(self.productVersion)) + self.data += self.productVersion + + self.data += chr(E2Util.getTypeLength(self.productSerialNumber)) + self.data += self.productSerialNumber + + self.data += chr(E2Util.getTypeLength(self.productAssetTag)) + if self.productAssetTag != None: + self.data += self.productAssetTag + + self.data += chr(E2Util.getTypeLength(self.fruFileId)) + if self.fruFileId != None: + self.data += self.fruFileId + + if self.productExtra1 != None: + self.data += chr(E2Util.getTypeLength(self.productExtra1)) + self.data += self.productExtra1 + + if self.productExtra2 != None: + self.data += chr(E2Util.getTypeLength(self.productExtra2)) + self.data += self.productExtra2 + + if self.productExtra3 != None: + self.data += chr(E2Util.getTypeLength(self.productExtra3)) + self.data += self.productExtra3 + + self.data += chr(0xc1) + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + d_print("self.data:%d" % len(self.data)) + d_print("self.size:%d" % self.size) + for tianchong in range(self.size - len(self.data) - 1): + self.data += self.INITVALUE + test = 0 + for index in range(len(self.data)): + test += ord(self.data[index]) + checksum = (0x100 - (test % 256)) if (test % 256) != 0 else 0 + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + +class MultiRecordArea(BaseArea): + pass + + +class Field(): + + def __init__(self, fieldType="ASCII", fieldData=""): + self.fieldData = fieldData + self.fieldType = fieldType + + @property + def data(self): + return self._data + + @property + def fieldType(self): + return self._fieldType + + @property + def fieldData(self): + return self._fieldData + + +class CommonArea(BaseArea): + _internalUserAreaOffset = None + _InternalUseArea = None + _ChassisInfoArea = None + _multiRecordArea = None + _chassicInfoAreaOffset = None + _multiRecordAreaOffset = None + + def decodeBin(self, eeprom): + commonHead = eeprom[0:8] + d_print("decode version %x" % ord(commonHead[0])) + if self.COMMON_HEAD_VERSION != commonHead[0]: + print ("not equal") + if E2Util.checksum(commonHead[0:7]) != ord(commonHead[7]): + print ("check sum error") + sys.exit(-1) + if commonHead[1] != self.INITVALUE: + d_print("Internal Use Area is present") + self.internalUseArea = InternalUseArea( + name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) + self.internalUseArea.isPresent = True + self.internalUserAreaOffset = ord(commonHead[1]) + self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( + self.internalUserAreaOffset * 8 + self.internalUseArea.size)] + if commonHead[2] != self.INITVALUE: + d_print("Chassis Info Area is present") + self.chassisInfoArea = ChassisInfoArea( + name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) + self.chassisInfoArea.isPresent = True + self.chassicInfoAreaOffset = ord(commonHead[2]) + self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( + self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] + if commonHead[3] != self.INITVALUE: + self.boardInfoArea = BoardInfoArea( + name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) + self.boardInfoArea.isPresent = True + self.boardInfoAreaOffset = ord(commonHead[3]) + self.boardInfoArea.size = ord( + eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 + d_print("Board Info Area is present size:%d" % + (self.boardInfoArea.size)) + self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( + self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] + if E2Util.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): + print ("check boardInfoArea checksum error[cal:%02x data:%02x]" % (E2Util.checksum(self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:]))) + sys.exit(-1) + self.boardInfoArea.decodedata() + if commonHead[4] != self.INITVALUE: + d_print("Product Info Area is present") + self.productInfoArea = ProductInfoArea( + name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) + self.productInfoArea.isPresent = True + self.productinfoAreaOffset = ord(commonHead[4]) + + self.productInfoArea.size = ord( + eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 + d_print("Product Info Area is present size:%d" % + (self.productInfoArea.size)) + + self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( + self.productinfoAreaOffset * 8 + self.productInfoArea.size)] + if E2Util.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): + print ("check productInfoArea checksum error [cal:%02x data:%02x]" % (E2Util.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:]))) + sys.exit(-1) + self.productInfoArea.decodedata() + if commonHead[5] != self.INITVALUE: + self.multiRecordArea = MultiRecordArea( + name="MultiRecord record Area ") + d_print("MultiRecord record present") + self.multiRecordArea.isPresent = True + self.multiRecordAreaOffset = ord(commonHead[5]) + self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( + self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] + # self.recalcute() + + def initDefault(self): + self.version = self.COMMON_HEAD_VERSION + self.internalUserAreaOffset = self.INITVALUE + self.chassicInfoAreaOffset = self.INITVALUE + self.boardInfoAreaOffset = self.INITVALUE + self.productinfoAreaOffset = self.INITVALUE + self.multiRecordAreaOffset = self.INITVALUE + self.PAD = self.INITVALUE + self.zeroCheckSum = self.INITVALUE + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + self.productInfoArea = None + self.internalUseArea = None + self.boardInfoArea = None + self.chassisInfoArea = None + self.multiRecordArea = None + self.recalcute() + + @property + def version(self): + return self._version + + @property + def internalUserAreaOffset(self): + return self._internalUserAreaOffset + + @property + def chassicInfoAreaOffset(self): + return self._chassicInfoAreaOffset + + @property + def productinfoAreaOffset(self): + return self._productinfoAreaOffset + + @property + def boardInfoAreaOffset(self): + return self._boardInfoAreaOffset + + @property + def multiRecordAreaOffset(self): + return self._multiRecordAreaOffset + + @property + def PAD(self): + return self._PAD + + @property + def zeroCheckSum(self): + return self._zeroCheckSum + + @property + def productInfoArea(self): + return self._ProductInfoArea + + @property + def internalUseArea(self): + return self._InternalUseArea + + @property + def boardInfoArea(self): + return self._BoardInfoArea + + @property + def chassisInfoArea(self): + return self._ChassisInfoArea + + @property + def multiRecordArea(self): + return self._multiRecordArea + + @property + def bindata(self): + return self._bindata + + def recalcuteCommonHead(self): + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + d_print("common Header %d" % self.offset) + if self.internalUseArea != None and self.internalUseArea.isPresent: + self.internalUserAreaOffset = self.offset / 8 + self.offset += self.internalUseArea.size + d_print("internalUseArea is present offset:%d" % self.offset) + if self.chassisInfoArea != None and self.chassisInfoArea.isPresent: + self.chassicInfoAreaOffset = self.offset / 8 + self.offset += self.chassisInfoArea.size + d_print("chassisInfoArea is present offset:%d" % self.offset) + if self.boardInfoArea != None and self.boardInfoArea.isPresent: + self.boardInfoAreaOffset = self.offset / 8 + self.offset += self.boardInfoArea.size + d_print("boardInfoArea is present offset:%d" % self.offset) + + if self.productInfoArea != None and self.productInfoArea.isPresent: + self.productinfoAreaOffset = self.offset / 8 + self.offset += self.productInfoArea.size + d_print("productInfoArea is present offset:%d" % self.offset) + if self.multiRecordArea != None and self.multiRecordArea.isPresent: + self.multiRecordAreaOffset = self.offset / 8 + d_print("multiRecordArea is present offset:%d" % self.offset) + + if self.internalUserAreaOffset == self.INITVALUE: + self.internalUserAreaOffset = 0 + if self.productinfoAreaOffset == self.INITVALUE: + self.productinfoAreaOffset = 0 + if self.chassicInfoAreaOffset == self.INITVALUE: + self.chassicInfoAreaOffset = 0 + if self.boardInfoAreaOffset == self.INITVALUE: + self.boardInfoAreaOffset = 0 + if self.multiRecordAreaOffset == self.INITVALUE: + self.multiRecordAreaOffset = 0 + self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset \ + - self.boardInfoAreaOffset - self.multiRecordAreaOffset)&0xff + d_print("zerochecksum:%x" % self.zeroCheckSum) + self.data = self.version + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( + self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + self.PAD + chr(self.zeroCheckSum) + + def recalcutebin(self): + self.bindata = "" + self.bindata += self.data + if self.internalUseArea != None and self.internalUseArea.isPresent: + d_print("internalUseArea is present") + self.bindata += self.internalUseArea.data + if self.chassisInfoArea != None and self.chassisInfoArea.isPresent: + d_print("chassisInfoArea is present") + self.bindata += self.chassisInfoArea.data + if self.boardInfoArea != None and self.boardInfoArea.isPresent: + d_print("boardInfoArea is present") + self.boardInfoArea.recalcute() + self.bindata += self.boardInfoArea.data + if self.productInfoArea != None and self.productInfoArea.isPresent: + d_print("productInfoArea is present") + self.productInfoArea.recalcute() + self.bindata += self.productInfoArea.data + if self.multiRecordArea != None and self.multiRecordArea.isPresent: + d_print("multiRecordArea is present") + self.bindata += self.productInfoArea.data + totallen = len(self.bindata) + if (totallen < 256): + for left_t in range(0, 256 - totallen): + self.bindata += chr(0x00) + + def recalcute(self): + self.recalcuteCommonHead() + self.recalcutebin() + + +class E2Util(): + + BOARDINFOAREAISPRESETN = 'boardinfoarea.ispresent' + BOARDINFOAREABOARDMANUFACTURER = 'boardinfoarea.boardmanufacturer' + BOARDINFOAREABORADPRODUCTNAME = 'boardinfoarea.boradproductname' + BOARDINFOAREABOARDSERIALNUMBER = 'boardinfoarea.boardserialnumber' + BOARDINFOAREABOARDPARTNUMBER = 'boardinfoarea.boardpartnumber' + BOARDINFOAREAFRUFILEID = 'boardinfoarea.frufileid' + BOARDINFOAREAFEXTRA1 = 'boardinfoarea.boardextra1' + + PRODUCTINFOAREAISPRESENT = "productInfoArea.ispresent" + PRODUCTINFOAREAPRODUCTMANUFACTURER = 'productinfoarea.productmanufacturer' + PRODUCTINFOAREAPRODUCTNAME = 'productinfoarea.productname' + PRODUCTINFOAREAPRODUCTPARTMODELNAME = 'productinfoarea.productpartmodelname' + PRODUCTINFOAREAPRODUCTVERSION = 'productinfoarea.productversion' + PRODUCTINFOAREAPRODUCTSERIALNUMBER = 'productinfoarea.productserialnumber' + PRODUCTINFOAREAPRODUCTASSETTAG = 'productinfoarea.productassettag' + PRODUCTINFOAREAFRUFILEID = 'productinfoarea.frufileid' + PRODUCTINFOAREAEXTRA1 = 'productinfoarea.productextra1' + PRODUCTINFOAREAEXTRA2 = 'productinfoarea.productextra2' + PRODUCTINFOAREAEXTRA3 = 'productinfoarea.productextra3' + + @staticmethod + def equals(x, typeV): + if x.strip()[-1] == typeV: + return True + else: + return False + + @staticmethod + def decodeBinByValue(retval): + fru = CommonArea() + fru.initDefault() + fru.decodeBin(retval) + return fru + + @staticmethod + def getBoardInfoAreaByProperty(prop): + boardinfoarea = None + try: + boradispresent = prop[E2Util.BOARDINFOAREAISPRESETN] + if (boradispresent == "1"): + boardinfoarea = BoardInfoArea(name="Board Info Area", + size=0) + boardinfoarea.isPresent = True + boardinfoarea.boardManufacturer = prop[E2Util.BOARDINFOAREABOARDMANUFACTURER] + boardinfoarea.boardProductName = prop[E2Util.BOARDINFOAREABORADPRODUCTNAME] + boardinfoarea.boardSerialNumber = prop[E2Util.BOARDINFOAREABOARDSERIALNUMBER] + boardinfoarea.boardPartNumber = prop[E2Util.BOARDINFOAREABOARDPARTNUMBER] + boardinfoarea.fruFileId = prop[E2Util.BOARDINFOAREAFRUFILEID] + boardinfoarea.boardextra1 = prop[E2Util.BOARDINFOAREAFEXTRA1] + boardinfoarea.recalcute() + else: + boardinfoarea = None + except Exception as e: + raise e + boardinfoarea = None + return boardinfoarea + + @staticmethod + def getProductInfoAreaByProperty(prop): + productInfoArea = None + try: + productispresent = prop[E2Util.PRODUCTINFOAREAISPRESENT] + if (productispresent == "1"): + productInfoArea = ProductInfoArea(name="Product Info Area ", + size=0) + productInfoArea.isPresent = True + + productInfoArea.productManufacturer = prop[E2Util.PRODUCTINFOAREAPRODUCTMANUFACTURER] + productInfoArea.productName = prop[E2Util.PRODUCTINFOAREAPRODUCTNAME] + productInfoArea.productPartModelName = prop[E2Util.PRODUCTINFOAREAPRODUCTPARTMODELNAME] + productInfoArea.productVersion = prop[E2Util.PRODUCTINFOAREAPRODUCTVERSION] + productInfoArea.productSerialNumber = prop[E2Util.PRODUCTINFOAREAPRODUCTSERIALNUMBER] + # productInfoArea.fruFileId = prop[E2Util.PRODUCTINFOAREAFRUFILEID] + val_t = E2Util.getTimeFormat() + if val_t != None: + productInfoArea.productExtra1 = val_t + if prop.__contains__(E2Util.PRODUCTINFOAREAEXTRA2): + # Extra2 Special Processing (MAC address) + macaddr = prop[E2Util.PRODUCTINFOAREAEXTRA2] + if macaddr != None: + productInfoArea.productExtra2 = E2Util.encodeMac( + macaddr) + if prop.__contains__(E2Util.PRODUCTINFOAREAEXTRA3): + # Extra3 Special Processing + productInfoArea.productExtra3 = E2Util.encodeMacLen( + prop[E2Util.PRODUCTINFOAREAEXTRA3]) + productInfoArea.recalcute() + else: + productInfoArea = None + + except Exception as e: + print ("error") + productInfoArea = None + return productInfoArea + + @staticmethod + def generateBinBySetMac(bia, pia): + fru = CommonArea() + fru.initDefault() + if bia != None: + fru.boardInfoArea = bia + if pia != None: + fru.productInfoArea = pia + fru.recalcute() + return fru + + @staticmethod + def generateBinByInput(prop): + bia = E2Util.getBoardInfoAreaByProperty(prop) + pia = E2Util.getProductInfoAreaByProperty(prop) + fru = CommonArea() + fru.initDefault() + if bia != None: + fru.boardInfoArea = bia + if pia != None: + fru.productInfoArea = pia + fru.recalcute() + return fru + + @staticmethod + def defaultBinByConfig(product, typeVal): + filename = CONFIG_FILE + dir = os.path.dirname(os.path.realpath(__file__)) + if filename in os.listdir(dir): + filename = os.path.join(dir, filename) + return E2Util.generateBinByConfig(filename, product, typeVal) + + @staticmethod + def generateBinByConfig(filename, product, typeVal): + fileconf = E2Util.getConfig(filename) + if product not in fileconf.ProductsTypes: + raise E2Exception("product type not in Success") + productParts = fileconf.getProductSections(product) + if len(productParts) <= 0: + raise E2Exception("config file has no product config") + # print typeVal + ret_t = filter(lambda x: E2Util.equals(x, typeVal), productParts) + if len(ret_t) <= 0: + raise E2Exception("config file has no child eeprom config") + # print "".join(ret_t) + bia = E2Util.getBoardInfoAreaConfigFile(fileconf, "".join(ret_t)) + pia = E2Util.getProductInfoAreaConfigFile(fileconf, "".join(ret_t)) + + fru = CommonArea() + fru.initDefault() + + if bia != None: + fru.boardInfoArea = bia + if pia != None: + fru.productInfoArea = pia + fru.recalcute() + return fru + + @staticmethod + def getProductInfoAreaConfigFile(conf, part): + pia = None + try: + productispresent = conf.getProductName( + E2Util.PRODUCTINFOAREAISPRESENT, part) + if (productispresent == "1"): + pia = ProductInfoArea(name="Product Info Area ", + size=0) + pia.isPresent = True + + pia.productManufacturer = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTMANUFACTURER, part) + pia.productName = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTNAME, part) + pia.productPartModelName = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTPARTMODELNAME, part) + pia.productVersion = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTVERSION, part) + pia.productSerialNumber = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTSERIALNUMBER, part) + pia.productAssetTag = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTASSETTAG, part) + # print pia.productAssetTag + pia.fruFileId = conf.getProductName( + E2Util.PRODUCTINFOAREAFRUFILEID, part) + val_t = E2Util.getTimeFormat() + if val_t != None: + pia.productExtra1 = val_t + # Extra2 Special Processing (MAC address) + macaddr = conf.getProductName( + E2Util.PRODUCTINFOAREAEXTRA2, part) + if macaddr != None: + pia.productExtra2 = E2Util.encodeMac(macaddr) + # Extra3 Special Processing + pia.productExtra3 = E2Util.encodeMacLen(conf.getProductName( + E2Util.PRODUCTINFOAREAEXTRA3, part)) + pia.recalcute() + else: + pia = None + + except Exception as e: + print (e) + pia = None + return pia + + @staticmethod + def getBoardInfoAreaConfigFile(conf, part): + boardinfoarea = None + try: + boradispresent = conf.getProductName( + E2Util.BOARDINFOAREAISPRESETN, part) + if (boradispresent == "1"): + boardinfoarea = BoardInfoArea(name="Board Info Area", + size=0) + boardinfoarea.isPresent = True + boardinfoarea.boardManufacturer = conf.getProductName( + E2Util.BOARDINFOAREABOARDMANUFACTURER, part) + boardinfoarea.boardProductName = conf.getProductName( + E2Util.BOARDINFOAREABORADPRODUCTNAME, part) + boardinfoarea.boardSerialNumber = conf.getProductName( + E2Util.BOARDINFOAREABOARDSERIALNUMBER, part) + boardinfoarea.boardPartNumber = conf.getProductName( + E2Util.BOARDINFOAREABOARDPARTNUMBER, part) + boardinfoarea.fruFileId = conf.getProductName( + E2Util.BOARDINFOAREAFRUFILEID, part) + boardinfoarea.boardextra1 = conf.getProductName( + E2Util.BOARDINFOAREAFEXTRA1, part) + boardinfoarea.recalcute() + else: + boardinfoarea = None + except Exception as e: + print (e) + boardinfoarea = None + return boardinfoarea + + @staticmethod + def decodeBinName(filename): + retval = None + try: + with open(filename, 'rb') as fd: + retval = fd.read() + except Exception: + print ("open file error") + return + return E2Util.decodeBinByValue(retval) + + + @staticmethod + def decodeMac(encodedata): + if encodedata == None: + return None + ret = "" + for i in range(len(encodedata)): + ret += "%02x" % ord(encodedata[i]) + return ret.upper() + + @staticmethod + def strtoint(strtmp): + value = 0 + rest_v = strtmp.replace("0X", "").replace("0x", "") + for index in range(len(rest_v)): + value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4) + return value + + @staticmethod + def decodeMacLen(lenstr): + if lenstr == None: + return None + maclen = ord(lenstr[0]) << 8 | ord(lenstr[1]) + return maclen + + @staticmethod + def encodeMac(macaddr): + ret_t = "" + if len(macaddr) != 12: + return None + for i in range(6): + tt = macaddr[2 * i: 2 * i + 2] + ret_t += chr(int(tt, 16)) + return ret_t + + @staticmethod + def encodeMacLen(strlem): + val_t = int(strlem) + temp_t = chr(val_t >> 8) + chr(val_t & 0x00ff) + return temp_t + + @staticmethod + def loadconfig(): + global conf + conf = E2Config() + return conf + + @staticmethod + def getConfig(filename): + return E2Config(filename) + + + @staticmethod + def getdefaultconfig(): + filename = CONFIG_FILE + dir = os.path.dirname(os.path.realpath(__file__)) + if filename in os.listdir(dir): + filename = os.path.join(dir, filename) + config = E2Util.getConfig(filename) + ret = {} + for i in config.ProductsTypes: + ret[config.getProductName(i)] = i + return ret + + @staticmethod + def createFruBin(filename, boardinfoarea, productInfoArea): + fru = CommonArea() + fru.initDefault() + + if boardinfoarea != None: + fru.boardInfoArea = boardinfoarea + if productInfoArea != None: + fru.productInfoArea = productInfoArea + + fru.recalcute() + E2Util.write_bin_file(filename, fru.bindata) + + @staticmethod + def createpartbin(part): + try: + bia = None + pia = None + + boradispresent = conf.getProductName( + E2Util.BOARDINFOAREAISPRESETN, part) + if (boradispresent == "1"): + bia = BoardInfoArea(name="Board Info Area", + size=0) + bia.isPresent = True + bia.boardManufacturer = conf.getProductName( + E2Util.BOARDINFOAREABOARDMANUFACTURER, part) + bia.boardProductName = conf.getProductName( + E2Util.BOARDINFOAREABORADPRODUCTNAME, part) + bia.boardSerialNumber = conf.getProductName( + E2Util.BOARDINFOAREABOARDSERIALNUMBER, part) + bia.boardPartNumber = conf.getProductName( + E2Util.BOARDINFOAREABOARDPARTNUMBER, part) + bia.fruFileId = conf.getProductName( + E2Util.BOARDINFOAREAFRUFILEID, part) + bia.boardextra1 = conf.getProductName( + E2Util.BOARDINFOAREAFEXTRA1, part) + bia.recalcute() + + productispresent = conf.getProductName( + E2Util.PRODUCTINFOAREAISPRESENT, part) + if (productispresent == "1"): + pia = ProductInfoArea(name="Product Info Area ", + size=0) + pia.isPresent = True + + pia.productManufacturer = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTMANUFACTURER, part) + pia.productName = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTNAME, part) + pia.productPartModelName = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTPARTMODELNAME, part) + pia.productVersion = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTVERSION, part) + pia.productSerialNumber = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTSERIALNUMBER, part) + pia.productAssetTag = conf.getProductName( + E2Util.PRODUCTINFOAREAPRODUCTASSETTAG, part) + pia.fruFileId = conf.getProductName( + E2Util.PRODUCTINFOAREAFRUFILEID, part) + val_t = E2Util.getTimeFormat() + if val_t != None: + pia.productExtra1 = val_t + # Extra2 Special Processing (MAC address + macaddr = conf.getProductName( + E2Util.PRODUCTINFOAREAEXTRA2, part) + if macaddr != None: + pia.productExtra2 = E2Util.encodeMac(macaddr) + # Extra3 Special Processing + pia.productExtra3 = E2Util.encodeMacLen(conf.getProductName( + E2Util.PRODUCTINFOAREAEXTRA3, part)) + pia.recalcute() + + filename = conf.getPartBinName(part) + print ("filename", filename) + E2Util.createFruBin(filename, bia, pia) + except Exception as e: + print (e) + + @staticmethod + def checksum(b): + result = 0 + for i in range(len(b)): + result += ord(b[i]) + return (0x100 - (result % 256)) if (result % 256) != 0 else 0 + + @staticmethod + def decodeLength(value): + a = bitarray(8) + a.setall(True) + a[0:1] = 0 + a[1:2] = 0 + x = ord(a.tobytes()) + return x & ord(value) + + @staticmethod + def getTypeLength(value): + if value == None: + return 0 + a = bitarray(8) + a.setall(False) + a[0:1] = 1 + a[1:2] = 1 + x = ord(a.tobytes()) + return x | len(value) + + @staticmethod + def minToData(): + starttime = datetime(1996, 1, 1, 0, 0, 0) + endtime = datetime.now() + seconds = (endtime - starttime).total_seconds() + mins = seconds / 60 + m = int(round(mins)) + return m + + @staticmethod + def mfgToTime(val): + starttime = datetime(1996, 1, 1, 0, 0, 0) + + + @staticmethod + def getTimeFormat(): + return datetime.now().strftime('%Y-%m-%d') + + @staticmethod + def printbinvalue(b): + index = 0 + print (" ",) + for width in range(16): + print ("%02x " % width,) + print ("") + for i in range(0, len(b)): + if index % 16 == 0: + print (" ") + print (" %02x " % i,) + print ("%02x " % ord(b[i]),) + index += 1 + print ("") + + @staticmethod + def write_bin_file(filename, _value): + retname = "test/" + filename + with open(retname, 'wb') as filep: + for x in _value: + filep.write(str(x)) + filep.close() + + @staticmethod + def getRemoteConfig(url): + res = requests.get(url) + print (res.content) + f = open('bin.conf', 'w') + f.write(res.content) + return res.text + + +class E2Config(): + _CONFIG_PRODUCT_SECTON = "products" + _CONFIG_TYPENAME_SECTON = "typename" + + def __init__(self, filename=CONFIG_FILE): + cf = ConfigParser.ConfigParser() + cf.read(filename) + if os.path.exists(filename) != True: + raise E2Exception("init E2Config error") + self.configparse = cf + self.Sections = cf.sections() + self.ProductsTypes = cf.options(self._CONFIG_PRODUCT_SECTON) + + def getProductPartItem(self, section): + return self.configparse.options(section) + + def getPartBinName(self, part): + part = part.rstrip() + fileprename = self.getProductName( + part[-1:], self._CONFIG_TYPENAME_SECTON) + return (part + "_" + fileprename + ".bin").lower().replace("-", "_") + + def getProductName(self, name, section=_CONFIG_PRODUCT_SECTON): + try: + return self.configparse.get(section, name) + except Exception: + return None + + def loadFile(self): + pass + + def getProductSections(self, typeindex): + typename = self.getProductName(typeindex) + return filter(lambda x: typename in x, self.Sections) + + @property + def ProductsTypes(self): + return self._productTypes + + @property + def Sections(self): + return self._sections + + @property + def configparse(self): + return self._configparse + + +def main(arg): + '''create bin''' + E2Util.loadconfig() + if len(arg) < 1: + usage() + sys.exit(1) + producttype = arg[0] + d_print(producttype) + if producttype not in conf.ProductsTypes: + usage() + sys.exit(1) + + productParts = conf.getProductSections(producttype) + print ("productParts", productParts) + print ("产品名称: %s" % conf.getProductName(producttype)) + if len(productParts) <= 0: + print ("没有配置项") + for part in productParts: + print (" 生成文件: %s" % conf.getPartBinName(part)) + E2Util.createpartbin(part) + + +def usage(): + print("Usage: [e2.py product ]") + print(" example: e2.py 1 ") + print(" userless-product :") + for card in conf.ProductsTypes: + print (" %s %s" % (card, conf.getProductName(card))) + + +if __name__ == '__main__': + # main(sys.argv[1:]) + main(["1"]) + main(["2"]) + main(["3"]) + main(["4"]) + main(["5"]) + main(["6"]) + pass diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/product.conf b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/product.conf new file mode 100644 index 000000000000..0b60083dca34 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/fruutil/product.conf @@ -0,0 +1,67 @@ +[products] +6 = BMCEEPROM +17 = CPUM-C7EDN6-U2 +26 = EMMC-CARD +33 = RA-B6010-48GT4X +# 1 TLV EEPROM 0x56 +# 2 X86 CPU EEPROM +# 3 BMC EEPROM +# 4 CPU BASE_BOARD EEPROM 0x57 +# 5 MAC BOARD EEPROM +# 6.Line card EEPROM (128) +# 7.Fan adapter EEPROM +# 8.Fan the small plate EEPROM +# 9.PSU FRU EEPROM +[typename] +1= tlveeprom +2= x86cpueeprom +3= bmceeprom +4= cpueeprom +5= maceeprom +6= sloteeprom +7= fanconnecteeprom +8= M1HFANI-F +9= M1HFANI-R +A= M2HFANI-F +B= M2HFANI-R +C= psu +M = RA-EMMC-CARD +Q = ibvbeeprom + +[BMCEEPROM-3] +boardinfoarea.ispresent = 1 +boardinfoarea.boardManufacturer = Ragile +boardinfoarea.boradProductName = BMC +boardinfoarea.boardSerialNumber = 0000000000000 +boardinfoarea.boardPartNumber = BMC +boardinfoarea.FRUFileID = 6-3 +boardinfoarea.boardextra1 = AA + +[RA-B6010-48GT4X-4] +productInfoArea.ispresent = 1 +productInfoArea.productManufacturer = Ragile +productInfoArea.productName = RA-B6010-48GT4X +productInfoArea.productPartModelName = RA-B6010-48GT4X +productInfoArea.productVersion = 00 +productInfoArea.productSerialNumber = 0000000000000 +productInfoArea.FRUFileID = 33-4 +productInfoArea.productExtra1 = 2020-12-20 +productInfoArea.productExtra2 = 1a2b3c4d5e6f +productInfoArea.productExtra3 = 2 + +boardinfoarea.ispresent = 1 +boardinfoarea.boardManufacturer = Ragile +boardinfoarea.boradProductName = RA-B6010-48GT4X +boardinfoarea.boardSerialNumber = 0000000000000 +boardinfoarea.boardPartNumber = RA-B6010-48GT4X +boardinfoarea.FRUFileID = 33-4 +boardinfoarea.boardextra1 = AA + +[EMMC-CARD-M] +boardinfoarea.ispresent = 1 +boardinfoarea.boardManufacturer = Ragile +boardinfoarea.boradProductName = EMMC-CARD +boardinfoarea.boardSerialNumber = 0000000000000 +boardinfoarea.boardPartNumber = RA-EMMC-CARD +boardinfoarea.FRUFileID = 26-M +boardinfoarea.boardextra1 = AA \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/logutil/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/logutil/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/logutil/logutil.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/logutil/logutil.py new file mode 100644 index 000000000000..0785993c3bd8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/logutil/logutil.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +import sys +import os +import syslog +import logging +import subprocess + +SYSLOG_IDENTIFIER = "LOGUTIL" + +# ========================== Syslog wrappers ========================== + +def log_info(msg,log_type=SYSLOG_IDENTIFIER, also_print_to_console=False): + syslog.openlog(log_type) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + + +def log_debug(msg, log_type=SYSLOG_IDENTIFIER, also_print_to_console=False): + try: + syslog.openlog(log_type) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + except Exception as e: + pass + + +def log_warning(msg, log_type=SYSLOG_IDENTIFIER, also_print_to_console=False): + syslog.openlog(log_type) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +def log_error(msg, log_type=SYSLOG_IDENTIFIER, also_print_to_console=False): + syslog.openlog(log_type) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +restful_logger_path = "/var/log/bmc_restful.log" +def bmc_restful_logger(message): + if not os.path.isfile(restful_logger_path): + cmd = "sudo touch %s && sudo chmod +x %s" % ( + restful_logger_path, restful_logger_path) + subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + logging.basicConfig(filename=restful_logger_path, + filemode='a', + format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', + datefmt='%H:%M:%S', + level=logging.INFO) + + logging.info(message) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/redfishutil/redfish_api.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/redfishutil/redfish_api.py new file mode 100644 index 000000000000..d0d9927d0690 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/redfishutil/redfish_api.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import sys +import json +import traceback +import datetime +import os +import ssl +import subprocess +import syslog + +class Redfish_Api(): + BmcBaseUrl = 'http://240.1.1.1:8080' + ThermalUrl = '/redfish/v1/Chassis/1/Thermal' + PowerUrl = '/redfish/v1/Chassis/1/Power' + ThresholdSensorsUrl = '/redfish/v1/Chassis/1/ThresholdSensors' + FanSpeedUrl = '/redfish/v1/Chassis/1/Thermal/Actions/Oem/Ragile/Fan.SetSpeed' + BoardsUrl = '/redfish/v1/Chassis/1/Boards/' + BoardLedUrl = "/redfish/v1/Chassis/1/Boards/{}/Actions/Oem/Ragile/Boards.SetLED" + + # Maximum time in seconds that you allow the connection to the server to take. + connect_timeout = 30 + # Maximum time in seconds that you allow the whole operation to take + operation_timeout = 300 + + default_prefix='/redfish/v1/' + session = None + __DEBUG__ = "N" + __DUMP_RESP__ = "N" + RST_STATUS = "status" + RST_SUCCESS = "OK" + refish_logger = None + + def redfish_log_debug(self, msg): + if (self.__DEBUG__ == "Y"): + syslog.openlog("redfis_api") + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + def redfish_log_error(self, msg): + syslog.openlog("redfish_api") + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + def __init__(self): + pass + + def get_full_url(self, url): + return self.BmcBaseUrl + url + + def _exec_cmd(self, cmd): + self.redfish_log_debug("Cmd: %s" % cmd) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p.wait() + self.redfish_log_debug("Cmd return: %d" % p.returncode) + str_stdout = p.stdout.read().decode('utf-8') + str_stderr = p.stderr.read().decode('utf-8') + self.redfish_log_debug("Cmd stdout: %s" % str_stdout) + if p.returncode !=0: + self.redfish_log_error("Cmd: %s, failed! error msg:%s" % (cmd, str_stderr)) + return None + else: + try: + ret = json.loads(str_stdout) + return ret + except Exception as e: + self.redfish_log_error("Cmd: %s, failed! stdout msg:%s" % (cmd, str_stdout)) + return None + + def _redfish_get(self, url): + self.redfish_log_debug("Get info from %s." % url) + result = None + try: + cmd_get="curl --connect-timeout %d -m %d -X GET %s" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url)) + result = self._exec_cmd(cmd_get) + except Exception as e: + self.redfish_log_error("error_message: %s" % e) + result = None + finally: + return result + + def _redfish_post(self, url, playload): + self.redfish_log_debug("post url: %s" % url) + self.redfish_log_debug("Playload: %s" % playload) + + playload_json = json.dumps(playload) + result = False + try: + cmd_post="curl --connect-timeout %d -m %d -X POST %s -d \'%s\'" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url), playload_json) + ret_msg = self._exec_cmd(cmd_post) + if ret_msg == None: + return False + elif ret_msg["success"] == False: + redfish_log_error("Url: '%s', Playload: '%s', Bmc return failed, error_message: %s" % (url, playload_json, ret_msg["Message"])) + result = False + else: + result = True + except Exception as e: + redfish_log_error("error_message: %s" % e) + result = False + finally: + return result + + def get_thermal(self): + """Get thermal info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.ThermalUrl) + + def get_power(self): + """Get power info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.PowerUrl) + + def get_thresholdSensors(self): + """Get thresholdSensors info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.ThresholdSensorsUrl) + + def post_odata(self, odata_id, playload): + """post odata info + :params odata_id: the specified odata_id path + :type odata_id: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if odata_id is None or playload is None: + print("post failed: odata_id or playload is None") + return False + return self._redfish_post(odata_id, playload) + + def get_odata(self, odata_id): + """Get odata info + :params odata_id: the specified odata_id path + :type odata_id: string + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + if odata_id is None: + print("Get odata_id failed: odata_id is None") + return None + return self._redfish_get(odata_id) + + def post_fanSpeed(self, playload): + """post odata info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.FanSpeedUrl, playload) + + def get_board(self, board_name="indicatorboard"): + """Get board info + :board_name: name of board, default is "indicatorboard" + :type: string + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + if board_name is None : + print("get failed: board_name is None") + return None + return self._redfish_get(self.BoardsUrl + board_name) + + def post_boardLed(self, playload, board_name="indicatorboard"): + """post boardLed info + :board_name: name of board, default is "indicatorboard" + :type: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if board_name is None or playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.BoardLedUrl.format(board_name), playload) + + ''' not supported currently + def post_thermal(self, playload): + """post thermal info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_thermal failed: playload is None") + return None + return self._redfish_post(self.ThermalUrl, playload) + + def post_power(self, playload): + """post power info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_power failed: playload is None") + return None + return self._redfish_post(self.PowerUrl, playload) + + def post_thresholdSensors(self, playload): + """post thresholdSensors info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_thresholdSensors failed: playload is None") + return None + return self._redfish_post(self.ThresholdSensorsUrl, playload) + + def get_fanSpeed(self): + """Get board led info + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.FanSpeedUrl) + + def post_board(self, playload, board_name="indicatorboard"): + """post board info + :board_name: name of board, default is "indicatorboard" + :type: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if board_name is None or playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.BoardsUrl + board_name, playload) + + def get_boardLed(self, board_name="indicatorboard"): + """Get boardLed info + :board_name: name of board, default is "indicatorboard" + :type: string + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + if board_name is None : + print("get failed: board_name is None") + return None + return self._redfish_get(self.BoardsUrl % board_name) + + ''' + +''' +if __name__ == '__main__': + redfish = Redfish_Api() + + ### get + # boards + ret = redfish.get_board() + if ret is None: + print("get failed: board") + else: + print("get succeeded, board:%s" % ret) + + ret = redfish.get_thresholdSensors() + if ret is None: + print("get failed: threshold") + else: + print("get succeeded, threshold:%s" % ret) + + ret = redfish.get_power() + if ret is None: + print("get failed: power") + else: + print("get succeeded, power:%s" % ret) + + ret = redfish.get_thermal() + if ret is None: + print("get failed:thermal") + else: + print("get succeeded,thermal:%s" % ret) + + # get playload + resp = redfish.get_thresholdSensors() + if (resp != None): + print(resp["@odata.id"]) + print(resp["@odata.type"]) + print(resp["Id"]) + print(resp["Name"]) + else: + print("Failed: get_thresholdSensors") + + ### post + # fanSpeed + playload = {} + playload["FanName"] = 'Fan0' + playload["FanSpeedLevelPercents"] = "70" + print("post fanSpeed:%s" % redfish.post_fanSpeed(playload)) + + #{"LEDs": [{"IndicatorLEDColor": "green","LEDType": "sys"},{"IndicatorLEDColor": "off","LEDType": "pwr"},{"IndicatorLEDColor": "green","LEDType": "fan"}]} + playload = {} + led = {} + led1 = {} + led_list = [] + led["IndicatorLEDColor"] = "green" + led["LEDType"] = "sys" + led1["IndicatorLEDColor"] = "off" + led1["LEDType"] = "pwr" + led_list.append(led) + led_list.append(led1) + playload["LEDs"] = led_list + # boardsLed + print("post boardLed:%s" % redfish.post_boardLed(playload)) +''' \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rest/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rest/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rest/rest.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rest/rest.py new file mode 100644 index 000000000000..f83e41a50225 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rest/rest.py @@ -0,0 +1,1213 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import redis +import urllib +import urllib2 +import json +import ssl +import requests +import cookielib +import time +import os +import re +import collections +import pickle +import binascii +import base64 +import subprocess +import imp +import pexpect +from logutil.logutil import * +from requests.packages.urllib3.exceptions import InsecureRequestWarning +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + +headers = {'Content-type': 'application/json'} +context = ssl._create_unverified_context() +__DEBUG__ = "N" +LOGIN_TRY_TIME = 3 +RESTRETURNKEY = "status" +RESTRETURNSUCCESSKEY = "OK" +SYSLOG_IDENTIFIER = "rest" + +def d_print(debug_info): + if(__DEBUG__ == "Y"): + print(debug_info) + + +class BMCMessage(): + _session = None + _diagToBmcCmdPrefix = "/usr/local/bin/rj_rawcmd_cli diag cmd " + _sessionFile = "bmcsession" + BMC_LOGIN_PATH = "/login" + BMC_URLPRE_PATH = "http://240.1.1.1:8080" + FANS_PRE_STRING = "/xyz/openbmc_project/inventory/system/chassis/motherboard/fan" + FANS_STATE_STRING = "/xyz/openbmc_project/state/fan0" + FANS_PATH = "/xyz/openbmc_project/sensors/fan_tach/enumerate" + FAN_FRU_PATH = "/xyz/openbmc_project/inventory/system/chassis/motherboard/enumerate" + SENSORS_PATH = "/xyz/openbmc_project/sensors/enumerate" + BMC_STATE_PATH = '/xyz/openbmc_project/state/bmc0' + + def getBmcUrl(self, name): + return self.BMC_URLPRE_PATH + name + + def getBmcValue(self, path): + return self.bmcget(self.getBmcUrl(path)); + + @property + def getSessionConfigfile(self): + filename = self._sessionFile + direct = os.path.dirname(os.path.realpath(__file__)) + filename = os.path.join(direct, filename) + return filename + + def saveSessionToFile(self): + configfile = self.getSessionConfigfile + with open(configfile, 'wb') as f: + pickle.dump(self.session.cookies, f) + + @property + def getsessionvalue(self): + configfile = self.getSessionConfigfile; + if os.path.exists(configfile) == False: + d_print("file no exists") + return False + self.session = requests.session() + self.session.keep_alive = False + with open(configfile, 'rb') as f: + self.session.cookies.update(pickle.load(f)) + return True + + def __init__(self): + d_print("bmcmessage init...") + self.session = requests.session() + self.session.keep_alive = False + #if self.getsessionvalue == False: + # d_print("init value...") + # self.login_times() + #if self.getsessionvalue == False: + # raise Exception("connect failed") + pass + + def __del__(self): + pass + + def bmcget(self, url): + d_print(url) + for i in range(3): + try: + response = self.session.get(url, verify=False, timeout=60) + if self.isReturnSuccess(response.text): + return json.loads(response.text)['data'] + bmc_restful_logger("bmcget:%s,status:%s,text:%s" %(url,response.status_code,response.text)) + except Exception as e: + bmc_restful_logger("bmcget:%s,Exception:%s" %(url,str(e))) + return None + + def bmcput(self, url, data): + d_print(url) + d_print(data) + request = {} + request["data"] = data + data_json = json.dumps(request) + d_print(data_json) + try: + response = self.session.put( + url, data=data_json, headers=headers, verify=False, timeout=60) + if self.isReturnSuccess(response.text): + return 1 + else: + bmc_restful_logger("data:%s,bmcput:%s,status:%s,text:%s" %(data,url,response.status_code,response.text)) + return 0 + except Exception as e: + bmc_restful_logger("data:%s,bmcput:%s,Exception:%s" %(data,url,str(e))) + return 0 + + def bmcpost(self, url, data,maytimeout=120): + d_print(url) + d_print(data) + request = {} + request = data + data_json = json.dumps(request) + d_print(data_json) + + for i in range(3): + try: + response = self.session.post( + url, data=data_json, headers=headers, verify=False, timeout=maytimeout) + if self.isReturnSuccess(response.text): + if json.loads(response.text)['data'] != None and json.loads(response.text)['data']['Outputs'] != None: + return json.loads(response.text)['data']['Outputs'] + else: + return "Success" + bmc_restful_logger("data:%s,bmcpost:%s,status:%s,text:%s" %(data,url,response.status_code,response.text)) + except Exception as e: + bmc_restful_logger("bmcpost:%s,Exception:%s" %(url,str(e))) + return None + + def postSffTemp(self, data): + url = "/xyz/openbmc_project/sensors/temperature/ODM_SSF_Temp/attr/Scale" + return self.bmcput(self.getBmcUrl(url), data) + + def isNeedLogin(self, val): + if RESTRETURNKEY in json.loads(val) and json.loads(val)[RESTRETURNKEY] == "error" and json.loads(val)['data']['description'] == 'Login required': + return True + else: + return False + + def isReturnSuccess(self, val): + if RESTRETURNKEY in json.loads(val) and json.loads(val)[RESTRETURNKEY] == RESTRETURNSUCCESSKEY: + return True + else: + return False + + def getfansList(self): + fan_ret = self.bmcget(self.getBmcUrl(self.FANS_PATH)) + return fan_ret + + def getfanFruList(self): + fanfru_ret = self.bmcget(self.getBmcUrl(self.FAN_FRU_PATH)) + return fanfru_ret + + def getFansMsg(self): + curFanList = self.getfansList() + fanfru_ret = self.getfanFruList() + if fanfru_ret == None: + return None + curfanFruLists = [it for it in fanfru_ret if "fan" in it] + d_print(curFanList) + fan_state = self.bmcget(self.getBmcUrl(self.FANS_STATE_STRING)) + if fan_state == None: + return None + if curFanList == None: + return None + curFanLists = [elem for elem in curFanList if elem.split("/")[-1].startswith("FAN")] + curFanLists = sorted(curFanLists) + result = dict() + result["Number"] = len(curFanLists) + d_print("fan num:%d" % len(curFanLists)) + for item in curFanLists: + rest1 = item.split("/") + ret = rest1[-1]#.replace("ODM_", "").upper() + d_print("ret: %s fan index:%s"%(ret, str(int(ret[3:4]) - 1))) + fansreadNamevalue = self.FANS_PRE_STRING + str(int(ret[3:4]) - 1) + dict1 = curFanList.get(item, None) + dict2 = fanfru_ret.get(fansreadNamevalue, None) + if dict1 == None: + dict_t = dict2 + elif dict2 == None: + dict_t = dict1 + else: + dict_t = dict(dict1, **dict2) + + d_print("dict:") + d_print(dict_t) + + fanPresentKey = "Fan%dPresent" % (int(ret[3:4])) + fanStateKey = "Fan%dState" % (int(ret[3:4])) + fanAirFlow = "Fan%dAirFlow"% (int(ret[3:4])) + fanMotor1= "Fan%dMotor1"% (int(ret[3:4])) + fanMotor2= "Fan%dMotor2"% (int(ret[3:4])) + + ret_ttt = False + if fan_state != None and fan_state.get(fanPresentKey, None) == "xyz.openbmc_project.State.ODM_Fan.CurrentState.Ready": + dict_t["Present"] = True + else: + dict_t["Present"] = False + + if fan_state != None and fan_state.get(fanStateKey, None) == "xyz.openbmc_project.State.ODM_Fan.CurrentState.Ready": + dict_t["Running"] = True + else: + dict_t["Running"] = False + + if fan_state.get(fanMotor1, None) == "xyz.openbmc_project.State.ODM_Fan.CurrentState.Ready" and fan_state.get(fanMotor2, None) == "xyz.openbmc_project.State.ODM_Fan.CurrentState.Ready": + ret_ttt = True + + airflowtmp = fan_state.get(fanAirFlow, "").split('.')[-1] + if airflowtmp == "NA": + dict_t["AirFlow"] = None + else: + dict_t["AirFlow"]= airflowtmp + dict_t["Status"]= ret_ttt + + dict_t["PN"] = dict_t.get("Model", None) + dict_t["SN"] = dict_t.get("SerialNumber", None) + dict_t["Speed"] = dict_t.get("Value", None) + dict_t["LowThd"] = dict_t.get("CriticalLow", None) + dict_t["HighThd"] = dict_t.get("CriticalHigh", None) + result[ret] = dict_t + return collections.OrderedDict(sorted(result.items(), key=lambda t: t[0])) + + def login_times(self): + n = 0 + while True: + if n > LOGIN_TRY_TIME: + return False + if self.login() == True: + return True + n += 1 + return False + + def login(self): + try: + url = self.getBmcUrl(self.BMC_LOGIN_PATH) + self.session = requests.session() + data_json = json.dumps(LOGIN_REQUEST_DATA) + response = self.session.post( + url, data=data_json, headers=headers, verify=False, timeout=60) + if self.isReturnSuccess(response.text): + self.saveSessionToFile() + return True + else: + return False + except Exception: + return False + + def getPsuNum(self): + return len(self.getPsuValues()) + + def getPsuMsg(self): + PSU_FAN_PATH = "/xyz/openbmc_project/sensors/fan_tach/enumerate" + PSU_FRU_PATH = "/xyz/openbmc_project/inventory/system/chassis/motherboard/enumerate" + PSU_PRESENCE_STR = "/xyz/openbmc_project/state/psu0" + STATE_STR = "xyz.openbmc_project.State.ODM_PSU.CurrentState.Ready" + STATE_TRUE = 'xyz.openbmc_project.State.ODM_PSU.CurrentState.True' + PSU_PRE_STR ="/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply" + + psuNums = self.bmcget(self.getBmcUrl(PSU_FAN_PATH)) + if psuNums == None: + return None + psuNumStrs = [psu_item for psu_item in psuNums if "PSU" in psu_item] + d_print(psuNumStrs) + ret = self.bmcget(self.getBmcUrl(PSU_FRU_PATH)) + value = self.bmcget(self.getBmcUrl(PSU_PRESENCE_STR)) + if ret == None: + return None + psuRestult = dict() + psuRestult["Number"] = len(psuNumStrs) + PSUNAME = "PSU" + for psu_child in range(len(psuNumStrs)): + index = psu_child + 1 + psuNames = PSU_PRE_STR + str(index - 1) + psuDict = dict() + psuPresentKey = "PSU%dPresent" % (index ) + psuStateKey = "PSU%dState" % (index ) + psuInputStatus ="PSU%dInputState" % (index ) + psuInputType ="PSU%dInputType"% (index ) + psuOutputStatus= "PSU%dOutputState"% (index ) + AirFlow = "PSU%dAirFlow"% (index ) + psuName = PSUNAME + str(index ) + itemdict = ret.get(psuNames, {}) + psuDict = itemdict + if value.get(psuPresentKey, None) == STATE_STR: + psuDict["Present"] = True + else: + psuDict["Present"] = False + if value.get(psuStateKey, None) == STATE_STR: + psuDict["PowerStatus"] = True + else: + psuDict["PowerStatus"] = False + if value.get(psuInputStatus, None) == STATE_TRUE: + psuDict["InputStatus"] = True + else: + psuDict["InputStatus"] = False + if value.get(psuOutputStatus, None) == STATE_TRUE: + psuDict["OutputStatus"] = True + else: + psuDict["OutputStatus"] = False + psuinputtypetmp = value.get(psuInputType, "").split('.')[-1] + if psuinputtypetmp == 'NA': + psuDict["InputType"] = None + else: + psuDict["InputType"] = psuinputtypetmp + ariflowtmp = value.get(AirFlow, "").split('.')[-1] + if ariflowtmp == 'NA': + psuDict["AirFlow"] = None + else: + psuDict["AirFlow"] = ariflowtmp + psuDict["PN"] = itemdict.get("Model", None) + psuDict["SN"] = itemdict.get("SerialNumber", None) + psuRestult[psuName] = psuDict + return collections.OrderedDict(sorted(psuRestult.items(), key=lambda t: t[0])) + + def getSensorsNum(self): + return len(self.getSensorsNames()) + + def getSensorsName(self, index): + result = self.getSensorsNames()[index] + rest1 = result.split(":") + return "".join(rest1[-1:]) + + def getSensorsFullName(self, index): + return self.getSensorsNames()[index] + + def getSensorsInputNumsByIndex(self, index): + name = self.getSensorsFullName(index) + return self.getSensorsinputNumByName(name) + + def getsensorLists(self): + ret_t = self.bmcget(self.getBmcUrl(self.SENSORS_PATH)) + bmcstate = self.bmcget(self.getBmcUrl(self.BMC_STATE_PATH)) + #lc1 = ["Dvdd0v8_V1","Dvdd0v8_C1","Avdd0v8_V1","Avdd0v8_C1","Cq1v2_V1","Cq1v2_C1","Cq1v8_V1","Cq1v8_C1","ODM_Cq3v3_V1","ODM_Cq3v3_C1","ODM_Cq5v0_V1","ODM_Cq5v0_C1","ODM_Cq3v3Qs_V11","ODM_Cq3v3Qs_C11","ODM_Cq3v3Qs_V21","ODM_Cq3v3Qs_C21","ODM_LC1_Temp"] + #lc2 = ["Dvdd0v8_V2","Dvdd0v8_C2","Avdd0v8_V2","Avdd0v8_C2","Cq1v2_V2","Cq1v2_C2","Cq1v8_V2","Cq1v8_C2","ODM_Cq3v3_V2","ODM_Cq3v3_C2","ODM_Cq5v0_V2","ODM_Cq5v0_C2","ODM_Cq3v3Qs_V12","ODM_Cq3v3Qs_C12","ODM_Cq3v3Qs_V22","ODM_Cq3v3Qs_C22","ODM_LC2_Temp"] + #lc3 = ["Dvdd0v8_V3","Dvdd0v8_C3","Avdd0v8_V3","Avdd0v8_C3","Cq1v2_V3","Cq1v2_C3","Cq1v8_V3","Cq1v8_C3","ODM_Cq3v3_V3","ODM_Cq3v3_C3","ODM_Cq5v0_V3","ODM_Cq5v0_C3","ODM_Cq3v3Qs_V13","ODM_Cq3v3Qs_C13","ODM_Cq3v3Qs_V23","ODM_Cq3v3Qs_C23","ODM_LC3_Temp"] + #lc4 = ["Dvdd0v8_V4","Dvdd0v8_C4","Avdd0v8_V4","Avdd0v8_C4","Cq1v2_V4","Cq1v2_C4","Cq1v8_V4","Cq1v8_C4","ODM_Cq3v3_V4","ODM_Cq3v3_C4","ODM_Cq5v0_V4","ODM_Cq5v0_C4","ODM_Cq3v3Qs_V14","ODM_Cq3v3Qs_C14","ODM_Cq3v3Qs_V24","ODM_Cq3v3Qs_C24","ODM_LC4_Temp"] + + if ret_t == None: + return None + result = dict() + result['Sys'] = {"Sys_AirFlow":bmcstate.get('AirFlow',"").split('.')[-1]} + for item in ret_t: + childitem = dict() + rest1 = item.split("/") + ret = rest1[-1] + psus = ret.split("_")[0] + value1 = ret + if ret == "ODM_SSF_Temp": + continue + elif "_TEMP" in ret: + psus = "temperature".upper() + value1 = ret.upper() + ret_tmp = ret_t.get(item, None) + if ret_tmp == None: + continue + typename = self.getInputTypes(value1) + ret_tmp["Type"] = typename + ret_tmp["CriticalLow"] = self.getFinalValueByType(typename, ret_tmp.get("CriticalLow", 0)) + ret_tmp["LowThd"] = ret_tmp.get("CriticalLow", 0) + ret_tmp["CriticalHigh"] = self.getFinalValueByType(typename, ret_tmp.get("CriticalHigh", 0)) + ret_tmp["HighThd"] = ret_tmp.get("CriticalHigh", 0) + ret_tmp["Value"] = self.getFinalValueByType(typename, ret_tmp.get("Value", 0)) + if result.__contains__(psus): + result.get(psus)[value1] = ret_tmp + else: + childitem[value1] = ret_tmp + result[psus] = childitem + return collections.OrderedDict(sorted(result.items(), key=lambda t: t[0])) + + def getInputTypes(self, name): + if "TEMP" in name: + return "temperature" + elif "SYS_" in name and name.endswith("_V"): + return "voltage" + elif "SYS_" in name and name.endswith("_C"): + return "amp" + elif name.endswith("_V") or name.endswith("_V1") or name.endswith("_V2") or name.endswith("_V3") or name.endswith("_V4"): + return "voltage" + elif name.endswith("_C") or name.endswith("_C1") or name.endswith("_C2") or name.endswith("_C3") or name.endswith("_C4"): + return "amp" + elif name.endswith("_V11") or name.endswith("_V21") or name.endswith("_V12") or name.endswith("_V22") or name.endswith("_V13") or name.endswith("_V23") or name.endswith("_V14") or name.endswith("_V24") : + return "voltage" + elif name.endswith("_C11") or name.endswith("_C21") or name.endswith("_C12") or name.endswith("_C22") or name.endswith("_C13") or name.endswith("_C23") or name.endswith("_C14") or name.endswith("_C24") : + return "amp" + elif name.endswith("_C") : + return "amp" + elif name.endswith("_P") : + return "power" + elif "FAN" in name: + return "RPM" + elif "_CURR" in name: + return "amp" + elif "_VOL" in name: + return "voltage" + elif "POWER" in name: + return "power" + elif name == "SWITCH_VANALOG" or name == "SWITCH_VCORE": + return "voltage" + elif name == "SWITCH_CCORE" or name == "SWITCH_CANALOG": + return "amp" + else: + return "voltage" + return None + + def getSensorInputType(self, name): + if "TEMP" in name: + return "temperature" + elif "SYS_" in name and name.endswith("_V"): + return "voltage" + elif "SYS_" in name and name.endswith("_C"): + return "amp" + elif "FAN" in name: + return "RPM" + elif "_CURR" in name: + return "amp" + elif "_VOL" in name: + return "voltage" + elif "POWER" in name: + return "power" + else: + return "voltage" + return None + + def getFinalValueByType(self, inputtype, value): + if inputtype == "voltage" or inputtype == "temperature" or inputtype == "power" or inputtype == "wattage" or inputtype == "amp": + return float(value) / 1000 + else: + return value + + def getDealValueByType(self, inputtype, value): + inputtype = self.getSensorInputType(inputtype) + if inputtype == "voltage" or inputtype == "temperature" or inputtype == "power" or inputtype == "wattage" or inputtype == "amp": + return float(value) / 1000 + else: + return value + + @property + def session(self): + return self._session + + def send_diag_cmd_t_bmc(self, str): + PSU_PRESENCE_STR = "/api/hw/rawcmd" + fun_name_full = self._diagToBmcCmdPrefix + str + data_post = {"Command": fun_name_full} + realurl = self.getBmcUrl(PSU_PRESENCE_STR) + return self.bmcpost(realurl, data_post) + + def get_macrov_value(self): + data_post = {"Command": "/usr/local/bin/rj_rawcmd_cli get mac_rov"} + PSU_PRESENCE_STR = "/api/hw/rawcmd" + realurl = self.getBmcUrl(PSU_PRESENCE_STR) + return self.bmcpost(realurl, data_post) + + def get_current_bmc_version(self): + dataval = self.getBmcValue("/api/bmc/info") + if dataval == None: + return "" + else: + return "\"BmcVersion\": \""+dataval["Version"]+"\"" + + def get_bmc_version_flash(self): + dataval = self.getBmcValue("/api/bmc/info") + if dataval == None: + return "N/A","N/A" + else: + return str(dataval["Version"]),str(dataval["Flash"]) + +class MonitorMessage(): + + def __init__(self): + print ("test") + + def test(self): + print ("Monitor") + + +class x86Message(MonitorMessage): + MAILBOX_DIR = "/sys/bus/i2c/devices/" + PLATFORM_ROOT_PATH = '/usr/share/sonic/device' + module_product = None + + def __init__(self): + platform = Osutil.get_platform_info(Osutil.get_machine_info()) + platform_path = "/".join([self.PLATFORM_ROOT_PATH, platform]) + try: + module_file_config = "/".join([platform_path, "plugins", "config.py"]) + self.module_product = imp.load_source("config", module_file_config) + except IOError, e: + log_error("Failed to load platform module '%s': %s" % ("config", str(e)), True) + d_print('x86 init...') + + def test(self): + print ("x86Message") + + def getFanNum(self): + return len(self.getFanNames()) + + def getFanName(self, index): + x = self.getFanNames() + name = x[index] + return name + + # Get a mailbox register + def get_pmc_register(self, reg_name): + retval = 'ERR' + mb_reg_file = self.MAILBOX_DIR + reg_name + + if (not os.path.isfile(mb_reg_file)): + # print mb_reg_file, 'not found !' + return "%s %s notfound" % (retval , mb_reg_file) + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + pass + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + def getValue(self, location, bit , type): + value_t = self.get_pmc_register(location) + if value_t.startswith("ERR"): + return value_t + if (type == 1): + return float(value_t) / 1000 + elif (type == 2): + return float(value_t) / 100 + elif (type == 3): + psu_status = int(value_t, 16) + return (psu_status & (1 << bit)) >> bit + else: + return value_t; + + def getFanFru(self, name): + print (name) + return self.getFanStatus(name) + # ret = RedisUtil.grtFanFruValue(name) + # return self.bmcget(RedisUtil.getRedisPreValue(ret)) + + def tlve2set(self,bin_data): + RAGILE_CARDID = self.module_product.RAGILE_CARDID + machine_vars=Osutil.get_machine_info() + machine_vars_onie_version=machine_vars.get("onie_version") + _value = {} + _value[boardTLV._TLV_CODE_VENDOR_EXT] = self.getTLVcardidBin() + _value[boardTLV._TLV_CODE_PRODUCT_NAME] = self.module_product.RAGILE_PRODUCTNAME + _value[boardTLV._TLV_CODE_PART_NUMBER] = self.module_product.RAGILE_PART_NUMBER + _value[boardTLV._TLV_CODE_LABEL_REVISION] = self.module_product.RAGILE_LABEL_REVISION + _value[boardTLV._TLV_CODE_PLATFORM_NAME] = DeviceMessage().getplatform() + _value[boardTLV._TLV_CODE_ONIE_VERSION] = machine_vars_onie_version + _value[boardTLV._TLV_CODE_MAC_SIZE] = self.module_product.RAGILE_MAC_SIZE + _value[boardTLV._TLV_CODE_MANUF_NAME] = self.module_product.RAGILE_MANUF_NAME + _value[boardTLV._TLV_CODE_MANUF_COUNTRY] = self.module_product.RAGILE_MANUF_COUNTRY + _value[boardTLV._TLV_CODE_VENDOR_NAME] = self.module_product.RAGILE_VENDOR_NAME + _value[boardTLV._TLV_CODE_DIAG_VERSION] = self.module_product.RAGILE_DIAG_VERSION + _value[boardTLV._TLV_CODE_SERVICE_TAG] = self.module_product.RAGILE_SERVICE_TAG + _value[boardTLV._TLV_CODE_MANUF_DATE] =time.strftime('%m/%d/%Y %H:%M:%S', time.localtime()) # 自动添加setmac时 + _value[boardTLV._TLV_CODE_PRODUCT_NAME] = bin_data.get(boardTLV._TLV_CODE_PRODUCT_NAME) + _value[boardTLV._TLV_CODE_SERIAL_NUMBER] = bin_data.get(boardTLV._TLV_CODE_SERIAL_NUMBER) + _value[boardTLV._TLV_CODE_DEVICE_VERSION]= bin_data.get(boardTLV._TLV_CODE_DEVICE_VERSION) + _value[boardTLV._TLV_CODE_MAC_BASE] = bin_data.get(boardTLV._TLV_CODE_MAC_BASE) + rst, ret = boardTLV().generate_value(_value) + boardTLV().writeToEEprom(rst , self.module_product.E2_LOC) + + def getCPUeeprom(self): + e2loc = self.module_product.CPUEEPROMS + name = self.dumpValueByI2c(e2loc.get('bus'),e2loc.get('loc')) + return name + + def setCPUeeprom(self,bindata): + e2loc = self.module_product.CPUEEPROMS + Osutil.writeToE2(e2loc.get('bus'),e2loc.get('loc'), bindata) + + def dumpValueByI2c(self, bus, loc): + str = "" + for i in range(256): + ret,val = Osutil.rji2cget(bus, loc, i) + str += chr(Osutil.strtoint(val)) + return str + + def geteepromLocation(self,bus, devno): + location = "%d-00%02x/eeprom" % (bus,devno) + return location + + def getTlvLoc(self): + e2loc = self.module_product.E2_LOC + location = "%d-00%02x/eeprom" % (e2loc.get('bus'),e2loc.get('devno') ) + return location + + def getTLVe2(self): + name = self.get_pmc_register(self.getTlvLoc()) + if name == None: + return name + return boardTLV().decode_eeprom(name) + + def getcardid(self): + return self.module_product.RAGILE_CARDID + + def getproductname(self): + return self.module_product.RAGILE_PRODUCTNAME + + def getTLVproductname(self): + name = self.get_pmc_register(self.getTlvLoc()) + if name == None: + return name + return boardTLV().getcardName(name) + + def getTLVcardidBin(self): + return boardTLV().generate_e2_cardid(self.module_product.RAGILE_CARDID) + + def resetTLVe2(self): + cardidbin = self.getTLVcardidBin() + _value = {} + _value[boardTLV._TLV_CODE_VENDOR_EXT] = cardidbin + rst, ret = boardTLV().generate_value(_value) + print (boardTLV().writeToEEprom(rst, self.module_product.E2_LOC)) + + + def getPsuNum(self): + # TODO + pass + + def getPsuValues(self): + # TODO + pass + + def getPsuValue(self, index): + # TODO + pass + + def getSensorsNum(self): + # TODO + pass + + def getSensorsNames(self): + # TODO + pass + + def getSensorsName(self, index): + # TODO + pass + + def getSensorsFullName(self, index): + # TODO + pass + + def getSensorsinputNumByName(self, title): + # TODO + pass + + def getSensorsInputNumsByIndex(self, index): + # TODO + pass + + def getSensorsInputNameByIndex(self, sensorindex, inputindex): + # TODO + pass + + def getSensorsinputs(self, title): + # TODO + pass + + def getSensorsInputValue(self, index, index2): + # TODO + pass + + pass + +class boardTLV(): + _TLV_INFO_ID_STRING = "TlvInfo\x00" + _TLV_INFO_VERSION = 0x01 + _TLV_INFO_LENGTH = 0x00 + _TLV_INFO_LENGTH_VALUE = 0xba + _TLV_CODE_PRODUCT_NAME = 0x21 + _TLV_CODE_PART_NUMBER = 0x22 + _TLV_CODE_SERIAL_NUMBER = 0x23 + _TLV_CODE_MAC_BASE = 0x24 + _TLV_CODE_MANUF_DATE = 0x25 + _TLV_CODE_DEVICE_VERSION = 0x26 + _TLV_CODE_LABEL_REVISION = 0x27 + _TLV_CODE_PLATFORM_NAME = 0x28 + _TLV_CODE_ONIE_VERSION = 0x29 + _TLV_CODE_MAC_SIZE = 0x2A + _TLV_CODE_MANUF_NAME = 0x2B + _TLV_CODE_MANUF_COUNTRY = 0x2C + _TLV_CODE_VENDOR_NAME = 0x2D + _TLV_CODE_DIAG_VERSION = 0x2E + _TLV_CODE_SERVICE_TAG = 0x2F + _TLV_CODE_VENDOR_EXT = 0xFD + _TLV_CODE_CRC_32 = 0xFE + _TLV_DISPLAY_VENDOR_EXT = 1 + _TLV_CODE_RJ_CARID = 0x01 + _TLV_INFO_HDR_LEN = 11 + + def _crc32(self,v): + return '0x%08x' % (binascii.crc32(v) & 0xffffffff) + + def getTLV_BODY(self, type, productname): + x = [] + temp_t = "" + if type == self._TLV_CODE_MAC_BASE: + arr = productname.split(':') + for tt in arr: + temp_t += chr(int(tt, 16)) + elif type == self._TLV_CODE_DEVICE_VERSION: + temp_t = chr(productname) + elif type == self._TLV_CODE_MAC_SIZE: + temp_t = chr(productname >> 8) + chr(productname & 0x00ff) + else: + temp_t = productname + x.append(chr(type)) + x.append(chr(len(temp_t))) + for i in temp_t: + x.append(i) + return x + + def generate_value(self,_t): + ret = [] + for i in self._TLV_INFO_ID_STRING: + ret.append(i) + ret.append(chr(self._TLV_INFO_VERSION)) + ret.append(chr(self._TLV_INFO_LENGTH)) + ret.append(chr(self._TLV_INFO_LENGTH_VALUE)) + + total_len = 0 + for key in _t: + x = self.getTLV_BODY(key, _t[key]) + ret += x + total_len += len(x) + ret[10] = chr(total_len + 6) + + ret.append(chr(0xFE)) + ret.append(chr(0x04)) + s = self._crc32(''.join(ret)) + for t in range(0, 4): + ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16))) + totallen = len(ret) + if (totallen < 256): + for left_t in range(0, 256 - totallen): + ret.append(chr(0x00)) + return (ret, True) + + def generate_e2_cardid(self, cardid): + s = "%08x" % cardid + ret = "" + for t in range(0, 4): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + ret = chr(0x01) + chr(len(ret)) + ret + return ret + + def decode_eeprom(self, e): + total_len = (ord(e[9]) << 8) | ord(e[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_len + ret = [] + while (tlv_index + 2) < len(e) and tlv_index < tlv_end: + rt = self.decoder(None, e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])]) + ret.append(rt) + if ord(e[tlv_index]) == self._TLV_CODE_CRC_32: + break + tlv_index += ord(e[tlv_index + 1]) + 2 + for item in ret: + if item['code'] == self._TLV_CODE_VENDOR_EXT: + rt = self.decoder(None, item["value"] + [0: 0 + 2 + ord(item["value"][0 + 1])]) + ret.append(rt) + return ret + + def getcardid(self, eeprom): + ret = self.decode_eeprom(eeprom) + for item in ret: + if item['code'] == self._TLV_CODE_RJ_CARID: + return item.get('value',None) + return None + + def getcardName(self,eeprom): + ret = self.decode_eeprom(eeprom) + for item in ret: + if item['code'] == self._TLV_CODE_PRODUCT_NAME: + return item.get('value',None) + return None + + def decoder(self,s, t): + if ord(t[0]) == self._TLV_CODE_PRODUCT_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + elif ord(t[0]) == self._TLV_CODE_PART_NUMBER: + name = "Part Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_SERIAL_NUMBER: + name = "Serial Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_MAC_BASE: + name = "Base MAC Address" + value = ":".join([binascii.b2a_hex(T) for T in t[2:8]]).upper() + elif ord(t[0]) == self._TLV_CODE_MANUF_DATE: + name = "Manufacture Date" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_DEVICE_VERSION: + name = "Device Version" + value = str(ord(t[2])) + elif ord(t[0]) == self._TLV_CODE_LABEL_REVISION: + name = "Label Revision" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_PLATFORM_NAME: + name = "Platform Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_ONIE_VERSION: + name = "ONIE Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_MAC_SIZE: + name = "MAC Addresses" + value = str((ord(t[2]) << 8) | ord(t[3])) + elif ord(t[0]) == self._TLV_CODE_MANUF_NAME: + name = "Manufacturer" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_MANUF_COUNTRY: + name = "Manufacture Country" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_VENDOR_NAME: + name = "Vendor Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_DIAG_VERSION: + name = "Diag Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_SERVICE_TAG: + name = "Service Tag" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_VENDOR_EXT: + name = "Vendor Extension" + value = "" + if self._TLV_DISPLAY_VENDOR_EXT: + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == self._TLV_CODE_CRC_32 and len(t) == 6: + name = "CRC-32" + value = "0x%08X" % (((ord(t[2]) << 24) | ( + ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) + elif ord(t[0]) == self._TLV_CODE_RJ_CARID: + name = "rj_cardid" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + else: + name = "Unknown" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "0x%02X " % (ord(c),) + return {"name": name, "code": ord(t[0]), "value": value} + + def writeToEEprom(self,rst_arr , E2_LOC): + index = 0 + for item in rst_arr: + Osutil.rji2cset(E2_LOC["bus"], E2_LOC["devno"], index, ord(item)) + index += 1 + os.system("rmmod at24 ") + os.system("modprobe at24 ") + os.system("rm -f /var/cache/sonic/decode-syseeprom/syseeprom_cache") + +class Osutil(): + SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen' + HWSKU_KEY = "DEVICE_METADATA['localhost']['hwsku']" + PLATFORM_KEY = "DEVICE_METADATA['localhost']['platform']" + + @staticmethod + def writeToE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + Osutil.rji2cset(bus, loc, index, ord(item)) + index += 1 + @staticmethod + def strtoint(str): # The hexadecimal string is converted to int, "4040"/"0x4040"/"0X4040" = 16448 + value = 0 + rest_v = str.replace("0X", "").replace("0x", "") + for index in range(len(rest_v)): + value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4) + return value + # Compare strings regardless of size + @staticmethod + def astrcmp(str1,str2): + return str1.lower()==str2.lower() + @staticmethod + def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + if status: + log_error('Failed :%s msg:%s status:%s'%(cmd,output,status)) + return status, output + @staticmethod + def log_os_system(cmd, show,log_file=SYSLOG_IDENTIFIER): + d_print (' Run :'+ cmd) + status, output = subprocess.getstatusoutput(cmd) + d_print (" with result :" + str(status)) + d_print (" output :" + output) + if status: + log_error('Failed :%s msg:%s status:%s'%(cmd,output,status),log_file) + if show: + print ('Failed :'+ cmd) + return status, output + + @staticmethod + def rji2cset(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = Osutil.rj_os_system(command_line) + if ret == 0: + return True, ret_t + log_error('command_line:%s ret :%d ret_t:%s'%(command_line,ret,ret_t)) + return False, ret_t + + @staticmethod + def rji2cget(bus, devno, address, word=None): + if word == None: + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + else: + command_line = "i2cget -f -y %d 0x%02x 0x%02x %s" % (bus, devno, address, word) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = Osutil.rj_os_system(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + log_error('command_line:%s ret :%d ret_t:%s'%(command_line,ret,ret_t)) + return False, ret_t + @staticmethod + def isValidMac(mac): + if re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$", mac): + return True + return False + + @staticmethod + def seteth0mac(eth, mac): + rulefile = "/etc/udev/rules.d/70-persistent-net.rules" + if Osutil.isValidMac(mac) == False: + return False, "MAC非法" + + # Temporarily change the local ETH0 to the value after setMAC + ifconfigcmd = "ifconfig eth0 down" + log_debug(ifconfigcmd,SYSLOG_IDENTIFIER) + ret, status = Osutil.rj_os_system(ifconfigcmd) + if ret: + return False, "软件停用eth0出错" + ifconfigcmd = "ifconfig eth0 hw ether %s" % mac + log_debug(ifconfigcmd,SYSLOG_IDENTIFIER) + ret, status = Osutil.rj_os_system(ifconfigcmd) + if ret: + return False, "软件设置网卡MAC出错" + ifconfigcmd = "ifconfig eth0 up" + log_debug(ifconfigcmd,SYSLOG_IDENTIFIER) + ret, status = Osutil.rj_os_system(ifconfigcmd) + if ret: + return False, "软件启用eth0出错" + if os.path.exists(rulefile): + os.remove(rulefile) + print ("MGMT MAC【%s】" % mac) + return True, "success" + + @staticmethod + def get_machine_info(): + if not os.path.isfile('/host/machine.conf'): + return None + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + + @staticmethod + def get_platform_info(machine_info): + if machine_info != None: + if machine_info.__contains__('onie_platform'): + return machine_info['onie_platform'] + elif machine_info.__contains__('aboot_platform'): + return machine_info['aboot_platform'] + return None + + @staticmethod + def get_platform_and_hwsku(): + try: + proc = subprocess.Popen([Osutil.SONIC_CFGGEN_PATH, '-H', '-v', Osutil.PLATFORM_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + platform = stdout.rstrip('\n') + + proc = subprocess.Popen([Osutil.SONIC_CFGGEN_PATH, '-d', '-v', Osutil.HWSKU_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + hwsku = stdout.rstrip('\n') + except OSError, e: + raise OSError("Cannot detect platform") + + return (platform, hwsku) + +class DeviceMessage(): + _message = None + + def __init__(self, GLObalSelectBmc=True): + if GLObalSelectBmc: + # d_print("before BMCMessage init") + self._message = BMCMessage() + else: + # d_print("before x86 init") + self._message = x86Message() + + @property + def message(self): + return self._message + + def getFRUList(self): + str = "bmc_get_e2_show_list" + ret_info = BMCMessage().send_diag_cmd_t_bmc(str) + return ret_info[0] + + def getSETFRUList(self): + str1 = "bmc_get_e2_set_list" + ret_info = BMCMessage().send_diag_cmd_t_bmc(str1) + return ret_info[0] + + def getFRUeeprom(self, e2type, index): + strtmp = "bmc_get_e2_bin -json \"%s\"" + param = {} + param["e2type"] = e2type + param["index"] = index + paramtmp = strtmp % str(param) + ret_info = BMCMessage().send_diag_cmd_t_bmc(paramtmp) + ret_dict = eval(ret_info[0]) + if ret_dict.get("status") == "ok": + return ret_dict.get('ret_info') + else: + return None + + def setFRUeeprom(self, e2type, index, bindata): + strtmp = "bmc_write_e2_bin -json \"%s\"" + param1 = [] + param = {} + param["e2type"] = e2type + param["index"] = index + ret_t = base64.b64encode(bindata) + param["bin"] = ret_t + param1.append(param) + paramtmp = strtmp % str(param1) + ret_info = BMCMessage().send_diag_cmd_t_bmc(paramtmp) + ret_dict = eval(ret_info[0]) + if ret_dict.get("status") == "ok": + return True + else: + print (ret_dict.get("ret_info")) + return False + + def getplatform(self): + '''Obtain the sonic system platform information''' + (platform, hwsku) = Osutil.get_platform_and_hwsku() + return platform + + def settlve2(self, bin_data): + '''set TLV E2''' + return x86Message().tlve2set(bin_data) + + def getTLVe2(self): + '''get TLV E2''' + return x86Message().getTLVe2(); + + def getTLVe2Dict(self): + '''get TLV E2 dict''' + ret = self.getTLVe2() + ret_t = {} + for item in ret: + ret_t[item['code']] = item['value'] + return ret_t + + def resetTLVE2(self): + return x86Message().resetTLVe2(); + + def getfannum(self): + return self.message.getFanNum() + + def getcardid(self): + '''set TLV board crad ID''' + return x86Message().getcardid(); + + def getproductname(self, readtype): + '''Read the product name 0 is read from configs,1 is read from tlv''' + if readtype == 0: + return x86Message().getproductname() + elif readtype == 1: + return x86Message().getTLVproductname() + else: + return None + + def getCPUeeprom(self): + return x86Message().getCPUeeprom(); + + def setCPUEEPROM(self,bindata): + return x86Message().setCPUeeprom(bindata) + + def getFanNames(self): + return self.message.getFanNames() + + def getFanName(self, index): + return self.message.getFanName(index) + + def getFanStatus(self, name): + return self.message.getFanStatus(name) + + def getFanFru(self, name): + return self.message.getFanFru(name) + + def getFanAll(self): + return self.message.getFansMsg() + + def getPsuNum(self): + return self.message.getPsuNum() + + def getPsuValue(self, index): + return self.message.getPsuValue(index) + + def getPsuPresence(self, index): + return self.message.getPsuPresence(index) + + def getPsuStatus(self, index): + return self.message.getPsuStatus(index) + + def getPsuAll(self): + return self.message.getPsuMsg(); + + def getfanList(self): + return self.message.getfansList() + + def getSensorsNum(self): + return self.message.getSensorsNum() + + def getSensorsName(self, index): + return self.message.getSensorsName(index) + + def getSensorsinputNumByName(self, title): + return self.message.getSensorsinputNumByName(title) + + def getSensorsInputNumsByIndex(self, index): + return self.message.getSensorsInputNumsByIndex(index) + + def getSensorsInputNameByIndex(self, sensorindex, inputindex): + return self.message.getSensorsInputNameByIndex(sensorindex, inputindex) + + def getSensorsInputValue(self, index, index2): + return self.message.getSensorsInputValue(index, index2) + + def getsensorList(self): + return self.message.getsensorList() + + def getsensorAll(self): + return self.message.getsensorLists() + + def getSensorInputType(self, name): + return self.message.getSensorInputType(name) + + def getRealUnitByType(self, name): + return self.message.getRealUnitByType(name) + + def getDealValueByType(self, name, value): + return self.message.getDealValueByType(name, value) + + def util_setmac(self,eth, mac): + return Osutil.seteth0mac(eth, mac) + + def getDmiSysByType(self, type_t): + ret, log = Osutil.rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t %s" % type_t + ret1, log1 = Osutil.rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "命令执行出错[%s]" % cmd + its = log1.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + return True, ret + + pass diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rjutil/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rjutil/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rjutil/ragileutil.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rjutil/ragileutil.py new file mode 100644 index 000000000000..9a8227d0f037 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/rjutil/ragileutil.py @@ -0,0 +1,299 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +import sys +import os +import re +import syslog +import logging +import time +import binascii +import termios +import threading +import click +import json +import mmap +configfile_pre = "/usr/local/bin/" +import sys +sys.path.append(configfile_pre) +from ragileconfig import * +from fruutil import fru +import subprocess +import pexpect + +SYSLOG_IDENTIFIER = "UTILTOOL" + +def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + +def get_machine_info(): + if not os.path.isfile('/host/machine.conf'): + return None + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + +def get_platform_info(machine_info): + if machine_info != None: + if machine_info.__contains__('onie_platform'): + return machine_info['onie_platform'] + elif machine_info.__contains__('aboot_platform'): + return machine_info['aboot_platform'] + return None + +''' +def cpld_version_restful(url): + if url == "" or len(url) <=0: + print("invalid url") + return + bmc = BMCMessage() + value = bmc.getBmcValue(url) + json_dicts=json.dumps(value,indent=4) + return json_dicts +''' + +def lpc_cpld_rd(reg_addr): + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/lpc_cpld" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str = os.read(fd, 1) + return "%02x" % ord(str) + except ValueError: + return None + except Exception as e: + print (e) + return None + finally: + os.close(fd) + return None + +def my_log(txt): + if DEBUG == True: + print ("[RAGILE]:",) + print (txt) + return + +def log_os_system(cmd, show): + my_log (' Run :'+ cmd) + status, output = subprocess.getstatusoutput(cmd) + my_log (" with result :" + str(status)) + my_log (" output :" + output) + if status: + log_error('Failed :%s msg:%s'%(cmd,output)) + if show: + print ('Failed :'+ cmd) + return status, output + +def password_command(cmd, password, exec_timeout=30): + + newkey = 'continue connecting' + log_os_system("rm -rf ~/.ssh", 0) + msg = "" + try_times = 3 + try_times_conter = try_times + while try_times_conter: + child = pexpect.spawn(cmd) + if try_times != try_times_conter: + time.sleep(5) + try_times_conter -= 1 + try: + i = child.expect([pexpect.TIMEOUT, newkey, 'password: ',"refused",pexpect.EOF],timeout=30) + # If the login times out, print an error message and exit. + if i == 0: # Timeout + msg = '与BMC连接超时' + continue + # no public key + if i == 1: + child.sendline ('yes') + i = child.expect([pexpect.TIMEOUT, 'password: '],timeout=30) + if i == 0: # Timeout + msg = '与BMC连接超时' + continue + if i == 1:# Go below and enter the logic of the password + i = 2 + if i == 2: # Enter the password + child.sendline (password) + i = child.expect([pexpect.EOF, pexpect.TIMEOUT], exec_timeout) + if i == 0: + return True,child.before + if i == 1: + msg = str(child.before)+"\nBMC执行命令超时" + return False,msg + if i == 3: # BMC Connection refused + msg = '连接BMC失败' + continue + if i == 4: + msg = child.before + except Exception as e: + msg = str(child.before)+"\n连接BMC失败" + + return False,msg + +def password_command_realtime(ssh_header, ssh_cmd, password,key_words, exec_timeout=30): + + key_word_end = key_words.get("key_word_end") + key_word_pass = key_words.get("key_word_pass") + key_word_noshow = key_words.get("key_word_noshow") + # Prevents waiting caused by BMC restart + key_word_exit = key_words.get("key_word_exit") + + if None in [key_word_end,key_word_pass]: + print ("缺少参数") + return False + + newkey = 'continue connecting' + log_os_system("rm -rf ~/.ssh", 0) + msg = "" + try_times = 3 + key_word_pass_flag = False + try_times_conter = try_times + child = pexpect.spawn(ssh_header) + try: + i = child.expect([pexpect.TIMEOUT,newkey, 'password: ',"refused",pexpect.EOF],timeout=30) + # If the login times out, print an error message and exit. + if i == 0: # Timeout + msg = '与BMC连接超时' + # no public key + if i == 1: + child.sendline ('yes') + i = child.expect([pexpect.TIMEOUT, 'password: '],timeout=30) + if i == 0: # Timeout + msg = '与BMC连接超时' + if i == 1:# Go below and enter the logic of the password + i = 2 + + if i == 2: # Enter the password + child.sendline (password) + i = child.expect([pexpect.EOF, "\r",pexpect.TIMEOUT], exec_timeout) + if i == 0: + print (child.before) + return key_word_pass_flag + if i == 1: + child.sendline(ssh_cmd) + # amount received is similar to root@switch2 in order to avoid misjudgment about the end of execution + usr_symble_first = True + bmc_str_tmp="" + while True: + i = child.expect([pexpect.EOF,"\r","\n",key_word_end, pexpect.TIMEOUT], exec_timeout) + if i == 0: + return key_word_pass_flag + elif i in [1,2]: + if key_word_noshow == None or key_word_noshow not in child.before: + bmc_str, times = re.subn("\r|\n","",child.before) + if len(bmc_str) > 1: + print (bmc_str) + bmc_str_tmp=bmc_str_tmp + bmc_str + # print bmc_str_tmp + # if key_word_pass in child.before: + if re.search(key_word_pass,bmc_str_tmp) != None: + key_word_pass_flag = True + if key_word_exit != None and key_word_exit in child.before: + # Give the BMC time to execute the last command + time.sleep(3) + return key_word_pass_flag + elif i == 3 : + if usr_symble_first: + usr_symble_first = False + else: + return key_word_pass_flag + + if i == 3: # BMC Connection refused + msg = '连接BMC失败' + if i == 4: + msg = child.before + except Exception as e: + print (e) + msg = str(child.before)+"\n连接出错" + print (msg) + + return False + +from subprocess import Popen, PIPE, STDOUT + +def get_sys_execute2(cmd, key_word_pass): + # key_word_pass_flag1 = False + key_word_pass_flag = False + filename = "/tmp/diag_excute_out" + p = Popen(cmd + "|tee %s"%filename, shell = True) + p.wait() + with open(filename, 'r') as f: + str1 = f.read() + if key_word_pass in str1: + key_word_pass_flag = True + # if key_word_pass_flag1 and "100%" in str1: + # key_word_pass_flag = True + log_os_system("rm %s"%filename,0) + return key_word_pass_flag + + +BMC_PATH = "PATH=/usr/sbin/:/bin/:/usr/bin/:/sbin" +RETURN_KEY1 = "code" +RETURN_KEY2 = "msg" +DEBUG = False + +def rji2cget(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + +def strtoint(str): # Hexadecimal string to int,"4040"/"0x4040"/"0X4040" = 16448 + value = 0 + rest_v = str.replace("0X", "").replace("0x", "") + for index in range(len(rest_v)): + value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4) + return value + +def pci_read(pcibus, slot, fn , bar, offset): + if offset % 4 != 0: + return None + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + file = open(filename, "r+") + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + data.close() + return val + +########################################### +# Run the DMI command to obtain the BIOS information +########################################### +def getDmiSysByType(type_t): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t %s" % type_t + # Get the total first + ret1, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "Command error[%s]" % cmd + its = log1.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + return True, ret diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/sonic_fwmgr/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/sonic_fwmgr/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/sonic_fwmgr/fwgmr_base.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/sonic_fwmgr/fwgmr_base.py new file mode 100644 index 000000000000..50a4ca7bc675 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/lib/sonic_fwmgr/fwgmr_base.py @@ -0,0 +1,141 @@ +# fwgmr_base.py +# +# Base class for creating platform-specific firmware management interfaces for SONiC +# +try: + import abc +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +class FwMgrUtilBase(object): + + """Base class for Platform-specific FwMgrUtil class""" + __metaclass__ = abc.ABCMeta + + def __init__(self): + """TODO: to be defined1. """ + pass + + @abc.abstractmethod + def get_bmc_version(self): + """Get BMC version from SONiC + :returns: version string + """ + return + + @abc.abstractmethod + def get_cpld_version(self): + """Get CPLD version from SONiC + :returns: dict like {'CPLD_1': version_string, 'CPLD_2': version_string} + """ + return + + @abc.abstractmethod + def get_onie_version(self): + """Get ONiE version from SONiC + :returns: version string + """ + return + + @abc.abstractmethod + def get_uboot_version(self): + """Get UBOOT version from SONiC + :returns: version string + """ + return + + # @fw_type MANDATORY, firmware type, should be one of the strings: 'cpld', 'fpga', 'bios', 'bmc' + # @fw_path MANDATORY, target firmware file + # @fw_extra OPTIONAL, extra information string, + # for fw_type 'cpld' and 'fpga': it can be used to indicate specific cpld, such as 'cpld1', 'cpld2', ... + # or 'cpld_fan_come_board', etc. For fw_type 'bios' and 'bmc', value should be one of 'master' + # or 'slave' or 'both'. For BMC, 'pingpong' stands for alternative upgrade policy. + @abc.abstractmethod + def firmware_upgrade(self, fw_type, fw_path, fw_extra): + return + + # Get last firmware upgrade information, inlcudes: + # 1) FwType: cpld/fpga/bios/bmc(passed by method 'firmware_upgrade'), string + # 2) FwPath: path and file name of firmware(passed by method 'firmware_upgrade'), string + # 3) FwExtra: designated string, econdings of this string is determined by vendor(passed by method 'firmware_upgrade') + # 4) Result: indicates whether the upgrade action is performed and success/failure status if performed. Values should be one of: "DONE"/"FAILED"/"NOT_PERFORMED". + # dict object: + # { + # "FwType": "cpld", + # "FwExtra": "specific_encoded_string" + # "Result": "DONE"/"FAILED"/"NOT_PERFORMED" + # } + @abc.abstractmethod + def get_last_upgrade_result(self): + return + + # Program FPGA and/or CPLD firmware only, but do not refresh them + # + # @param fw_type value can be: FPGA, CPLD + # @param fw_path a string of firmware file path, seperated by ':' + # @param fw_extra a string of firmware subtype, i.e CPU_CPLD, BOARD_CPLD, + # FAN_CPLD, LC_CPLD, etc. Subtypes are seperated by ':', + # the sequence should match the file nanmes in param @fw_path + # @return True when all required firmware is program succefully, + # False otherwise. + # + # Example: + # self.firmware_program("CPLD", "/cpu_cpld.vme:/lc_cpld", \ + # "CPU_CPLD:LC_CPLD") + # or + # self.firmware_program("FPGA", "/fpga.bin", "FPGA") + @abc.abstractmethod + def firmware_program(self, fw_type, fw_path, fw_extra=None): + return + + # Refresh firmware and take extra action when necessary. + # @param fpga_list a list of FPGA names + # @param cpld_list a list of CPLD names + # @return True if refresh succefully + # + # @Note extra action: + # 1) response OK to restful call + # 2) shutdown eth0.4088(keep eth0 working) + # 3) shutdown SFP power + # 4) power off all(CPU, switch, gearbox) + # 5) if power off fpga is supported: + # power off fpga + # else: + # refresh fpga + # 6) refresh linecard cpld, fan cpld + # 7) refresh cpu cpld, baseboard cpld + # 8) power on all + # 9) bring up eth0.4088 + # + # Example: + # self.firmware_refresh(["FPGA"], ["CPU_CPLD", "LC_CPLD"], "/tmp/fw/refresh.vme") + # or + # self.firmware_refresh(["FPGA"], None, None) + # or + # self.firmware_refresh(None, ["FAN_CPLD", "LC1_CPLD", "BOARD_CPLD"], "/tmp/fw/refresh.vme") + @abc.abstractmethod + def firmware_refresh(self, fpga_list, cpld_list, fw_extra=None): + return + + # Get booting flash of running BMC. + # @return a string, "master" or "slave" + @abc.abstractmethod + def get_running_bmc(self): + return + + # Set booting flash of BMC + # @param flash should be "master" or "slave" + @abc.abstractmethod + def set_bmc_boot_flash(self, flash): + return + + # Reboot BMC + @abc.abstractmethod + def reboot_bmc(self): + return + + # Get booting uboot image of current running host OS + # @return a string, "master" or "slave" + @abc.abstractmethod + def get_current_uboot(self): + return diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/ctccmd b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/ctccmd new file mode 100755 index 000000000000..2c4410a16d66 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/ctccmd @@ -0,0 +1,3 @@ +#! /bin/bash + +docker exec -i syncd ctc_shell -e "$@" \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.py new file mode 100644 index 000000000000..d9953bfaaa66 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.py @@ -0,0 +1,50 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +import sys +import os +import re +import subprocess +try: + from sonic_platform import get_machine_info + from sonic_platform import get_platform_info +except: + try: + from sonic_device_util import get_machine_info + from sonic_device_util import get_platform_info + except: + from sonic_py_common import device_info + def get_machine_info(): + pass + def get_platform_info(x): + return device_info.get_platform() + +def start(): + x = get_platform_info(get_machine_info()) + print (x) + str = re.findall(r"-(.+?)_",x) + print (str[0]) + if str[0] == 'ragile': + print ("Start privatenetwork.sh") + os.system("/usr/local/bin/privatenetwork.sh start") + else: + print ("Not set private network.") +def stop(): + x = get_platform_info(get_machine_info()) + print (x) + str = re.findall(r"-(.+?)_",x) + print (str[0]) + if str[0] == 'ragile': + print ("Stop privatenetwork.sh") + os.system("/usr/local/bin/privatenetwork.sh stop") + else: + print ("Not stop private network.") +def main(): + print (sys.argv[1]) + if sys.argv[1]=='start': + start() + elif sys.argv[1]=='stop': + stop() + else: + print ("Error parameter!\nRequired parameters : start or stop.") +if __name__ == '__main__': + main() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.sh b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.sh new file mode 100644 index 000000000000..4105dcbfff83 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/privatenetwork.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +function load_eth0.4088(){ + try_times_remain=5 + state_up=$(ip -d link show eth0.4088 | awk '/state UP/{print $2}') + while [ -z "$state_up" ] && [ $try_times_remain -ne 0 ] + do + ((try_times_remain-=1)) + ip link add link eth0 name eth0.4088 type vlan id 4088 || true + ip addr add 240.1.1.2/30 brd 240.1.1.3 dev eth0.4088 || true + ip link set dev eth0.4088 up || true + state_up=$(ip -d link show eth0.4088 | awk '/state UP/{print $2}') + sleep 1 + done +} + +function unload_eth0.4088(){ + ip link set dev eth0.4088 down + ip link del eth0.4088 +} + +if [ "$1" = "start" ];then + load_eth0.4088 +elif [ "$1" = "stop" ];then + unload_eth0.4088 +fi diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/sfpTempToBmc.py b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/sfpTempToBmc.py new file mode 100644 index 000000000000..d22249c0ebba --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/sfpTempToBmc.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +import sys +import click +import os +import time +from ragileutil import * +import syslog +from rest.rest import BMCMessage +import subprocess +import signal +from logutil.logutil import * + +SYSLOG_IDENTIFIER = "sfpTempToBmc" + +def subprocess_os_system(cmd, timeout=1): + slice = 0.1 # 100ms for the unit + retry_total_cnt = timeout / slice + retry_cnt = 0 + try: + child_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True,preexec_fn=os.setsid) + except Exception as e: + print(e) + return child_process.returncode, "" + + while child_process.poll() is None and retry_cnt < retry_total_cnt: + time.sleep(slice) + retry_cnt += 1 + + if retry_cnt >= retry_total_cnt: + os.killpg(os.getpgid(child_process.pid), signal.SIGTERM) + log_error("time out:[%d]" % timeout,SYSLOG_IDENTIFIER) + return False, "" + out, err = child_process.communicate() + return child_process.returncode, out + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def getSfpMaxTemp(): + import sfputil.main + load_platform_sfputil = sfputil.main.load_platform_sfputil() + platform_sfputil = sfputil.main.platform_sfputil + + temps = [] + + for index in range(platform_sfputil.port_start, platform_sfputil.port_end + 1): + if index in platform_sfputil.qsfp_ports: + offset = 22 + eeprom_data = platform_sfputil.get_eeprom_raw(index) + else : + offset = 96 + eeprom_data = platform_sfputil.get_eeprom_dom_raw(index) + if eeprom_data == None: + continue + msb = int(eeprom_data[offset], 16) + lsb = int(eeprom_data[offset + 1], 16) + result = (msb << 8) | (lsb & 0xff) + result = float(result / 256.0) + temps.append(result) + maxtemp = 0 + if len(temps) > 0: + maxtemp = max(temps) + return int(maxtemp * 1000) + +def putDataToBmc(): + # log_info("putDataToBmc") + maxtemp = getSfpMaxTemp() + ret = BMCMessage().postSffTemp(maxtemp) + # print ret + if ret == False: + log_warning("put sfp max temp fail",SYSLOG_IDENTIFIER) + +def run(interval): + index = 0 + while True: + try: + putDataToBmc() + time.sleep(interval) + except Exception as e: + print(e) + +def strtoint(str): + value = 0 + rest_v = str.replace("0X", "").replace("0x", "") + for index in range(len(rest_v)): + value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4) + return value + +def macreset(macledconfig): + if macledconfig == None: + log_error("get param error",SYSLOG_IDENTIFIER) + value = macledconfig.get("reset", 0) + if value == 0: + log_error("get reset value error",SYSLOG_IDENTIFIER) + return False + # try reset 6 times total + for i in range(6): + resetcmd = macledconfig.get("cmdwrformat","") + if resetcmd == "": + log_error("get resetcmd value error",SYSLOG_IDENTIFIER) + continue + ret , status = subprocess_os_system(resetcmd % value) + if ret == 0: + readRDcmd = macledconfig.get("cmdrdformat","") + ret_rd, status_rd = subprocess_os_system(readRDcmd) + status_rd = status_rd.replace("\n", "") + if ret_rd ==0: + status_value = strtoint(status_rd) + if strtoint(status_rd) == value: + # this getter == setter so return + return True + continue + return False + +def runmacLed(interval): + while True: + try: + ret, status = subprocess_os_system("docker ps |wc -l", 3) + status = status.replace("\n", "") + if ret == 0 and int(status) >= 9: + macLedLocation = STARTMODULE.get("macledset_param", None) + if macLedLocation == None: + log_error("macreset error get param none",SYSLOG_IDENTIFIER) + else: + for item in macLedLocation: + if macreset(item) == False: + log_error("macreset error",SYSLOG_IDENTIFIER) + break + time.sleep(interval) + except Exception as e: + print (str(e)) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + interval = STARTMODULE.get("sfptempmodule_interval", 2) + run(interval) + + +@main.command() +def startmacreset(): + interval = STARTMODULE.get("macledreset_interval", 2) + # time.sleep(1) + runmacLed(interval) + +@main.command() +def stop(): + pass + +if __name__ == '__main__': + main() diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/update_machine_config.sh b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/update_machine_config.sh new file mode 100644 index 000000000000..933e7cc3575e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/script/update_machine_config.sh @@ -0,0 +1,24 @@ +#!/bin/bash +onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') +mkdir -p /mnt/onie-boot +mount $onie_dev /mnt/onie-boot +onie_grub_cfg=/mnt/onie-boot/onie/grub/grub-machine.cfg + +if [ ! -e $onie_grub_cfg ]; then + echo "$onie_grub_cfg not found" +else + oldoniebuilddate=`cat /host/machine.conf|grep "onie_build_date="` + oniebuilddate=`cat $onie_grub_cfg|grep "onie_build_date="|sed "s/\"//g"` + onieversion=`cat $onie_grub_cfg|grep "onie_version="` + oniekernelversion=`cat $onie_grub_cfg|grep "onie_kernel_version="` + if [ "$oldoniebuilddate" != "$oniebuilddate" ]; then + echo "update /home/machine.conf" + sed -i "s/onie_build_date=.*/$oniebuilddate/" /host/machine.conf + sed -i "s/onie_version=.*/$onieversion/" /host/machine.conf + sed -i "s/onie_kernel_version=.*/$oniekernelversion/" /host/machine.conf + sed -i "s/\"//g" /host/machine.conf + fi +fi +umount /mnt/onie-boot + + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/service/privatenetwork.service b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/service/privatenetwork.service new file mode 100644 index 000000000000..a962613ad155 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/common_custom/common_ragile/service/privatenetwork.service @@ -0,0 +1,13 @@ +[Unit] +Description=Update interfaces configuration for adding eth0 private subnetwork +After=network.target ra-b6010-48gt4x_platform.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/privatenetwork.py start +ExecStop=/usr/local/bin/privatenetwork.py stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/arm64_ragile_ra_b6010_48gt4x_r_r0_config.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/arm64_ragile_ra_b6010_48gt4x_r_r0_config.py new file mode 100755 index 000000000000..41de37ce85ac --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/arm64_ragile_ra_b6010_48gt4x_r_r0_config.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +from ragilecommon import * +from collections import OrderedDict +PCA9548START = -1 +PCA9548BUSEND = -2 + +RAGILE_CARDID = 0x00004099 +RAGILE_PRODUCTNAME = "RA-B6010-48GT4X" +RAGILE_PART_NUMBER = "RJ000001" +RAGILE_LABEL_REVISION = "R01" +RAGILE_ONIE_VERSION = "2018.05" +RAGILE_MAC_SIZE = 3 +RAGILE_MANUF_NAME = "Ragile" +RAGILE_MANUF_COUNTRY = "CHN" +RAGILE_VENDOR_NAME = "Ragile" +RAGILE_DIAG_VERSION = "0.1.0.15" +RAGILE_SERVICE_TAG = "www.Ragile.com" + +LOCAL_LED_CONTROL = { + "CLOSE":{}, + "OPEN":{} +} + +MACLED_PARAMS = [] + +# start system modules +STARTMODULE = { + "i2ccheck":0, + "fancontrol":0, + "avscontrol":0, + "avscontrol_restful":0, + "sfptempmodule":0, + "sfptempmodule_interval":3, + "macledreset": 0, + "macledreset_interval": 5, + "macledset_param":MACLED_PARAMS, + } + +FRULISTS = [ + {"name":"mmceeprom","bus":5,"loc":0x50, "E2PRODUCT":'2', "E2TYPE":'5' , "CANRESET":'1'}, + {"name":"cpueeprom","bus":5,"loc":0x57,"E2PRODUCT":'2', "E2TYPE":'4', "CANRESET":'1' }, + ] + +# rg_eeprom = "1-0056/eeprom" +E2_LOC = {"bus":1, "devno":0x56} +E2_PROTECT = {} + + +CPLDVERSIONS = [ + {"bus":2, "devno":0x0d, "name":"CPU底板CPLD"}, + {"bus":3, "devno":0x30, "name":"MAC_BOARD_CPLD_1"}, +] + +FIRMWARE_TOOLS = {"cpld": [{"channel":"0","cmd":"firmware_upgrade %s cpld %s cpld", "successtips":"CPLD Upgrade succeeded!"} + ], + } + +# drivers list +DRIVERLISTS = [ + {"name":"i2c_dev", "delay":0}, + {"name":"i2c_algo_bit","delay":0}, + {"name":"spi-bitbang", "delay":0}, + {"name":"i2c_mux", "delay":0}, + {"name":"rtc-pcf85063", "delay":0}, + {"name":"i2c_mux_pca954x", "delay":0}, # force_deselect_on_exit=1 + {"name":"ragile_common dfd_my_type=0x4099", "delay":0}, + {"name":"firmware_driver", "delay":0}, + {"name":"rg_cpld", "delay":0}, + #{"name":"spi-gpio", "delay":0}, + #{"name":"rg_spi_gpio", "delay":0}, + #{"name":"tpm_tis_core", "delay":0}, + #{"name":"tpm_tis_spi", "delay":0}, + {"name":"optoe", "delay":0}, +] + +DEVICE = [ + {"name":"pcf85063","bus":1,"loc":0x51 }, + {"name":"rg_cpld","bus":3,"loc":0x30 }, + {"name":"24c02","bus":5,"loc":0x50 }, + {"name":"24c02","bus":5,"loc":0x57 }, +] + +INIT_PARAM = [ + {"loc":"3-0030/tx_write_protect","value": "59","delay":1}, + {"loc":"3-0030/tx_disable","value": "00"}, + {"loc":"3-0030/tx_write_protect","value": "4e"}, +] + +INIT_COMMAND = [ + "hwclock -s", +] + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/fan_ctrl_cfg.json b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/fan_ctrl_cfg.json new file mode 100755 index 000000000000..d5ede1d886ab --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/config/fan_ctrl_cfg.json @@ -0,0 +1,25 @@ +{ + "Thermal": { + "INLET_TEMP": "INLET_TEMP", + "OUTLET_TEMP": "OUTLET_TEMP", + "SWITCH_TEMP": "TPS53688_TEMP" + }, + "Fans": { + "Fan1" : "Fantray0_Fan1", + "Fan2" : "Fantray0_Fan2", + "Fan3" : "Fantray1_Fan1", + "Fan4" : "Fantray1_Fan2" + }, + "PID": { + "Pwm_Max": 100, + "Pwm_Min": 35, + "TargetTemperature" : 89, + "P": 1.176, + "I": 0.196, + "D": 0.196, + "Temp_Fixup": 5.0, + "Temp_Min": 28.0, + "Temp_Max": 45.0, + "Fall_Hyst": 2.0 + } +} \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/Makefile new file mode 100755 index 000000000000..9310841c645a --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/Makefile @@ -0,0 +1 @@ +obj-m += rg_cpld.o diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/rg_cpld.c b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/rg_cpld.c new file mode 100755 index 000000000000..bbee228f9f8c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/modules/rg_cpld.c @@ -0,0 +1,346 @@ +/* + * rg_cpld.c - A driver for control rg_cpld base on rg_cpld.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2018 wk + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* debug switch level */ +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; +module_param(debuglevel, int, S_IRUGO | S_IWUSR); + +#define DBG_DEBUG(fmt, arg...) do { \ + if ( debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else if ( debuglevel >= DBG_ERROR ) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else { } \ +} while (0) + +#define DBG_ERROR(fmt, arg...) do { \ + if ( debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } \ + } while (0) + + +#define CPLD_SIZE 256 +#define CPLD_I2C_RETRY_TIMES 5 /* changed the number of retry time to 5 */ +#define CPLD_I2C_RETRY_WAIT_TIME 10 /* Delay 10ms before operation */ + + +struct cpld_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static s32 cpld_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_byte_data(client, command) ) >= 0 ) + break; + msleep(CPLD_I2C_RETRY_WAIT_TIME); + } + return ret; +} + +static s32 cpld_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values) ) >= 0 ) + break; + msleep(CPLD_I2C_RETRY_WAIT_TIME); + } + return ret; +} + +static ssize_t set_cpld_sysfs_value(struct device *dev, struct device_attribute *da, const char *buf, size_t +count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + unsigned long val; + int err; + + err = kstrtoul(buf, 16, &val); + if (err) + return err; + if ((val < 0) || (val > 0xff)) { + DBG_ERROR("please enter 0x00 ~ 0xff\n"); + return -1; + } + mutex_lock(&data->update_lock); + data->data[0] = (u8)val; + DBG_DEBUG("pos: 0x%02x count = %ld, data = 0x%02x\n", attr->index, count, data->data[0]); + i2c_smbus_write_byte_data(client, attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_i2c_block_data(client, 0, 4, data->data); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x %02x %02x %02x \n", data->data[0], data->data[1], data->data[2], + data->data[3]); +} + +static ssize_t show_cpld_sysfs_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_byte_data(client, attr->index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[0] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%02x\n", attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x\n", data->data[0]); +} + +/* sys */ +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, show_cpld_version, NULL, 0); + +/* sfp */ +static SENSOR_DEVICE_ATTR(sfp_presence1, S_IRUGO, show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(cable_led1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x20); +static SENSOR_DEVICE_ATTR(cable_led2, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x21); +static SENSOR_DEVICE_ATTR(cable_led3, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x22); +static SENSOR_DEVICE_ATTR(cable_led4, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x23); +static SENSOR_DEVICE_ATTR(cable_led5, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x24); +static SENSOR_DEVICE_ATTR(cable_led6, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x25); +static SENSOR_DEVICE_ATTR(sfp_led1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x26); +static SENSOR_DEVICE_ATTR(sfp_drop_record1, S_IRUGO , show_cpld_sysfs_value, NULL, 0x38); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO , show_cpld_sysfs_value, NULL, 0x50); +static SENSOR_DEVICE_ATTR(sfp_rx_loss1, S_IRUGO , show_cpld_sysfs_value, NULL, 0x70); +/* tx-disbale */ +static SENSOR_DEVICE_ATTR(tx_disable, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x90); +static SENSOR_DEVICE_ATTR(tx_write_protect, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x0e); + + +static struct attribute *mac_cpld_0x30_sysfs_attrs[] = { + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_sfp_presence1.dev_attr.attr, + &sensor_dev_attr_cable_led1.dev_attr.attr, + &sensor_dev_attr_cable_led2.dev_attr.attr, + &sensor_dev_attr_cable_led3.dev_attr.attr, + &sensor_dev_attr_cable_led4.dev_attr.attr, + &sensor_dev_attr_cable_led5.dev_attr.attr, + &sensor_dev_attr_cable_led6.dev_attr.attr, + &sensor_dev_attr_sfp_led1.dev_attr.attr, + &sensor_dev_attr_tx_disable.dev_attr.attr, + &sensor_dev_attr_tx_write_protect.dev_attr.attr, + &sensor_dev_attr_sfp_drop_record1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss1.dev_attr.attr, + NULL +}; + +static const struct attribute_group mac_cpld_0x30_sysfs_group = { + .attrs = mac_cpld_0x30_sysfs_attrs, +}; + + +struct cpld_attr_match_group { + int bus_nr; /* I2C-BUS number */ + unsigned short addr; /* device adress */ + const struct attribute_group *attr_group_ptr;/* SYS attribute pointer */ + const struct attribute_group *attr_hwmon_ptr;/* HWMON Attribute pointer */ +}; + +static struct cpld_attr_match_group g_cpld_attr_match[] = { + {3, 0x30, &mac_cpld_0x30_sysfs_group, NULL}, + +}; + +static const struct attribute_group *cpld_get_attr_group(struct i2c_client *client, int is_hwmon) +{ + int i; + struct cpld_attr_match_group *group; + + for (i = 0; i < ARRAY_SIZE(g_cpld_attr_match); i++) { + group = &g_cpld_attr_match[i]; + DBG_DEBUG("is_hwmon %d i %d client(nr:%d,addr:0x%x), group(nr:%d,addr:0x0%x) .\n", is_hwmon, + i, client->adapter->nr, client->addr, group->bus_nr, group->addr); + if ((client->addr == group->addr) && (client->adapter->nr == group->bus_nr)) { + DBG_DEBUG("is_hwmon %d i %d nr %d addr %d .\n", is_hwmon, i, client->adapter->nr, client->addr); + return (is_hwmon) ? (group->attr_hwmon_ptr) : (group->attr_group_ptr); + } + } + + DBG_DEBUG("is_hwmon %d nr %d addr %d dismatch, return NULL.\n", is_hwmon, client->adapter->nr, client->addr); + return NULL; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + const struct attribute_group *sysfs_group, *hwmon_group; + + status = -1; + DBG_DEBUG("=========cpld_probe(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + status = sysfs_create_group(&client->dev.kobj, sysfs_group); + DBG_DEBUG("=========(addr:0x%x, nr:%d) sysfs_create_group status %d===========\n", client->addr, client->adapter->nr, status); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_create_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + data->hwmon_dev = hwmon_device_register_with_groups(&client->dev, client->name, data, (const struct attribute_group **)hwmon_group); + if (IS_ERR(data->hwmon_dev)) { + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + DBG_ERROR("hwmon_device_register_with_groups failed ret %ld.\n", PTR_ERR(data->hwmon_dev)); + return PTR_ERR(data->hwmon_dev); + } + DBG_DEBUG("=========(addr:0x%x, nr:%d) hwmon_device_register_with_groups success===========\n", client->addr, client->adapter->nr); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_register_with_groups \n", client->addr, client->adapter->nr); + } + +error: + return status; + +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *sysfs_group, *hwmon_group; + + DBG_DEBUG("=========cpld_remove(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + + /* To be added the corresponding uninstall operation */ + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do sysfs_remove_group \n", client->addr, client->adapter->nr); + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_remove_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do hwmon_device_unregister \n", client->addr, client->adapter->nr); + hwmon_device_unregister(data->hwmon_dev); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_unregister \n", client->addr, client->adapter->nr); + } + + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "rg_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver rg_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "rg_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +}; + +module_i2c_driver(rg_cpld_driver); +MODULE_AUTHOR("wk "); +MODULE_DESCRIPTION("ragile CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/service/ra-b6010-48gt4x-r_platform.service b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/service/ra-b6010-48gt4x-r_platform.service new file mode 100755 index 000000000000..d068e4cccc4f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/service/ra-b6010-48gt4x-r_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-ra-b6010-48gt4x-r start +ExecStop=-/etc/init.d/platform-modules-ra-b6010-48gt4x-r stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/setup.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/setup.py new file mode 100755 index 000000000000..f51886a75d47 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize centec ra-b6010-48gt4x platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/__init__.py new file mode 100755 index 000000000000..4bfefa0fb636 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/chassis.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/chassis.py new file mode 100755 index 000000000000..21981ea7e73b --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/chassis.py @@ -0,0 +1,182 @@ + +#!/usr/bin/env python + +try: + import os + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from sonic_platform.fan import Fan + from sonic_platform.thermal import Thermal + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.sfp import Sfp + from sonic_platform.psu import Psu + from .component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 2 +NUM_FAN = 4 +NUM_THERMAL = 5 +NUM_PORT = 52 +NUM_PSU = 2 + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + # Initialize EEPROM + self._eeprom = Eeprom() + #firmware + for i in range(0,2): + self._component_list.append(Component(i)) + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + # Initialize SFP + self._sfp_list.append(Sfp(1)) + for index in range(0, NUM_PORT): + sfp = Sfp(index + 1) + self._sfp_list.append(sfp) + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + +############################################## +# 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_revision(self): + val = ord(self._eeprom.revision_str()) + test = "{}".format(val) + return test + + 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. + """ + return (None, 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. + """ + ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout) + 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] + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/component.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/component.py new file mode 100755 index 000000000000..4cb63f51027c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/component.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +try: + import subprocess + from sonic_platform_base.component_base import ComponentBase + import sonic_platform.hwaccess as hwaccess +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +def get_cpld_version(bus, i2caddr): + return '{}{}{}{}'.format(hwaccess.i2c_get(bus, i2caddr, 1), + hwaccess.i2c_get(bus, i2caddr, 2), + hwaccess.i2c_get(bus, i2caddr, 3), + hwaccess.i2c_get(bus, i2caddr, 0) + ) + +def get_cpu_cpld_version(): + return get_cpld_version(2, 0x0d) + +def get_cpld1_version(): + return get_cpld_version(3, 0x30) + +COMPONENT_LIST= [ + ['CPU CPLD', + 'cpu board', + get_cpu_cpld_version + ], + + ['MAC1 CPLD', + 'mac1 board', + get_cpld1_version + ] + ] + +class Component(ComponentBase): + """ Ragile Platform-specific Component class""" + + def __init__(self, component_index=0): + ComponentBase.__init__(self) + self.index = component_index + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return COMPONENT_LIST[self.index][0] + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return COMPONENT_LIST[self.index][1] + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + return COMPONENT_LIST[self.index][2]() + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + try: + successtips = "CPLD Upgrade succeeded!" + status, output = subprocess.getstatusoutput("which firmware_upgrade") + if status or len(output) <= 0: + logger.error("no upgrade tool.") + return False + cmdstr = "%s %s cpld %d cpld"%(output,image_path,self.slot) + ret, log = subprocess.getstatusoutput(cmdstr) + if ret == 0 and successtips in log: + return True + logger.error("upgrade failed. ret:%d, log:\n%s" % (ret, log)) + except Exception as e: + logger.error(str(e)) + return False + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/eeprom.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/eeprom.py new file mode 100755 index 000000000000..202bd1bbb207 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/eeprom.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + """Platform-specific Eeprom class""" + + def __init__(self, bus=1, loc="0056", config=None, iom_eeprom=False): + + if config: + bus = config.get("bus") + loc = config.get("loc") + + if bus and loc: + self.__eeprom_path = "/sys/bus/i2c/devices/{}-{}/eeprom".format(bus, loc) + else: + raise ValueError( + "Eeprom location error, bus: {}, loc: {}, config: {}".format( + bus, loc, config + ) + ) + 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-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan.py new file mode 100755 index 000000000000..fa08e9e151a0 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python + +import json +import math +import os.path +import time + +try: + from sonic_platform_base.fan_base import FanBase + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_NAME_LIST = ["Fan1", "Fan2"] + +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 + self.redfish = Redfish_Api() + pinf = self.redfish.get_thermal() + self._fan_list = [] + FanBase.__init__(self) + self.begin = time.time() + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_speed_pwm(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + speed = output.get("Oem").get("Ragile").get("FanSpeedLevelPercents") + return int(speed) + + def get_speed_rpm(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + speed = output.get("Reading") + return int(speed) + + def get_high_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + high = output.get("UpperThresholdFatal") + return int(high) + + def get_low_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + low = output.get("LowerThresholdFatal") + return int(low) + + def set_speed_pwm(self, speed): + post_url = '/redfish/v1/Chassis/1/Thermal/Actions/Oem/Ragile/Fan.SetSpeed' + playload = {} + playload["FanName"] = "Fan0" + playload["FanSpeedLevelPercents"] = str(speed) + return self.redfish.post_odata(post_url, playload) + + def get_status_led(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + led = output.get("Oem").get("Ragile").get("IndicatorLEDColor") + return led + + def set_status_led(self, color): + playload = {} + led = {} + led_list = [] + led["IndicatorLEDColor"] = color + led["LEDType"] = "fan" + led_list.append(led) + playload["LEDs"] = led_list + # boardsLed + return self.redfish.post_boardLed(playload) + + def get_direction(self): + return "B2F" + + def get_name(self): + fan_name = FAN_NAME_LIST[self.fan_index] + return "Fantray{}_{}".format(self.fan_tray_index, fan_name) + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + if output.get("Status").get("Status").get("State") == "Enabled": + return True + return False + + def get_status(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + if output.get("Status").get("Status").get("Health") == "OK": + return True + return False + + def get_high_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + high = output.get("UpperThresholdFatal") + return high + + def get_low_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + low = output.get("LowerThresholdFatal") + return low + + def get_speed(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + speed = output.get("Oem").get("Ragile").get("FanSpeedLevelPercents") + return speed diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan_drawer.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan_drawer.py new file mode 100755 index 000000000000..9db554d0d195 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/fan_drawer.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import json +import math +import os.path +import time + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(FanDrawerBase): + + FANS_PER_FANTRAY = 2 + + def __init__(self, fantray_index=0): + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + self.redfish = Redfish_Api() + pinf = self.redfish.get_thermal() + self.begin = time.time() + for i in range(self.FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_name(self): + return "FanTray{}".format(self.fantrayindex) + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fantrayindex] + if output.get("Status").get("Status").get("State") == "Enabled": + return True + + def get_status(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fantrayindex] + if output.get("Status").get("Status").get("Health") == "OK": + return True + + def set_status_led(self, color): + playload = {} + led = {} + led_list = [] + led["IndicatorLEDColor"] = color + led["LEDType"] = "fan" + led_list.append(led) + playload["LEDs"] = led_list + # boardsLed + return self.redfish.post_boardLed(playload) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/hwaccess.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/hwaccess.py new file mode 100755 index 000000000000..595514c07de4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/hwaccess.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import os +import struct +import mmap +import subprocess + +# Read PCI device + +def pci_mem_read(mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + return struct.unpack('I',read_data_stream)[0] + +def pci_get_value(resource, offset): + with open(resource, 'r+b') as fd: + mm = mmap.mmap(fd.fileno(), 0) + val = pci_mem_read(mm, offset) + mm.close() + return val + +def pci_mem_write(memmap, offset, data): + """ Write PCI device """ + memmap.seek(offset) + memmap.write(struct.pack('I', data)) + +def pci_set_value(resource, val, offset): + """ Set a value to PCI device """ + with open(resource, 'w+b') as filed: + memmap = None + try: + memmap = mmap.mmap(filed.fileno(), 0) + pci_mem_write(memmap, offset, val) + except EnvironmentError: + pass + if memmap is not None: + memmap.close() + +# Read I2C device + +def i2c_get(bus, i2caddr, ofs): + try: + valx = int(subprocess.check_output(['/usr/sbin/i2cget','-f', '-y', str(bus), str(i2caddr), str(ofs)]), 16) + return "{:02x}".format(valx) + except (FileNotFoundError, subprocess.CalledProcessError): + return -1 + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/platform.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/platform.py new file mode 100755 index 000000000000..7225a71b0307 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/platform.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +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-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/psu.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/psu.py new file mode 100755 index 000000000000..c5fc3b163854 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/psu.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +import time +import imp +import os + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common import device_info + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, index=0): + PsuBase.__init__(self) + self.redfish = Redfish_Api() + pinf = self.redfish.get_power() + self.psu_index = index + self._fan_list = [] + self._thermal_list = [] + self.begin = time.time() + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_power() + self.begin = time.time() + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + if output.get("Status").get("State") == "Enabled": + return True + else: + return False + + def get_powergood_status(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + if output.get("Status").get("Health") == "OK": + return True + else: + return False + + def get_serial(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + serial = output.get("SerialNumber") + return serial + + def get_model(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + model = output.get("Model") + return model + + def get_revision(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + manufacturer = output.get("Manufacturer") + return manufacturer + + def get_voltage(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + voltage = output.get("Oem").get("Ragile").get("OutputVoltage") + return voltage + + def get_input_current(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + current = output.get("Oem").get("Ragile").get("OutputAmperage") + return current + + def get_input_voltage(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + voltage = output.get("Oem").get("Ragile").get("OutputVoltage") + return voltage + + def get_current(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + current = output.get("Oem").get("Ragile").get("OutputAmperage") + return current + + def get_power(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + current = output.get("Oem").get("Ragile").get("OutputAmperage") + voltage = output.get("Oem").get("Ragile").get("OutputVoltage") + power = float(current)*float(voltage) + return power + + def get_temperature(self): + return None + + def get_status_led(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + led = output.get("Oem").get("Ragile").get("IndicatorLEDColor") + return led + + def set_status_led(self, color): + playload = {} + led = {} + led_list = [] + led["IndicatorLEDColor"] = color + led["LEDType"] = "pwr" + led_list.append(led) + playload["LEDs"] = led_list + # boardsLed + return self.redfish.post_boardLed(playload) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/redfish_api.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/redfish_api.py new file mode 100755 index 000000000000..d0d9927d0690 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/redfish_api.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import sys +import json +import traceback +import datetime +import os +import ssl +import subprocess +import syslog + +class Redfish_Api(): + BmcBaseUrl = 'http://240.1.1.1:8080' + ThermalUrl = '/redfish/v1/Chassis/1/Thermal' + PowerUrl = '/redfish/v1/Chassis/1/Power' + ThresholdSensorsUrl = '/redfish/v1/Chassis/1/ThresholdSensors' + FanSpeedUrl = '/redfish/v1/Chassis/1/Thermal/Actions/Oem/Ragile/Fan.SetSpeed' + BoardsUrl = '/redfish/v1/Chassis/1/Boards/' + BoardLedUrl = "/redfish/v1/Chassis/1/Boards/{}/Actions/Oem/Ragile/Boards.SetLED" + + # Maximum time in seconds that you allow the connection to the server to take. + connect_timeout = 30 + # Maximum time in seconds that you allow the whole operation to take + operation_timeout = 300 + + default_prefix='/redfish/v1/' + session = None + __DEBUG__ = "N" + __DUMP_RESP__ = "N" + RST_STATUS = "status" + RST_SUCCESS = "OK" + refish_logger = None + + def redfish_log_debug(self, msg): + if (self.__DEBUG__ == "Y"): + syslog.openlog("redfis_api") + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + def redfish_log_error(self, msg): + syslog.openlog("redfish_api") + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + def __init__(self): + pass + + def get_full_url(self, url): + return self.BmcBaseUrl + url + + def _exec_cmd(self, cmd): + self.redfish_log_debug("Cmd: %s" % cmd) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p.wait() + self.redfish_log_debug("Cmd return: %d" % p.returncode) + str_stdout = p.stdout.read().decode('utf-8') + str_stderr = p.stderr.read().decode('utf-8') + self.redfish_log_debug("Cmd stdout: %s" % str_stdout) + if p.returncode !=0: + self.redfish_log_error("Cmd: %s, failed! error msg:%s" % (cmd, str_stderr)) + return None + else: + try: + ret = json.loads(str_stdout) + return ret + except Exception as e: + self.redfish_log_error("Cmd: %s, failed! stdout msg:%s" % (cmd, str_stdout)) + return None + + def _redfish_get(self, url): + self.redfish_log_debug("Get info from %s." % url) + result = None + try: + cmd_get="curl --connect-timeout %d -m %d -X GET %s" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url)) + result = self._exec_cmd(cmd_get) + except Exception as e: + self.redfish_log_error("error_message: %s" % e) + result = None + finally: + return result + + def _redfish_post(self, url, playload): + self.redfish_log_debug("post url: %s" % url) + self.redfish_log_debug("Playload: %s" % playload) + + playload_json = json.dumps(playload) + result = False + try: + cmd_post="curl --connect-timeout %d -m %d -X POST %s -d \'%s\'" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url), playload_json) + ret_msg = self._exec_cmd(cmd_post) + if ret_msg == None: + return False + elif ret_msg["success"] == False: + redfish_log_error("Url: '%s', Playload: '%s', Bmc return failed, error_message: %s" % (url, playload_json, ret_msg["Message"])) + result = False + else: + result = True + except Exception as e: + redfish_log_error("error_message: %s" % e) + result = False + finally: + return result + + def get_thermal(self): + """Get thermal info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.ThermalUrl) + + def get_power(self): + """Get power info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.PowerUrl) + + def get_thresholdSensors(self): + """Get thresholdSensors info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.ThresholdSensorsUrl) + + def post_odata(self, odata_id, playload): + """post odata info + :params odata_id: the specified odata_id path + :type odata_id: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if odata_id is None or playload is None: + print("post failed: odata_id or playload is None") + return False + return self._redfish_post(odata_id, playload) + + def get_odata(self, odata_id): + """Get odata info + :params odata_id: the specified odata_id path + :type odata_id: string + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + if odata_id is None: + print("Get odata_id failed: odata_id is None") + return None + return self._redfish_get(odata_id) + + def post_fanSpeed(self, playload): + """post odata info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.FanSpeedUrl, playload) + + def get_board(self, board_name="indicatorboard"): + """Get board info + :board_name: name of board, default is "indicatorboard" + :type: string + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + if board_name is None : + print("get failed: board_name is None") + return None + return self._redfish_get(self.BoardsUrl + board_name) + + def post_boardLed(self, playload, board_name="indicatorboard"): + """post boardLed info + :board_name: name of board, default is "indicatorboard" + :type: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if board_name is None or playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.BoardLedUrl.format(board_name), playload) + + ''' not supported currently + def post_thermal(self, playload): + """post thermal info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_thermal failed: playload is None") + return None + return self._redfish_post(self.ThermalUrl, playload) + + def post_power(self, playload): + """post power info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_power failed: playload is None") + return None + return self._redfish_post(self.PowerUrl, playload) + + def post_thresholdSensors(self, playload): + """post thresholdSensors info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_thresholdSensors failed: playload is None") + return None + return self._redfish_post(self.ThresholdSensorsUrl, playload) + + def get_fanSpeed(self): + """Get board led info + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.FanSpeedUrl) + + def post_board(self, playload, board_name="indicatorboard"): + """post board info + :board_name: name of board, default is "indicatorboard" + :type: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if board_name is None or playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.BoardsUrl + board_name, playload) + + def get_boardLed(self, board_name="indicatorboard"): + """Get boardLed info + :board_name: name of board, default is "indicatorboard" + :type: string + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + if board_name is None : + print("get failed: board_name is None") + return None + return self._redfish_get(self.BoardsUrl % board_name) + + ''' + +''' +if __name__ == '__main__': + redfish = Redfish_Api() + + ### get + # boards + ret = redfish.get_board() + if ret is None: + print("get failed: board") + else: + print("get succeeded, board:%s" % ret) + + ret = redfish.get_thresholdSensors() + if ret is None: + print("get failed: threshold") + else: + print("get succeeded, threshold:%s" % ret) + + ret = redfish.get_power() + if ret is None: + print("get failed: power") + else: + print("get succeeded, power:%s" % ret) + + ret = redfish.get_thermal() + if ret is None: + print("get failed:thermal") + else: + print("get succeeded,thermal:%s" % ret) + + # get playload + resp = redfish.get_thresholdSensors() + if (resp != None): + print(resp["@odata.id"]) + print(resp["@odata.type"]) + print(resp["Id"]) + print(resp["Name"]) + else: + print("Failed: get_thresholdSensors") + + ### post + # fanSpeed + playload = {} + playload["FanName"] = 'Fan0' + playload["FanSpeedLevelPercents"] = "70" + print("post fanSpeed:%s" % redfish.post_fanSpeed(playload)) + + #{"LEDs": [{"IndicatorLEDColor": "green","LEDType": "sys"},{"IndicatorLEDColor": "off","LEDType": "pwr"},{"IndicatorLEDColor": "green","LEDType": "fan"}]} + playload = {} + led = {} + led1 = {} + led_list = [] + led["IndicatorLEDColor"] = "green" + led["LEDType"] = "sys" + led1["IndicatorLEDColor"] = "off" + led1["LEDType"] = "pwr" + led_list.append(led) + led_list.append(led1) + playload["LEDs"] = led_list + # boardsLed + print("post boardLed:%s" % redfish.post_boardLed(playload)) +''' \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/sfp.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/sfp.py new file mode 100755 index 000000000000..06ace335dce1 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/sfp.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import time +import imp +import os + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Sfp(SfpBase): + """ + Platform-specific sfp class + + Unimplemented methods: + - get_model + - get_serial + - get_status + - get_transceiver_info + - get_transceiver_bulk_status + - get_transceiver_threshold_info + - get_reset_status + - get_rx_los + - get_tx_fault + - get_tx_disable_channel + - get_power_override + - get_temperature + - get_voltage + - get_tx_bias + - get_rx_power + - get_tx_power + - tx_disable_channel + - set_power_override + """ + + def __init__(self, index): + self._index = index + self._thermal_list = [] + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "sfputil.py"]) + module = imp.load_source("sfputil", module_file) + sfp_util_class = getattr(module, "SfpUtil") + self._sfputil = sfp_util_class() + + def get_id(self): + return self._index + + def get_name(self): + return "Ethernet{}".format(self._index - 1) + + def get_lpmode(self): + return False + + def set_lpmode(self, lpmode): + return False + + def get_tx_disable(self): + return False + + def tx_disable(self, tx_disable): + return False + + def reset(self): + pass + + def clear_interrupt(self): + return False + + def get_interrupt_file(self): + return None + + def _get_sfputil(self): + return self._sfputil + + def get_presence(self): + return self._get_sfputil().get_presence(self._index) + + def get_transceiver_info(self): + return self._get_sfputil().get_transceiver_info_dict(self._index) + + def get_transceiver_bulk_status(self): + return self._get_sfputil().get_transceiver_dom_info_dict(self._index) + + def get_transceiver_threshold_info(self): + return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index) + + def get_transceiver_change_event(self, timeout): + return self._get_sfputil().get_transceiver_change_event(timeout) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/thermal.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/thermal.py new file mode 100755 index 000000000000..e768d3ca1187 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x-r/sonic_platform/thermal.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +import os +import re +import os.path +import time + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, thermal_index): + ThermalBase.__init__(self) + self.index = thermal_index + self.high_threshold = float(112) + self.redfish = Redfish_Api() + pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_temperature(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("ReadingCelsius") + return temp + + def get_high_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("UpperThresholdFatal") + return temp + + def get_low_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("LowerThresholdFatal") + return temp + + def get_high_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("UpperThresholdFatal") + return temp + + def get_low_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("LowerThresholdFatal") + return temp + + def get_name(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index].get("Name") + name = output.split("/",3)[2] + return "{}".format(name) + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + if output.get("Status").get("Status").get("State") == "Enabled": + return True + + def get_status(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + if output.get("Status").get("Health") == "OK": + return True diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/arm64_ragile_ra_b6010_48gt4x_r0_config.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/arm64_ragile_ra_b6010_48gt4x_r0_config.py new file mode 100644 index 000000000000..41de37ce85ac --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/arm64_ragile_ra_b6010_48gt4x_r0_config.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +from ragilecommon import * +from collections import OrderedDict +PCA9548START = -1 +PCA9548BUSEND = -2 + +RAGILE_CARDID = 0x00004099 +RAGILE_PRODUCTNAME = "RA-B6010-48GT4X" +RAGILE_PART_NUMBER = "RJ000001" +RAGILE_LABEL_REVISION = "R01" +RAGILE_ONIE_VERSION = "2018.05" +RAGILE_MAC_SIZE = 3 +RAGILE_MANUF_NAME = "Ragile" +RAGILE_MANUF_COUNTRY = "CHN" +RAGILE_VENDOR_NAME = "Ragile" +RAGILE_DIAG_VERSION = "0.1.0.15" +RAGILE_SERVICE_TAG = "www.Ragile.com" + +LOCAL_LED_CONTROL = { + "CLOSE":{}, + "OPEN":{} +} + +MACLED_PARAMS = [] + +# start system modules +STARTMODULE = { + "i2ccheck":0, + "fancontrol":0, + "avscontrol":0, + "avscontrol_restful":0, + "sfptempmodule":0, + "sfptempmodule_interval":3, + "macledreset": 0, + "macledreset_interval": 5, + "macledset_param":MACLED_PARAMS, + } + +FRULISTS = [ + {"name":"mmceeprom","bus":5,"loc":0x50, "E2PRODUCT":'2', "E2TYPE":'5' , "CANRESET":'1'}, + {"name":"cpueeprom","bus":5,"loc":0x57,"E2PRODUCT":'2', "E2TYPE":'4', "CANRESET":'1' }, + ] + +# rg_eeprom = "1-0056/eeprom" +E2_LOC = {"bus":1, "devno":0x56} +E2_PROTECT = {} + + +CPLDVERSIONS = [ + {"bus":2, "devno":0x0d, "name":"CPU底板CPLD"}, + {"bus":3, "devno":0x30, "name":"MAC_BOARD_CPLD_1"}, +] + +FIRMWARE_TOOLS = {"cpld": [{"channel":"0","cmd":"firmware_upgrade %s cpld %s cpld", "successtips":"CPLD Upgrade succeeded!"} + ], + } + +# drivers list +DRIVERLISTS = [ + {"name":"i2c_dev", "delay":0}, + {"name":"i2c_algo_bit","delay":0}, + {"name":"spi-bitbang", "delay":0}, + {"name":"i2c_mux", "delay":0}, + {"name":"rtc-pcf85063", "delay":0}, + {"name":"i2c_mux_pca954x", "delay":0}, # force_deselect_on_exit=1 + {"name":"ragile_common dfd_my_type=0x4099", "delay":0}, + {"name":"firmware_driver", "delay":0}, + {"name":"rg_cpld", "delay":0}, + #{"name":"spi-gpio", "delay":0}, + #{"name":"rg_spi_gpio", "delay":0}, + #{"name":"tpm_tis_core", "delay":0}, + #{"name":"tpm_tis_spi", "delay":0}, + {"name":"optoe", "delay":0}, +] + +DEVICE = [ + {"name":"pcf85063","bus":1,"loc":0x51 }, + {"name":"rg_cpld","bus":3,"loc":0x30 }, + {"name":"24c02","bus":5,"loc":0x50 }, + {"name":"24c02","bus":5,"loc":0x57 }, +] + +INIT_PARAM = [ + {"loc":"3-0030/tx_write_protect","value": "59","delay":1}, + {"loc":"3-0030/tx_disable","value": "00"}, + {"loc":"3-0030/tx_write_protect","value": "4e"}, +] + +INIT_COMMAND = [ + "hwclock -s", +] + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/fan_ctrl_cfg.json b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/fan_ctrl_cfg.json new file mode 100644 index 000000000000..4482fade9dbd --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/config/fan_ctrl_cfg.json @@ -0,0 +1,37 @@ +{ + "Device": { + "Liquid": 0, + "Buildin": 1 + }, + "Thermal": { + "INLET_TEMP": "INLET_TEMP", + "OUTLET_TEMP": "OUTLET_TEMP", + "SWITCH_TEMP": "SWITCH_TEMP" + }, + "Fans": { + "Fan1" : "Fantray0_Fan1", + "Fan2" : "Fantray0_Fan2", + "Fan3" : "Fantray1_Fan1", + "Fan4" : "Fantray1_Fan2" + }, + "PID": { + "Pwm_Max": 100, + "Pwm_Min": 30, + "SetPoint" : 90, + "P": 1.5, + "I": 1, + "D": 0.3, + "Temp_Min": 28.0, + "Temp_Max": 45.0, + "Sensor": "SWITCH_TEMP" + }, + "OpenLoop": { + "a": -0.06, + "b": 10.3, + "c": -142.0, + "fix_up": -8, + "pwmMax": 100, + "pwmMin": 30, + "tempMin": 25 + } +} \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/Makefile new file mode 100644 index 000000000000..9310841c645a --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/Makefile @@ -0,0 +1 @@ +obj-m += rg_cpld.o diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/rg_cpld.c b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/rg_cpld.c new file mode 100644 index 000000000000..bbee228f9f8c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/modules/rg_cpld.c @@ -0,0 +1,346 @@ +/* + * rg_cpld.c - A driver for control rg_cpld base on rg_cpld.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2018 wk + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* debug switch level */ +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; +module_param(debuglevel, int, S_IRUGO | S_IWUSR); + +#define DBG_DEBUG(fmt, arg...) do { \ + if ( debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else if ( debuglevel >= DBG_ERROR ) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else { } \ +} while (0) + +#define DBG_ERROR(fmt, arg...) do { \ + if ( debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } \ + } while (0) + + +#define CPLD_SIZE 256 +#define CPLD_I2C_RETRY_TIMES 5 /* changed the number of retry time to 5 */ +#define CPLD_I2C_RETRY_WAIT_TIME 10 /* Delay 10ms before operation */ + + +struct cpld_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static s32 cpld_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_byte_data(client, command) ) >= 0 ) + break; + msleep(CPLD_I2C_RETRY_WAIT_TIME); + } + return ret; +} + +static s32 cpld_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values) ) >= 0 ) + break; + msleep(CPLD_I2C_RETRY_WAIT_TIME); + } + return ret; +} + +static ssize_t set_cpld_sysfs_value(struct device *dev, struct device_attribute *da, const char *buf, size_t +count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + unsigned long val; + int err; + + err = kstrtoul(buf, 16, &val); + if (err) + return err; + if ((val < 0) || (val > 0xff)) { + DBG_ERROR("please enter 0x00 ~ 0xff\n"); + return -1; + } + mutex_lock(&data->update_lock); + data->data[0] = (u8)val; + DBG_DEBUG("pos: 0x%02x count = %ld, data = 0x%02x\n", attr->index, count, data->data[0]); + i2c_smbus_write_byte_data(client, attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_i2c_block_data(client, 0, 4, data->data); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x %02x %02x %02x \n", data->data[0], data->data[1], data->data[2], + data->data[3]); +} + +static ssize_t show_cpld_sysfs_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_byte_data(client, attr->index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[0] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%02x\n", attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x\n", data->data[0]); +} + +/* sys */ +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, show_cpld_version, NULL, 0); + +/* sfp */ +static SENSOR_DEVICE_ATTR(sfp_presence1, S_IRUGO, show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(cable_led1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x20); +static SENSOR_DEVICE_ATTR(cable_led2, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x21); +static SENSOR_DEVICE_ATTR(cable_led3, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x22); +static SENSOR_DEVICE_ATTR(cable_led4, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x23); +static SENSOR_DEVICE_ATTR(cable_led5, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x24); +static SENSOR_DEVICE_ATTR(cable_led6, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x25); +static SENSOR_DEVICE_ATTR(sfp_led1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x26); +static SENSOR_DEVICE_ATTR(sfp_drop_record1, S_IRUGO , show_cpld_sysfs_value, NULL, 0x38); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO , show_cpld_sysfs_value, NULL, 0x50); +static SENSOR_DEVICE_ATTR(sfp_rx_loss1, S_IRUGO , show_cpld_sysfs_value, NULL, 0x70); +/* tx-disbale */ +static SENSOR_DEVICE_ATTR(tx_disable, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x90); +static SENSOR_DEVICE_ATTR(tx_write_protect, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x0e); + + +static struct attribute *mac_cpld_0x30_sysfs_attrs[] = { + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_sfp_presence1.dev_attr.attr, + &sensor_dev_attr_cable_led1.dev_attr.attr, + &sensor_dev_attr_cable_led2.dev_attr.attr, + &sensor_dev_attr_cable_led3.dev_attr.attr, + &sensor_dev_attr_cable_led4.dev_attr.attr, + &sensor_dev_attr_cable_led5.dev_attr.attr, + &sensor_dev_attr_cable_led6.dev_attr.attr, + &sensor_dev_attr_sfp_led1.dev_attr.attr, + &sensor_dev_attr_tx_disable.dev_attr.attr, + &sensor_dev_attr_tx_write_protect.dev_attr.attr, + &sensor_dev_attr_sfp_drop_record1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss1.dev_attr.attr, + NULL +}; + +static const struct attribute_group mac_cpld_0x30_sysfs_group = { + .attrs = mac_cpld_0x30_sysfs_attrs, +}; + + +struct cpld_attr_match_group { + int bus_nr; /* I2C-BUS number */ + unsigned short addr; /* device adress */ + const struct attribute_group *attr_group_ptr;/* SYS attribute pointer */ + const struct attribute_group *attr_hwmon_ptr;/* HWMON Attribute pointer */ +}; + +static struct cpld_attr_match_group g_cpld_attr_match[] = { + {3, 0x30, &mac_cpld_0x30_sysfs_group, NULL}, + +}; + +static const struct attribute_group *cpld_get_attr_group(struct i2c_client *client, int is_hwmon) +{ + int i; + struct cpld_attr_match_group *group; + + for (i = 0; i < ARRAY_SIZE(g_cpld_attr_match); i++) { + group = &g_cpld_attr_match[i]; + DBG_DEBUG("is_hwmon %d i %d client(nr:%d,addr:0x%x), group(nr:%d,addr:0x0%x) .\n", is_hwmon, + i, client->adapter->nr, client->addr, group->bus_nr, group->addr); + if ((client->addr == group->addr) && (client->adapter->nr == group->bus_nr)) { + DBG_DEBUG("is_hwmon %d i %d nr %d addr %d .\n", is_hwmon, i, client->adapter->nr, client->addr); + return (is_hwmon) ? (group->attr_hwmon_ptr) : (group->attr_group_ptr); + } + } + + DBG_DEBUG("is_hwmon %d nr %d addr %d dismatch, return NULL.\n", is_hwmon, client->adapter->nr, client->addr); + return NULL; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + const struct attribute_group *sysfs_group, *hwmon_group; + + status = -1; + DBG_DEBUG("=========cpld_probe(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + status = sysfs_create_group(&client->dev.kobj, sysfs_group); + DBG_DEBUG("=========(addr:0x%x, nr:%d) sysfs_create_group status %d===========\n", client->addr, client->adapter->nr, status); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_create_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + data->hwmon_dev = hwmon_device_register_with_groups(&client->dev, client->name, data, (const struct attribute_group **)hwmon_group); + if (IS_ERR(data->hwmon_dev)) { + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + DBG_ERROR("hwmon_device_register_with_groups failed ret %ld.\n", PTR_ERR(data->hwmon_dev)); + return PTR_ERR(data->hwmon_dev); + } + DBG_DEBUG("=========(addr:0x%x, nr:%d) hwmon_device_register_with_groups success===========\n", client->addr, client->adapter->nr); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_register_with_groups \n", client->addr, client->adapter->nr); + } + +error: + return status; + +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *sysfs_group, *hwmon_group; + + DBG_DEBUG("=========cpld_remove(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + + /* To be added the corresponding uninstall operation */ + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do sysfs_remove_group \n", client->addr, client->adapter->nr); + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_remove_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do hwmon_device_unregister \n", client->addr, client->adapter->nr); + hwmon_device_unregister(data->hwmon_dev); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_unregister \n", client->addr, client->adapter->nr); + } + + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "rg_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver rg_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "rg_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +}; + +module_i2c_driver(rg_cpld_driver); +MODULE_AUTHOR("wk "); +MODULE_DESCRIPTION("ragile CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/service/ra-b6010-48gt4x_platform.service b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/service/ra-b6010-48gt4x_platform.service new file mode 100644 index 000000000000..bd13cf98ae3d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/service/ra-b6010-48gt4x_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-ra-b6010-48gt4x start +ExecStop=-/etc/init.d/platform-modules-ra-b6010-48gt4x stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/setup.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/setup.py new file mode 100644 index 000000000000..f51886a75d47 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize centec ra-b6010-48gt4x platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/__init__.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/__init__.py new file mode 100644 index 000000000000..4bfefa0fb636 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/chassis.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/chassis.py new file mode 100644 index 000000000000..d5a2d0ca8084 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/chassis.py @@ -0,0 +1,181 @@ + +#!/usr/bin/env python + +try: + import os + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from sonic_platform.fan import Fan + from sonic_platform.thermal import Thermal + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.sfp import Sfp + from sonic_platform.psu import Psu + from .component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 2 +NUM_FAN = 4 +NUM_THERMAL = 3 +NUM_PORT = 52 +NUM_PSU = 2 + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + # Initialize EEPROM + self._eeprom = Eeprom() + #firmware + for i in range(0,2): + self._component_list.append(Component(i)) + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + # Initialize SFP + for index in range(0, NUM_PORT + 1): + sfp = Sfp(index) + self._sfp_list.append(sfp) + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + +############################################## +# 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_revision(self): + val = ord(self._eeprom.revision_str()) + test = "{}".format(val) + return test + + 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. + """ + return (None, 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. + """ + ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout) + 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] + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/component.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/component.py new file mode 100755 index 000000000000..4cb63f51027c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/component.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +try: + import subprocess + from sonic_platform_base.component_base import ComponentBase + import sonic_platform.hwaccess as hwaccess +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +def get_cpld_version(bus, i2caddr): + return '{}{}{}{}'.format(hwaccess.i2c_get(bus, i2caddr, 1), + hwaccess.i2c_get(bus, i2caddr, 2), + hwaccess.i2c_get(bus, i2caddr, 3), + hwaccess.i2c_get(bus, i2caddr, 0) + ) + +def get_cpu_cpld_version(): + return get_cpld_version(2, 0x0d) + +def get_cpld1_version(): + return get_cpld_version(3, 0x30) + +COMPONENT_LIST= [ + ['CPU CPLD', + 'cpu board', + get_cpu_cpld_version + ], + + ['MAC1 CPLD', + 'mac1 board', + get_cpld1_version + ] + ] + +class Component(ComponentBase): + """ Ragile Platform-specific Component class""" + + def __init__(self, component_index=0): + ComponentBase.__init__(self) + self.index = component_index + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return COMPONENT_LIST[self.index][0] + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return COMPONENT_LIST[self.index][1] + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + return COMPONENT_LIST[self.index][2]() + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + try: + successtips = "CPLD Upgrade succeeded!" + status, output = subprocess.getstatusoutput("which firmware_upgrade") + if status or len(output) <= 0: + logger.error("no upgrade tool.") + return False + cmdstr = "%s %s cpld %d cpld"%(output,image_path,self.slot) + ret, log = subprocess.getstatusoutput(cmdstr) + if ret == 0 and successtips in log: + return True + logger.error("upgrade failed. ret:%d, log:\n%s" % (ret, log)) + except Exception as e: + logger.error(str(e)) + return False + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/eeprom.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/eeprom.py new file mode 100644 index 000000000000..202bd1bbb207 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/eeprom.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + """Platform-specific Eeprom class""" + + def __init__(self, bus=1, loc="0056", config=None, iom_eeprom=False): + + if config: + bus = config.get("bus") + loc = config.get("loc") + + if bus and loc: + self.__eeprom_path = "/sys/bus/i2c/devices/{}-{}/eeprom".format(bus, loc) + else: + raise ValueError( + "Eeprom location error, bus: {}, loc: {}, config: {}".format( + bus, loc, config + ) + ) + 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-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan.py new file mode 100644 index 000000000000..bd0ab73ab4ef --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python + +import json +import math +import os.path +import time + +try: + from sonic_platform_base.fan_base import FanBase + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_NAME_LIST = ["Fan1", "Fan2"] + +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 + self.redfish = Redfish_Api() + pinf = self.redfish.get_thermal() + self._fan_list = [] + FanBase.__init__(self) + self.begin = time.time() + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_speed_pwm(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + speed = output.get("Oem").get("Ragile").get("FanSpeedLevelPercents") + return int(speed) + + def get_speed_rpm(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + speed = output.get("Reading") + return int(speed) + + def get_high_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + high = output.get("UpperThresholdFatal") + return int(high) + + def get_low_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + low = output.get("LowerThresholdFatal") + return int(low) + + def set_speed_pwm(self, speed): + post_url = '/redfish/v1/Chassis/1/Thermal/Actions/Oem/Ragile/Fan.SetSpeed' + playload = {} + playload["FanName"] = "Fan0" + playload["FanSpeedLevelPercents"] = str(speed) + return self.redfish.post_odata(post_url, playload) + + def get_status_led(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + led = output.get("Oem").get("Ragile").get("IndicatorLEDColor") + return led + + def set_status_led(self, color): + playload = {} + led = {} + led_list = [] + led["IndicatorLEDColor"] = color + led["LEDType"] = "fan" + led_list.append(led) + playload["LEDs"] = led_list + # boardsLed + return self.redfish.post_boardLed(playload) + + def get_direction(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + airflow = output.get("Oem").get("Ragile").get("AirFlow") + return airflow + + def get_name(self): + fan_name = FAN_NAME_LIST[self.fan_index] + return "Fantray{}_{}".format(self.fan_tray_index, fan_name) + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + if output.get("Status").get("Status").get("State") == "Enabled": + return True + return False + + def get_status(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + if output.get("Status").get("Status").get("Health") == "OK": + return True + return False + + def get_high_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + high = output.get("UpperThresholdFatal") + return high + + def get_low_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + low = output.get("LowerThresholdFatal") + return low + + def get_speed(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fan_index] + speed = output.get("Oem").get("Ragile").get("FanSpeedLevelPercents") + return speed diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan_drawer.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan_drawer.py new file mode 100755 index 000000000000..9db554d0d195 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/fan_drawer.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import json +import math +import os.path +import time + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(FanDrawerBase): + + FANS_PER_FANTRAY = 2 + + def __init__(self, fantray_index=0): + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + self.redfish = Redfish_Api() + pinf = self.redfish.get_thermal() + self.begin = time.time() + for i in range(self.FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_name(self): + return "FanTray{}".format(self.fantrayindex) + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fantrayindex] + if output.get("Status").get("Status").get("State") == "Enabled": + return True + + def get_status(self): + self.get_power_3s() + ctrl = self.pinf["Fans"] + output = ctrl[self.fantrayindex] + if output.get("Status").get("Status").get("Health") == "OK": + return True + + def set_status_led(self, color): + playload = {} + led = {} + led_list = [] + led["IndicatorLEDColor"] = color + led["LEDType"] = "fan" + led_list.append(led) + playload["LEDs"] = led_list + # boardsLed + return self.redfish.post_boardLed(playload) + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/hwaccess.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/hwaccess.py new file mode 100755 index 000000000000..595514c07de4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/hwaccess.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import os +import struct +import mmap +import subprocess + +# Read PCI device + +def pci_mem_read(mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + return struct.unpack('I',read_data_stream)[0] + +def pci_get_value(resource, offset): + with open(resource, 'r+b') as fd: + mm = mmap.mmap(fd.fileno(), 0) + val = pci_mem_read(mm, offset) + mm.close() + return val + +def pci_mem_write(memmap, offset, data): + """ Write PCI device """ + memmap.seek(offset) + memmap.write(struct.pack('I', data)) + +def pci_set_value(resource, val, offset): + """ Set a value to PCI device """ + with open(resource, 'w+b') as filed: + memmap = None + try: + memmap = mmap.mmap(filed.fileno(), 0) + pci_mem_write(memmap, offset, val) + except EnvironmentError: + pass + if memmap is not None: + memmap.close() + +# Read I2C device + +def i2c_get(bus, i2caddr, ofs): + try: + valx = int(subprocess.check_output(['/usr/sbin/i2cget','-f', '-y', str(bus), str(i2caddr), str(ofs)]), 16) + return "{:02x}".format(valx) + except (FileNotFoundError, subprocess.CalledProcessError): + return -1 + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/platform.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/platform.py new file mode 100644 index 000000000000..7225a71b0307 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/platform.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +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-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/psu.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/psu.py new file mode 100644 index 000000000000..c5fc3b163854 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/psu.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +import time +import imp +import os + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common import device_info + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, index=0): + PsuBase.__init__(self) + self.redfish = Redfish_Api() + pinf = self.redfish.get_power() + self.psu_index = index + self._fan_list = [] + self._thermal_list = [] + self.begin = time.time() + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_power() + self.begin = time.time() + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + if output.get("Status").get("State") == "Enabled": + return True + else: + return False + + def get_powergood_status(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + if output.get("Status").get("Health") == "OK": + return True + else: + return False + + def get_serial(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + serial = output.get("SerialNumber") + return serial + + def get_model(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + model = output.get("Model") + return model + + def get_revision(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + manufacturer = output.get("Manufacturer") + return manufacturer + + def get_voltage(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + voltage = output.get("Oem").get("Ragile").get("OutputVoltage") + return voltage + + def get_input_current(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + current = output.get("Oem").get("Ragile").get("OutputAmperage") + return current + + def get_input_voltage(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + voltage = output.get("Oem").get("Ragile").get("OutputVoltage") + return voltage + + def get_current(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + current = output.get("Oem").get("Ragile").get("OutputAmperage") + return current + + def get_power(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + current = output.get("Oem").get("Ragile").get("OutputAmperage") + voltage = output.get("Oem").get("Ragile").get("OutputVoltage") + power = float(current)*float(voltage) + return power + + def get_temperature(self): + return None + + def get_status_led(self): + self.get_power_3s() + ctrl = self.pinf["PowerSupplies"] + output = ctrl[self.psu_index] + led = output.get("Oem").get("Ragile").get("IndicatorLEDColor") + return led + + def set_status_led(self, color): + playload = {} + led = {} + led_list = [] + led["IndicatorLEDColor"] = color + led["LEDType"] = "pwr" + led_list.append(led) + playload["LEDs"] = led_list + # boardsLed + return self.redfish.post_boardLed(playload) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/redfish_api.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/redfish_api.py new file mode 100755 index 000000000000..d0d9927d0690 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/redfish_api.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import sys +import json +import traceback +import datetime +import os +import ssl +import subprocess +import syslog + +class Redfish_Api(): + BmcBaseUrl = 'http://240.1.1.1:8080' + ThermalUrl = '/redfish/v1/Chassis/1/Thermal' + PowerUrl = '/redfish/v1/Chassis/1/Power' + ThresholdSensorsUrl = '/redfish/v1/Chassis/1/ThresholdSensors' + FanSpeedUrl = '/redfish/v1/Chassis/1/Thermal/Actions/Oem/Ragile/Fan.SetSpeed' + BoardsUrl = '/redfish/v1/Chassis/1/Boards/' + BoardLedUrl = "/redfish/v1/Chassis/1/Boards/{}/Actions/Oem/Ragile/Boards.SetLED" + + # Maximum time in seconds that you allow the connection to the server to take. + connect_timeout = 30 + # Maximum time in seconds that you allow the whole operation to take + operation_timeout = 300 + + default_prefix='/redfish/v1/' + session = None + __DEBUG__ = "N" + __DUMP_RESP__ = "N" + RST_STATUS = "status" + RST_SUCCESS = "OK" + refish_logger = None + + def redfish_log_debug(self, msg): + if (self.__DEBUG__ == "Y"): + syslog.openlog("redfis_api") + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + def redfish_log_error(self, msg): + syslog.openlog("redfish_api") + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + def __init__(self): + pass + + def get_full_url(self, url): + return self.BmcBaseUrl + url + + def _exec_cmd(self, cmd): + self.redfish_log_debug("Cmd: %s" % cmd) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p.wait() + self.redfish_log_debug("Cmd return: %d" % p.returncode) + str_stdout = p.stdout.read().decode('utf-8') + str_stderr = p.stderr.read().decode('utf-8') + self.redfish_log_debug("Cmd stdout: %s" % str_stdout) + if p.returncode !=0: + self.redfish_log_error("Cmd: %s, failed! error msg:%s" % (cmd, str_stderr)) + return None + else: + try: + ret = json.loads(str_stdout) + return ret + except Exception as e: + self.redfish_log_error("Cmd: %s, failed! stdout msg:%s" % (cmd, str_stdout)) + return None + + def _redfish_get(self, url): + self.redfish_log_debug("Get info from %s." % url) + result = None + try: + cmd_get="curl --connect-timeout %d -m %d -X GET %s" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url)) + result = self._exec_cmd(cmd_get) + except Exception as e: + self.redfish_log_error("error_message: %s" % e) + result = None + finally: + return result + + def _redfish_post(self, url, playload): + self.redfish_log_debug("post url: %s" % url) + self.redfish_log_debug("Playload: %s" % playload) + + playload_json = json.dumps(playload) + result = False + try: + cmd_post="curl --connect-timeout %d -m %d -X POST %s -d \'%s\'" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url), playload_json) + ret_msg = self._exec_cmd(cmd_post) + if ret_msg == None: + return False + elif ret_msg["success"] == False: + redfish_log_error("Url: '%s', Playload: '%s', Bmc return failed, error_message: %s" % (url, playload_json, ret_msg["Message"])) + result = False + else: + result = True + except Exception as e: + redfish_log_error("error_message: %s" % e) + result = False + finally: + return result + + def get_thermal(self): + """Get thermal info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.ThermalUrl) + + def get_power(self): + """Get power info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.PowerUrl) + + def get_thresholdSensors(self): + """Get thresholdSensors info + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.ThresholdSensorsUrl) + + def post_odata(self, odata_id, playload): + """post odata info + :params odata_id: the specified odata_id path + :type odata_id: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if odata_id is None or playload is None: + print("post failed: odata_id or playload is None") + return False + return self._redfish_post(odata_id, playload) + + def get_odata(self, odata_id): + """Get odata info + :params odata_id: the specified odata_id path + :type odata_id: string + :returns: class 'redfish.rest.v1.RestResponse' or None when failed + """ + if odata_id is None: + print("Get odata_id failed: odata_id is None") + return None + return self._redfish_get(odata_id) + + def post_fanSpeed(self, playload): + """post odata info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.FanSpeedUrl, playload) + + def get_board(self, board_name="indicatorboard"): + """Get board info + :board_name: name of board, default is "indicatorboard" + :type: string + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + if board_name is None : + print("get failed: board_name is None") + return None + return self._redfish_get(self.BoardsUrl + board_name) + + def post_boardLed(self, playload, board_name="indicatorboard"): + """post boardLed info + :board_name: name of board, default is "indicatorboard" + :type: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if board_name is None or playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.BoardLedUrl.format(board_name), playload) + + ''' not supported currently + def post_thermal(self, playload): + """post thermal info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_thermal failed: playload is None") + return None + return self._redfish_post(self.ThermalUrl, playload) + + def post_power(self, playload): + """post power info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_power failed: playload is None") + return None + return self._redfish_post(self.PowerUrl, playload) + + def post_thresholdSensors(self, playload): + """post thresholdSensors info + :playload: info to post + :type: dictionary + :returns: True or False + """ + if playload is None: + print("post_thresholdSensors failed: playload is None") + return None + return self._redfish_post(self.ThresholdSensorsUrl, playload) + + def get_fanSpeed(self): + """Get board led info + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + return self._redfish_get(self.FanSpeedUrl) + + def post_board(self, playload, board_name="indicatorboard"): + """post board info + :board_name: name of board, default is "indicatorboard" + :type: string + :playload: info to post + :type: dictionary + :returns: True or False + """ + if board_name is None or playload is None: + print("post failed: playload is None") + return False + return self._redfish_post(self.BoardsUrl + board_name, playload) + + def get_boardLed(self, board_name="indicatorboard"): + """Get boardLed info + :board_name: name of board, default is "indicatorboard" + :type: string + :returns: class'redfish.rest.v1.RestResponse' or None when failed + """ + if board_name is None : + print("get failed: board_name is None") + return None + return self._redfish_get(self.BoardsUrl % board_name) + + ''' + +''' +if __name__ == '__main__': + redfish = Redfish_Api() + + ### get + # boards + ret = redfish.get_board() + if ret is None: + print("get failed: board") + else: + print("get succeeded, board:%s" % ret) + + ret = redfish.get_thresholdSensors() + if ret is None: + print("get failed: threshold") + else: + print("get succeeded, threshold:%s" % ret) + + ret = redfish.get_power() + if ret is None: + print("get failed: power") + else: + print("get succeeded, power:%s" % ret) + + ret = redfish.get_thermal() + if ret is None: + print("get failed:thermal") + else: + print("get succeeded,thermal:%s" % ret) + + # get playload + resp = redfish.get_thresholdSensors() + if (resp != None): + print(resp["@odata.id"]) + print(resp["@odata.type"]) + print(resp["Id"]) + print(resp["Name"]) + else: + print("Failed: get_thresholdSensors") + + ### post + # fanSpeed + playload = {} + playload["FanName"] = 'Fan0' + playload["FanSpeedLevelPercents"] = "70" + print("post fanSpeed:%s" % redfish.post_fanSpeed(playload)) + + #{"LEDs": [{"IndicatorLEDColor": "green","LEDType": "sys"},{"IndicatorLEDColor": "off","LEDType": "pwr"},{"IndicatorLEDColor": "green","LEDType": "fan"}]} + playload = {} + led = {} + led1 = {} + led_list = [] + led["IndicatorLEDColor"] = "green" + led["LEDType"] = "sys" + led1["IndicatorLEDColor"] = "off" + led1["LEDType"] = "pwr" + led_list.append(led) + led_list.append(led1) + playload["LEDs"] = led_list + # boardsLed + print("post boardLed:%s" % redfish.post_boardLed(playload)) +''' \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/sfp.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/sfp.py new file mode 100644 index 000000000000..f814b571749a --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/sfp.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import time +import imp +import os + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Sfp(SfpBase): + """ + Platform-specific sfp class + + Unimplemented methods: + - get_model + - get_serial + - get_status + - get_transceiver_info + - get_transceiver_bulk_status + - get_transceiver_threshold_info + - get_reset_status + - get_rx_los + - get_tx_fault + - get_tx_disable_channel + - get_power_override + - get_temperature + - get_voltage + - get_tx_bias + - get_rx_power + - get_tx_power + - tx_disable_channel + - set_power_override + """ + + def __init__(self, index): + self._index = index + self._thermal_list = [] + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "sfputil.py"]) + module = imp.load_source("sfputil", module_file) + sfp_util_class = getattr(module, "SfpUtil") + self._sfputil = sfp_util_class() + + def get_id(self): + return self._index + + def get_name(self): + return "Ethernet{}".format(self._index - 1) + + def get_lpmode(self): + return False + + def set_lpmode(self, lpmode): + return False + + def get_tx_disable(self): + return False + + def tx_disable(self, tx_disable): + return False + + def reset(self): + pass + + def clear_interrupt(self): + return False + + def get_interrupt_file(self): + return None + + def _get_sfputil(self): + return self._sfputil + + def get_presence(self): + return self._get_sfputil().get_presence(self._index) + + def get_transceiver_info(self): + # temporary solution for a sonic202111 bug + transceiver_info = self._get_sfputil().get_transceiver_info_dict(self._index) + if transceiver_info.get("vendor_rev", None) is None: + transceiver_info["vendor_rev"] = transceiver_info["hardware_rev"] + return transceiver_info + + def get_transceiver_bulk_status(self): + return self._get_sfputil().get_transceiver_dom_info_dict(self._index) + + def get_transceiver_threshold_info(self): + return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index) + + def get_transceiver_change_event(self, timeout): + return self._get_sfputil().get_transceiver_change_event(timeout) diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/thermal.py b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/thermal.py new file mode 100644 index 000000000000..e768d3ca1187 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/ra-b6010-48gt4x/sonic_platform/thermal.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +import os +import re +import os.path +import time + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .redfish_api import Redfish_Api +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, thermal_index): + ThermalBase.__init__(self) + self.index = thermal_index + self.high_threshold = float(112) + self.redfish = Redfish_Api() + pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_power_3s(self): + self.elapsed = time.time() + if self.elapsed - self.begin < 3: + pass + else: + self.pinf = self.redfish.get_thermal() + self.begin = time.time() + + def get_temperature(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("ReadingCelsius") + return temp + + def get_high_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("UpperThresholdFatal") + return temp + + def get_low_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("LowerThresholdFatal") + return temp + + def get_high_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("UpperThresholdFatal") + return temp + + def get_low_critical_threshold(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + temp = output.get("LowerThresholdFatal") + return temp + + def get_name(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index].get("Name") + name = output.split("/",3)[2] + return "{}".format(name) + + def get_presence(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + if output.get("Status").get("Status").get("State") == "Enabled": + return True + + def get_status(self): + self.get_power_3s() + ctrl = self.pinf["Temperatures"] + output = ctrl[self.index] + if output.get("Status").get("Health") == "OK": + return True diff --git a/platform/centec-arm64/sonic_fit.its b/platform/centec-arm64/sonic_fit.its index 0f96550c88f7..1cf2b959870c 100644 --- a/platform/centec-arm64/sonic_fit.its +++ b/platform/centec-arm64/sonic_fit.its @@ -48,6 +48,18 @@ algo = "crc32"; }; }; + ctc_fdtb6010 { + description = "dtb for ra-b6010-48gt4x-r0"; + data = /incbin/("./ra-b6010-48gt4x-r0.dtb"); + type = "flat_dt"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x88000000>; + hash { + algo = "crc32"; + }; + }; }; configurations { default = "arm64-centec_e530_24x2c-r0"; @@ -86,5 +98,18 @@ ramdisk = "initramfs"; fdt = "ctc_fdt"; }; + arm64-ragile_ra-b6010-48gt4x-r0 { + description = "config for ragile_ra-b6010-48gt4x"; + kernel = "kernel_ctc"; + ramdisk = "initramfs"; + fdt = "ctc_fdtb6010"; + }; + arm64-ragile_ra-b6010-48gt4x-r-r0 { + description = "config for ragile_ra-b6010-48gt4x-r"; + kernel = "kernel_ctc"; + ramdisk = "initramfs"; + fdt = "ctc_fdtb6010"; + }; + }; }; }; From 736c2aefd9939fbefbaf94b1e5bfb8965b850fad Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Fri, 6 Jan 2023 21:11:46 +0800 Subject: [PATCH 02/13] Update azure-pipelines.yml --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f1004ab709d1..e8a58879e927 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -66,6 +66,7 @@ stages: swi_image: yes - name: mellanox - name: marvell-armhf + - name: centec-arm64 pool: sonicbld-armhf timeoutInMinutes: 1200 variables: From 307217e8fdea8d6e9662e46bb4410f17d07e3159 Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Fri, 6 Jan 2023 21:21:32 +0800 Subject: [PATCH 03/13] Update azure-pipelines.yml --- azure-pipelines.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e8a58879e927..c26982ae926a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -61,11 +61,6 @@ stages: parameters: buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}' jobGroups: - - name: broadcom - variables: - swi_image: yes - - name: mellanox - - name: marvell-armhf - name: centec-arm64 pool: sonicbld-armhf timeoutInMinutes: 1200 From 66a1f34e802553817fbad1fc1902282ead5f4447 Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Fri, 6 Jan 2023 22:01:39 +0800 Subject: [PATCH 04/13] Update azure-pipelines.yml --- azure-pipelines.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c26982ae926a..7880f5b9ebb0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -62,10 +62,6 @@ stages: buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}' jobGroups: - name: centec-arm64 - pool: sonicbld-armhf - timeoutInMinutes: 1200 - variables: - PLATFORM_ARCH: armhf - stage: Test dependsOn: BuildVS From 75e5c258f71615071f0b4d014f80208c29920852 Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Fri, 6 Jan 2023 22:12:54 +0800 Subject: [PATCH 05/13] Update azure-pipelines.yml --- azure-pipelines.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7880f5b9ebb0..e4eec1d42e71 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -62,6 +62,8 @@ stages: buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}' jobGroups: - name: centec-arm64 + variables: + PLATFORM_ARCH: arm64 - stage: Test dependsOn: BuildVS From 9756d2599fa018d07b90a903242eb78ead434e0f Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Fri, 6 Jan 2023 22:29:04 +0800 Subject: [PATCH 06/13] Update azure-pipelines.yml --- azure-pipelines.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e4eec1d42e71..074a805c83c3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -62,6 +62,8 @@ stages: buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}' jobGroups: - name: centec-arm64 + pool: sonicbld-arm64 + timeoutInMinutes: 1200 variables: PLATFORM_ARCH: arm64 From c765b1716fd7c1f04b3b61689a67abbc5d505bba Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Fri, 6 Jan 2023 23:23:08 +0800 Subject: [PATCH 07/13] Update azure-pipelines.yml --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 074a805c83c3..a54697a12c4d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -49,7 +49,7 @@ stages: jobs: - template: .azure-pipelines/azure-pipelines-build.yml parameters: - buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) BUILD_MULTIASIC_KVM=y ${{ variables.VERSION_CONTROL_OPTIONS }}' + buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) BUILD_MULTIASIC_KVM=y ' jobGroups: - name: vs @@ -59,7 +59,7 @@ stages: jobs: - template: .azure-pipelines/azure-pipelines-build.yml parameters: - buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc) ${{ variables.VERSION_CONTROL_OPTIONS }}' + buildOptions: 'USERNAME=admin SONIC_BUILD_JOBS=$(nproc)' jobGroups: - name: centec-arm64 pool: sonicbld-arm64 From 3e361e3e9d1dcf04dc04fef70c19cd433f291a4f Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Sat, 7 Jan 2023 09:11:53 +0800 Subject: [PATCH 08/13] Update sai.mk --- platform/centec-arm64/sai.mk | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk index 032c4916314a..c4f3ce6f4d8f 100755 --- a/platform/centec-arm64/sai.mk +++ b/platform/centec-arm64/sai.mk @@ -2,11 +2,9 @@ export CENTEC_SAI_VERSION = 1.10.2-1 export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb -export CENTEC_SAI_DEV = libsai-dev_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb -$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sai-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) -$(CENTEC_SAI_DEV)_URL = https://github.com/CentecNetworks/sai-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI_DEV) -$(eval $(call add_conflict_package,$(CENTEC_SAI_DEV),$(LIBSAIVS_DEV))) +$(CENTEC_SAI)_URL = https://github.com/pettershao-ragilenetworks/sonic-binaries/blob/main/centec-arm64/sai/libsai_1.10.2-1_arm64.deb + SONIC_ONLINE_DEBS += $(CENTEC_SAI) -SONIC_ONLINE_DEBS += $(CENTEC_SAI_DEV) + From 8e631076186dbe1bddc2eae32c979859f77b71e2 Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Sat, 7 Jan 2023 11:38:49 +0800 Subject: [PATCH 09/13] Update sai.mk --- platform/centec-arm64/sai.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk index c4f3ce6f4d8f..b5dd234a3ff2 100755 --- a/platform/centec-arm64/sai.mk +++ b/platform/centec-arm64/sai.mk @@ -3,8 +3,8 @@ export CENTEC_SAI_VERSION = 1.10.2-1 export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb -$(CENTEC_SAI)_URL = https://github.com/pettershao-ragilenetworks/sonic-binaries/blob/main/centec-arm64/sai/libsai_1.10.2-1_arm64.deb - +$(CENTEC_SAI)_URL = https://github.com/pettershao-ragilenetworks/sonic-binaries/raw/main/centec-arm64/sai/libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb +$(CENTEC_SAI)_DEPENDS += $(LIBNL3) $(LIBNL3_DEV) $(LIBNL_GENL3) $(LIBNL_GENL3_DEV) SONIC_ONLINE_DEBS += $(CENTEC_SAI) From 26454624256e20d55857d719d11ec64fbbf5c154 Mon Sep 17 00:00:00 2001 From: pettershao-ragilenetworks <81281940+pettershao-ragilenetworks@users.noreply.github.com> Date: Sat, 7 Jan 2023 16:18:10 +0800 Subject: [PATCH 10/13] Update sai.mk --- platform/centec-arm64/sai.mk | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk index b5dd234a3ff2..d53943972eca 100755 --- a/platform/centec-arm64/sai.mk +++ b/platform/centec-arm64/sai.mk @@ -1,10 +1,11 @@ -# Centec SAI - -export CENTEC_SAI_VERSION = 1.10.2-1 +export CENTEC_SAI_VERSION = 1.11.0-1 export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb +export CENTEC_SAI_DEV = libsai-dev_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb -$(CENTEC_SAI)_URL = https://github.com/pettershao-ragilenetworks/sonic-binaries/raw/main/centec-arm64/sai/libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb -$(CENTEC_SAI)_DEPENDS += $(LIBNL3) $(LIBNL3_DEV) $(LIBNL_GENL3) $(LIBNL_GENL3_DEV) +$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) +$(CENTEC_SAI_DEV)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI_DEV) +$(eval $(call add_conflict_package,$(CENTEC_SAI_DEV),$(LIBSAIVS_DEV))) SONIC_ONLINE_DEBS += $(CENTEC_SAI) +SONIC_ONLINE_DEBS += $(CENTEC_SAI_DEV) From 5abf417069928a98db1ea17bd74547f1afa4f845 Mon Sep 17 00:00:00 2001 From: panyi Date: Sat, 7 Jan 2023 22:27:53 +0800 Subject: [PATCH 11/13] add debian floder --- .gitignore | 2 +- .../debian/changelog | 6 + .../debian/compat | 1 + .../debian/control | 14 +++ .../platform-modules-ra-b6010-48gt4x-r.init | 60 +++++++++ ...platform-modules-ra-b6010-48gt4x-r.install | 2 + ...latform-modules-ra-b6010-48gt4x-r.postinst | 6 + .../platform-modules-ra-b6010-48gt4x.init | 60 +++++++++ .../platform-modules-ra-b6010-48gt4x.install | 2 + .../platform-modules-ra-b6010-48gt4x.postinst | 6 + .../debian/rules | 114 ++++++++++++++++++ 11 files changed, 272 insertions(+), 1 deletion(-) create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/debian/changelog create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/compat create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/control create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.init create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.install create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.postinst create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.init create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.install create mode 100644 platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.postinst create mode 100755 platform/centec-arm64/sonic-platform-modules-ragile/debian/rules diff --git a/.gitignore b/.gitignore index 60c328d62289..090389701ba4 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,7 @@ src/**/*.o platform/**/*.egg-info platform/**/*-none-any.whl platform/**/.pybuild -platform/**/debian/* +#platform/**/debian/* platform/**/build platform/**/*.ko platform/**/*.mod.c diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/changelog b/platform/centec-arm64/sonic-platform-modules-ragile/debian/changelog new file mode 100755 index 000000000000..4cbb334fd2d9 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/changelog @@ -0,0 +1,6 @@ +sonic-centec-platform-modules (1.3) unstable; urgency=low + + * Add support for ragile ra-b6010-48gt4x + + -- sonic_rd Mon, 21 Sep 2020 13:34:33 +0800 + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/compat b/platform/centec-arm64/sonic-platform-modules-ragile/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/control b/platform/centec-arm64/sonic-platform-modules-ragile/debian/control new file mode 100644 index 000000000000..98ee5c80b8ab --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/control @@ -0,0 +1,14 @@ +Source: sonic-centec-platform-modules +Section: main +Priority: extra +Maintainer: shil +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-ra-b6010-48gt4x +Architecture: arm64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-ra-b6010-48gt4x-r +Architecture: arm64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.init b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.init new file mode 100644 index 000000000000..f18075f3df78 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.init @@ -0,0 +1,60 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +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 + echo -n "Install sonic_platform-1.0-py3-none-any.whl ..." + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} + +function load_kernel_modules() +{ + hwaddr=`fw_printenv ethaddr | awk -F = '{print $2}'` + if [ "$hwaddr" != "" ]; then + ifconfig eth0 hw ether $hwaddr + fi + depmod -a + modprobe dal +} + +function remove_kernel_modules() +{ + modprobe -r dal +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + install_python_api_package + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ra-b6010-48gt4x-r {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.install b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.install new file mode 100644 index 000000000000..967666c58a85 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.install @@ -0,0 +1,2 @@ +ra-b6010-48gt4x-r/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-ragile_ra-b6010-48gt4x-r-r0 + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.postinst b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.postinst new file mode 100644 index 000000000000..c6c9512ef85a --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x-r.postinst @@ -0,0 +1,6 @@ +systemctl enable ra-b6010-48gt4x-r_platform.service +systemctl start ra-b6010-48gt4x-r_platform.service +systemctl enable device_i2c.service +systemctl start device_i2c.service +systemctl enable privatenetwork.service +systemctl start privatenetwork.service diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.init b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.init new file mode 100644 index 000000000000..2a7badcbb04e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.init @@ -0,0 +1,60 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +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 + echo -n "Install sonic_platform-1.0-py3-none-any.whl ..." + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} + +function load_kernel_modules() +{ + hwaddr=`fw_printenv ethaddr | awk -F = '{print $2}'` + if [ "$hwaddr" != "" ]; then + ifconfig eth0 hw ether $hwaddr + fi + depmod -a + modprobe dal +} + +function remove_kernel_modules() +{ + modprobe -r dal +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + install_python_api_package + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ra-b6010-48gt4x {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.install b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.install new file mode 100644 index 000000000000..3ad193101a7d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.install @@ -0,0 +1,2 @@ +ra-b6010-48gt4x/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-ragile_ra-b6010-48gt4x-r0 + diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.postinst b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.postinst new file mode 100644 index 000000000000..a0eb2d1fc43e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/platform-modules-ra-b6010-48gt4x.postinst @@ -0,0 +1,6 @@ +systemctl enable ra-b6010-48gt4x_platform.service +systemctl start ra-b6010-48gt4x_platform.service +systemctl enable device_i2c.service +systemctl start device_i2c.service +systemctl enable privatenetwork.service +systemctl start privatenetwork.service diff --git a/platform/centec-arm64/sonic-platform-modules-ragile/debian/rules b/platform/centec-arm64/sonic-platform-modules-ragile/debian/rules new file mode 100755 index 000000000000..ffaf8a1d7172 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-ragile/debian/rules @@ -0,0 +1,114 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON = python3.9 + +PACKAGE_PRE_NAME := platform-modules +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ra-b6010-48gt4x +MODULE_DIRS_R:= ra-b6010-48gt4x-r +MODULE_DIR := common +CUSTOMS_DIRS := common_custom/common_ragile +SERVICE_DIR := service +CLASSES_DIR := classes +CONFIG_DIR := config +KDAL_DIR := ../../centec/centec-dal/ +export KERNEL_SRC + + + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(KDAL_DIR); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/; \ + done) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + cd $${mod}; $(PYTHON) setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd -; \ + done) + (for mod in $(MODULE_DIRS_R); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + cd $${mod}; $(PYTHON) setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd -; \ + done) + make -C $(MODULE_DIR); + make -C $(CUSTOMS_DIRS); + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} boot; \ + cp -r $(MOD_SRC_DIR)/$(MODULE_DIR)/build/* debian/$(PACKAGE_PRE_NAME)-$${mod}/; \ + cp -r $(MOD_SRC_DIR)/$(CUSTOMS_DIRS)/build/* debian/$(PACKAGE_PRE_NAME)-$${mod}/; \ + cp $(MOD_SRC_DIR)/$${mod}/config/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$(KDAL_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + cp $(MOD_SRC_DIR)/${CONFIG_DIR}/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/; \ + cd -; \ + done) + (for mod in $(MODULE_DIRS_R); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} boot; \ + cp -r $(MOD_SRC_DIR)/$(MODULE_DIR)/build/* debian/$(PACKAGE_PRE_NAME)-$${mod}/; \ + cp -r $(MOD_SRC_DIR)/$(CUSTOMS_DIRS)/build/* debian/$(PACKAGE_PRE_NAME)-$${mod}/; \ + cp $(MOD_SRC_DIR)/$${mod}/config/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$(KDAL_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + cp $(MOD_SRC_DIR)/${CONFIG_DIR}/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/; \ + cd -; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean From 15c25f25c90dc63add7434fd1642d52dd1bfd634 Mon Sep 17 00:00:00 2001 From: panyi Date: Sun, 8 Jan 2023 12:22:55 +0800 Subject: [PATCH 12/13] add platform_asic file --- device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/platform_asic | 1 + 1 file changed, 1 insertion(+) create mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/platform_asic diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/platform_asic b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/platform_asic new file mode 100644 index 000000000000..0815c8a78c0b --- /dev/null +++ b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/platform_asic @@ -0,0 +1 @@ +centec-arm64 From 282bca1de2a0ad683bded0c51c7db6caf5fb1d14 Mon Sep 17 00:00:00 2001 From: panyi Date: Mon, 9 Jan 2023 21:53:39 +0800 Subject: [PATCH 13/13] update tsingma --- .../RA-b6010-48gt4x-board.json | 868 ------------------ .../RA-b6010-48gt4x-p-chip-profile.txt | 96 -- .../RA-b6010-48gt4x-p-datapath.txt | 281 ------ .../RA-B6010-48GT4X/default_sku | 1 - .../RA-B6010-48GT4X/phy_mapping.cfg | 198 ---- .../RA-B6010-48GT4X/port_config.ini | 53 -- .../RA-B6010-48GT4X/sai.profile | 4 - .../RA-B6010-48GT4X/start_up.cfg | 48 - .../default_sku | 1 - .../installer.conf | 9 - .../plugins/config.py | 22 - .../plugins/eeprom.py | 21 - .../plugins/sfputil.py | 455 --------- .../pmon_daemon_control.json | 7 - dockers/docker-platform-monitor/Dockerfile.j2 | 3 + files/build_scripts/mask_disabled_services.py | 14 +- files/image_config/platform/rc.local | 2 +- platform/centec-arm64/one-image.mk | 2 +- platform/centec-arm64/sai.mk | 7 +- .../centec-arm64/tsingma-bsp/debian/rules | 2 + .../tsingma-bsp/debian/tsingma-bsp.install | 1 + .../tsingma-bsp/src/ra-b6010-48gt4x/Makefile | 5 + .../tsingma-bsp/src/ra-b6010-48gt4x/arm-gic.h | 23 + .../src/ra-b6010-48gt4x/ctc5236-clks.h | 25 + .../src/ra-b6010-48gt4x/ctc5236-clock.dtsi | 63 ++ .../src/ra-b6010-48gt4x/ctc5236.dtsi | 428 +++++++++ .../tsingma-bsp/src/ra-b6010-48gt4x/irq.h | 20 + .../ra-b6010-48gt4x/ra-b6010-48gt4x-r0.dts | 333 +++++++ rules/isc-dhcp.mk | 2 +- src/dhcpmon/src/dhcp_device.cpp | 316 ++++--- src/dhcpmon/src/dhcp_device.h | 8 +- src/dhcpmon/src/dhcp_mon.cpp | 2 +- 32 files changed, 1107 insertions(+), 2213 deletions(-) delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py delete mode 100644 device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json create mode 100755 platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/Makefile create mode 100755 platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/arm-gic.h create mode 100755 platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clks.h create mode 100755 platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clock.dtsi create mode 100755 platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236.dtsi create mode 100755 platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/irq.h create mode 100755 platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ra-b6010-48gt4x-r0.dts diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json deleted file mode 100644 index 80fb22238078..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-board.json +++ /dev/null @@ -1,868 +0,0 @@ -{ - "macleds" : { - "polarity" : 1, - "freq" : 2500, - "interval" : 50000000, - "maps" : [ - { - "port_id" : 0, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port1/brightness" - }, - { - "port_id" : 1, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port2/brightness" - }, - { - "port_id" : 2, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port3/brightness" - }, - { - "port_id" : 3, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port4/brightness" - }, - { - "port_id" : 4, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port5/brightness" - }, - { - "port_id" : 5, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port6/brightness" - }, - { - "port_id" : 6, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port7/brightness" - }, - { - "port_id" : 7, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port8/brightness" - }, - { - "port_id" : 16, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port9/brightness" - }, - { - "port_id" : 17, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port10/brightness" - }, - { - "port_id" : 18, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port11/brightness" - }, - { - "port_id" : 19, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port12/brightness" - }, - { - "port_id" : 20, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port13/brightness" - }, - { - "port_id" : 21, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port14/brightness" - }, - { - "port_id" : 22, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port15/brightness" - }, - { - "port_id" : 23, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port16/brightness" - }, - { - "port_id" : 8, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port17/brightness" - }, - { - "port_id" : 9, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port18/brightness" - }, - { - "port_id" : 10, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port19/brightness" - }, - { - "port_id" : 11, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port20/brightness" - }, - { - "port_id" : 32, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port21/brightness" - }, - { - "port_id" : 33, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port22/brightness" - }, - { - "port_id" : 34, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port23/brightness" - }, - { - "port_id" : 35, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port24/brightness" - }, - { - "port_id" : 36, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port25/brightness" - }, - { - "port_id" : 37, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port26/brightness" - }, - { - "port_id" : 38, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port27/brightness" - }, - { - "port_id" : 39, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port28/brightness" - }, - { - "port_id" : 40, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port29/brightness" - }, - { - "port_id" : 41, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port30/brightness" - }, - { - "port_id" : 42, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port31/brightness" - }, - { - "port_id" : 43, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port32/brightness" - }, - { - "port_id" : 24, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port33/brightness" - }, - { - "port_id" : 25, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port34/brightness" - }, - { - "port_id" : 26, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port35/brightness" - }, - { - "port_id" : 27, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port36/brightness" - }, - { - "port_id" : 48, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port37/brightness" - }, - { - "port_id" : 49, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port38/brightness" - }, - { - "port_id" : 50, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port39/brightness" - }, - { - "port_id" : 51, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port40/brightness" - }, - { - "port_id" : 52, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port41/brightness" - }, - { - "port_id" : 53, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port42/brightness" - }, - { - "port_id" : 54, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port43/brightness" - }, - { - "port_id" : 55, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port44/brightness" - }, - { - "port_id" : 56, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port45/brightness" - }, - { - "port_id" : 57, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port46/brightness" - }, - { - "port_id" : 58, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port47/brightness" - }, - { - "port_id" : 59, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port48/brightness" - }, - { - "port_id" : 12, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port49/brightness" - }, - { - "port_id" : 13, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port50/brightness" - }, - { - "port_id" : 14, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port51/brightness" - }, - { - "port_id" : 15, - "lchip" : 0, - "ctl_id" : 0, - "mode" : "LED_MODE_1_RXLNK_BIACT", - "fixed" : 0, - "sysfs_path" : "/sys/class/leds/port52/brightness" - } - ] - }, - "phys" : [ - { - "macid" : 0, - "busid" : 0, - "addr" : 0, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 1, - "busid" : 0, - "addr" : 1, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 2, - "busid" : 0, - "addr" : 2, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 3, - "busid" : 0, - "addr" : 3, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 4, - "busid" : 0, - "addr" : 4, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 5, - "busid" : 0, - "addr" : 5, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 6, - "busid" : 0, - "addr" : 6, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 7, - "busid" : 0, - "addr" : 7, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 16, - "busid" : 0, - "addr" : 8, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 17, - "busid" : 0, - "addr" : 9, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 18, - "busid" : 0, - "addr" : 10, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 19, - "busid" : 0, - "addr" : 11, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 20, - "busid" : 0, - "addr" : 12, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 21, - "busid" : 0, - "addr" : 13, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 22, - "busid" : 0, - "addr" : 14, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 23, - "busid" : 0, - "addr" : 15, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 8, - "busid" : 0, - "addr" : 16, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 9, - "busid" : 0, - "addr" : 17, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 10, - "busid" : 0, - "addr" : 18, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 11, - "busid" : 0, - "addr" : 19, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 32, - "busid" : 0, - "addr" : 20, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 33, - "busid" : 0, - "addr" : 21, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 34, - "busid" : 0, - "addr" : 22, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 35, - "busid" : 0, - "addr" : 23, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 36, - "busid" : 1, - "addr" : 0, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 37, - "busid" : 1, - "addr" : 1, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 38, - "busid" : 1, - "addr" : 2, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 39, - "busid" : 1, - "addr" : 3, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 40, - "busid" : 1, - "addr" : 4, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 41, - "busid" : 1, - "addr" : 5, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 42, - "busid" : 1, - "addr" : 6, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 43, - "busid" : 1, - "addr" : 7, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 24, - "busid" : 1, - "addr" : 8, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 25, - "busid" : 1, - "addr" : 9, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 26, - "busid" : 1, - "addr" : 10, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 27, - "busid" : 1, - "addr" : 11, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 48, - "busid" : 1, - "addr" : 12, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 49, - "busid" : 1, - "addr" : 13, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 50, - "busid" : 1, - "addr" : 14, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 51, - "busid" : 1, - "addr" : 15, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 52, - "busid" : 1, - "addr" : 16, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 53, - "busid" : 1, - "addr" : 17, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 54, - "busid" : 1, - "addr" : 18, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 55, - "busid" : 1, - "addr" : 19, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 56, - "busid" : 1, - "addr" : 20, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 57, - "busid" : 1, - "addr" : 21, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 58, - "busid" : 1, - "addr" : 22, - "base_port": 1, - "last_port": 4 - }, - { - "macid" : 59, - "busid" : 1, - "addr" : 23, - "base_port": 1, - "last_port": 4 - } - ], - "ffe" : { - "board_material" : "BOARD_MATERIAL_M4", - "config" : [ - { - "serdes_id" : [0], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 255, 10, 0] - }, - { - "serdes_id" : [1], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 240, 10, 0] - }, - { - "serdes_id" : [2], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 230, 10, 0] - }, - { - "serdes_id" : [3], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 220, 7, 0] - }, - { - "serdes_id" : [4], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 220, 8, 0] - }, - { - "serdes_id" : [5], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 210, 6, 0] - }, - { - "serdes_id" : [6], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 180, 6, 0] - }, - { - "serdes_id" : [7], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [0, 180, 5, 0] - }, - { - "serdes_id" : [8], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [2, 160, 4, 0] - }, - { - "serdes_id" : [9], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [2, 160, 4, 0] - }, - { - "serdes_id" : [10], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [3, 140, 9, 0] - }, - { - "serdes_id" : [11], - "is_dac" : 0, - "speed" : [1000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [3, 140, 5, 0] - }, - { - "serdes_id" : [12, 13, 14, 15], - "is_dac" : 0, - "speed" : [10000], - "mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE", - "cfg" : [3, 94, 15, 0] - } - ] - }, - "ctle" : { - "config" : [ - { - "serdes_id" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], - "auto-en" : 0, - "cfg" : [6, 14, 2] - } - ] - } -} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt deleted file mode 100644 index 2373e27f5f8b..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-chip-profile.txt +++ /dev/null @@ -1,96 +0,0 @@ -#----------------- 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] = 1; -[NPM_SUPPORT] = 1; -[DOT1AE_SUPPORT] = 1; - -#----------------- Chip Init Parameter -------------- -#Local chip number and global chip id -[Local chip_num] = 1 -[Local chip0] = 0 -[Local chip1] = 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 - -#----------------- Interrupt Init Parameter -------------- -#0: pin, 1: msi -[Interrupt_mode] = 0 -[IRQ] = 69 - -#----------------- 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 - -#----------------- L2 Init Parameter -------------- -[FDB Hw Learning] = 1 -[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_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 port queue number support 16/8/8 BPE/4 BPE, -#When resrc_profile.cfg exist, queue number valid, -#Default 8 queue mode -#8 queue = 8 -#16 queue = 16 -#4 queue BPE = 17 -#8 queue BPE = 18 -[QOS_PORT_QUEUE_NUM] = 8 -#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_POLICER_MERGE_MODE] = 0 -#QOS service queue mode, default 0,0:logic scr port + dstport enq 1:service id + dstport enq -[QOS_SERVICE_QUEUE_MODE] = 0 -#Global enable logic dst port + dstport enq -[QOS_SERVICE_QUEUE_EGRESS_EN] = 0 - -#----------------- Stacking Init Parameter -------------- -#0: normal mode; 1: spine-leaf mode -[FABRIC MODE] = 0 -[STACKING VERSION] = 1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt deleted file mode 100644 index 959b97a150cc..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/RA-b6010-48gt4x-p-datapath.txt +++ /dev/null @@ -1,281 +0,0 @@ -#Generated by 'CTC DataPath Tools' on Fri Dec 18 19:15:31 2020 -#Version 1.0, Supported by TsingMa SDK - - -#SERDES_MODE : 0-NONE, 1-XFI, 2-SGMII, 3-Not Support, 4-QSGMII, 5-XAUI, 6-DXAUI, 7-XLG, 8-CG, 9-SGMII2G5 -# 10-USXGMII-S, 11-USXGMII-M2G5, 12-USXGMII-M5G, 13-XXVG, 14-LG, 15-100BASE-FX -#SERDES_RX_POLY: 0-Normal, 1-Inverse -#SERDES_SWITCH : 0-Not Support Dynamic Switch, 1-Support Dynamic Switch - -[WLAN_ENABLE] = 1 -[DOT1AE_ENABLE] = 1 - -[CORE_PLLA] = 600 -#{ -[SERDES_ITEM] -#repeat 32 step 6 -[SERDES_ID] = 0 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 1 -[SERDES_TX_POLY] = 1 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 1 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 2 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 1 -[SERDES_TX_POLY] = 1 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 3 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 4 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 5 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 6 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 7 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 1 -[SERDES_TX_POLY] = 1 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 8 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 1 -[SERDES_TX_POLY] = 1 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 9 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 10 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 11 -[SERDES_MODE] = 4 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 12 -[SERDES_MODE] = 1 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 1 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 13 -[SERDES_MODE] = 1 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 1 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 14 -[SERDES_MODE] = 1 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 1 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 15 -[SERDES_MODE] = 1 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 1 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 16 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 17 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 18 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 19 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 20 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 21 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 22 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 23 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 24 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 25 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 26 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 1 - -[SERDES_ID] = 27 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 1 - -[SERDES_ID] = 28 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 29 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 0 - -[SERDES_ID] = 30 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 1 - -[SERDES_ID] = 31 -[SERDES_MODE] = 3 -[SERDES_RX_POLY] = 0 -[SERDES_TX_POLY] = 0 -[SERDES_SWITCH] = 0 -[SERDES_GROUP] = 1 - -#repeat end -#} - - -#[SERDES_TO_LPORT] -#{ -# | QSGMII/USXGMII-M2G5 | USXGMII-M5G | USXGMII-S | 100BASE-FX | SGMII/SGMII2G5/XFI | XAUI/DXAUI | XLG | XXVG | LG | CG -#---------|---------------------|-------------|-----------|------------|--------------------|------------|-----|------|----|--- -#serdes 0 |0 /1 /2 /3 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 1 |4 /5 /6 /7 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 2 |16/17/18/19 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 3 |20/21/22/23 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 4 |8 /9 /10/11 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 5 |32/33/34/35 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 6 |36/37/38/39 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 7 |40/41/42/43 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 8 |24/25/26/27 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 9 |48/49/50/51 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 10|52/53/54/55 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 11|56/57/58/59 |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 12|NA |NA |NA |12 |12 |12 |12 |NA |NA |NA -#serdes 13|NA |NA |NA |13 |13 |12 |12 |NA |NA |NA -#serdes 14|NA |NA |NA |14 |14 |12 |12 |NA |NA |NA -#serdes 15|NA |NA |NA |15 |15 |12 |12 |NA |NA |NA -#serdes 16|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 17|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 18|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 19|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 20|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 21|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 22|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 23|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 24|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 25|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 26|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 27|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 28|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 29|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 30|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#serdes 31|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA -#} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku deleted file mode 100644 index 2a8d51c1f241..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/default_sku +++ /dev/null @@ -1 +0,0 @@ -RA-B6010-48GT4X l1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg deleted file mode 100644 index eefd67e9c28b..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/phy_mapping.cfg +++ /dev/null @@ -1,198 +0,0 @@ -#######################PHY_MAPPING_48+4####################### - -#{ -[PHY_MAPPING_ITEM] - -[API_PORT] = 0 -[PHY_ADDR] = 0 -[MDIO_BUS] = 0 - -[API_PORT] = 1 -[PHY_ADDR] = 1 -[MDIO_BUS] = 0 - -[API_PORT] = 2 -[PHY_ADDR] = 2 -[MDIO_BUS] = 0 - -[API_PORT] = 3 -[PHY_ADDR] = 3 -[MDIO_BUS] = 0 - -[API_PORT] = 4 -[PHY_ADDR] = 4 -[MDIO_BUS] = 0 - -[API_PORT] = 5 -[PHY_ADDR] = 5 -[MDIO_BUS] = 0 - -[API_PORT] = 6 -[PHY_ADDR] = 6 -[MDIO_BUS] = 0 - -[API_PORT] = 7 -[PHY_ADDR] = 7 -[MDIO_BUS] = 0 - -[API_PORT] = 16 -[PHY_ADDR] = 8 -[MDIO_BUS] = 0 - -[API_PORT] = 17 -[PHY_ADDR] = 9 -[MDIO_BUS] = 0 - -[API_PORT] = 18 -[PHY_ADDR] = 10 -[MDIO_BUS] = 0 - -[API_PORT] = 19 -[PHY_ADDR] = 11 -[MDIO_BUS] = 0 - -[API_PORT] = 20 -[PHY_ADDR] = 12 -[MDIO_BUS] = 0 - -[API_PORT] = 21 -[PHY_ADDR] = 13 -[MDIO_BUS] = 0 - -[API_PORT] = 22 -[PHY_ADDR] = 14 -[MDIO_BUS] = 0 - -[API_PORT] = 23 -[PHY_ADDR] = 15 -[MDIO_BUS] = 0 - -[API_PORT] = 8 -[PHY_ADDR] = 16 -[MDIO_BUS] = 0 - -[API_PORT] = 9 -[PHY_ADDR] = 17 -[MDIO_BUS] = 0 - -[API_PORT] = 10 -[PHY_ADDR] = 18 -[MDIO_BUS] = 0 - -[API_PORT] = 11 -[PHY_ADDR] = 19 -[MDIO_BUS] = 0 - -[API_PORT] = 32 -[PHY_ADDR] = 20 -[MDIO_BUS] = 0 - -[API_PORT] = 33 -[PHY_ADDR] = 21 -[MDIO_BUS] = 0 - -[API_PORT] = 34 -[PHY_ADDR] = 22 -[MDIO_BUS] = 0 - -[API_PORT] = 35 -[PHY_ADDR] = 23 -[MDIO_BUS] = 0 - -[API_PORT] = 36 -[PHY_ADDR] = 0 -[MDIO_BUS] = 1 - -[API_PORT] = 37 -[PHY_ADDR] = 1 -[MDIO_BUS] = 1 - -[API_PORT] = 38 -[PHY_ADDR] = 2 -[MDIO_BUS] = 1 - -[API_PORT] = 39 -[PHY_ADDR] = 3 -[MDIO_BUS] = 1 - -[API_PORT] = 40 -[PHY_ADDR] = 4 -[MDIO_BUS] = 1 - -[API_PORT] = 41 -[PHY_ADDR] = 5 -[MDIO_BUS] = 1 - -[API_PORT] = 42 -[PHY_ADDR] = 6 -[MDIO_BUS] = 1 - -[API_PORT] = 43 -[PHY_ADDR] = 7 -[MDIO_BUS] = 1 - -[API_PORT] = 24 -[PHY_ADDR] = 8 -[MDIO_BUS] = 1 - -[API_PORT] = 25 -[PHY_ADDR] = 9 -[MDIO_BUS] = 1 - -[API_PORT] = 26 -[PHY_ADDR] = 10 -[MDIO_BUS] = 1 - -[API_PORT] = 27 -[PHY_ADDR] = 11 -[MDIO_BUS] = 1 - -[API_PORT] = 48 -[PHY_ADDR] = 12 -[MDIO_BUS] = 1 - -[API_PORT] = 49 -[PHY_ADDR] = 13 -[MDIO_BUS] = 1 - -[API_PORT] = 50 -[PHY_ADDR] = 14 -[MDIO_BUS] = 1 - -[API_PORT] = 51 -[PHY_ADDR] = 15 -[MDIO_BUS] = 1 - -[API_PORT] = 52 -[PHY_ADDR] = 16 -[MDIO_BUS] = 1 - -[API_PORT] = 53 -[PHY_ADDR] = 17 -[MDIO_BUS] = 1 - -[API_PORT] = 54 -[PHY_ADDR] = 18 -[MDIO_BUS] = 1 - -[API_PORT] = 55 -[PHY_ADDR] = 19 -[MDIO_BUS] = 1 - -[API_PORT] = 56 -[PHY_ADDR] = 20 -[MDIO_BUS] = 1 - -[API_PORT] = 57 -[PHY_ADDR] = 21 -[MDIO_BUS] = 1 - -[API_PORT] = 58 -[PHY_ADDR] = 22 -[MDIO_BUS] = 1 - -[API_PORT] = 59 -[PHY_ADDR] = 23 -[MDIO_BUS] = 1 - -#} diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini deleted file mode 100644 index cd9f488c53b2..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/port_config.ini +++ /dev/null @@ -1,53 +0,0 @@ -# name lanes alias index speed admin_status -Ethernet1 0 eth-0-1 1 1000 up -Ethernet2 1 eth-0-2 2 1000 up -Ethernet3 2 eth-0-3 3 1000 up -Ethernet4 3 eth-0-4 4 1000 up -Ethernet5 4 eth-0-5 5 1000 up -Ethernet6 5 eth-0-6 6 1000 up -Ethernet7 6 eth-0-7 7 1000 up -Ethernet8 7 eth-0-8 8 1000 up -Ethernet9 16 eth-0-9 9 1000 up -Ethernet10 17 eth-0-10 10 1000 up -Ethernet11 18 eth-0-11 11 1000 up -Ethernet12 19 eth-0-12 12 1000 up -Ethernet13 20 eth-0-13 13 1000 up -Ethernet14 21 eth-0-14 14 1000 up -Ethernet15 22 eth-0-15 15 1000 up -Ethernet16 23 eth-0-16 16 1000 up -Ethernet17 8 eth-0-17 17 1000 up -Ethernet18 9 eth-0-18 18 1000 up -Ethernet19 10 eth-0-19 19 1000 up -Ethernet20 11 eth-0-20 20 1000 up -Ethernet21 32 eth-0-21 21 1000 up -Ethernet22 33 eth-0-22 22 1000 up -Ethernet23 34 eth-0-23 23 1000 up -Ethernet24 35 eth-0-24 24 1000 up -Ethernet25 36 eth-0-25 25 1000 up -Ethernet26 37 eth-0-26 26 1000 up -Ethernet27 38 eth-0-27 27 1000 up -Ethernet28 39 eth-0-28 28 1000 up -Ethernet29 40 eth-0-29 29 1000 up -Ethernet30 41 eth-0-30 30 1000 up -Ethernet31 42 eth-0-31 31 1000 up -Ethernet32 43 eth-0-32 32 1000 up -Ethernet33 24 eth-0-33 33 1000 up -Ethernet34 25 eth-0-34 34 1000 up -Ethernet35 26 eth-0-35 35 1000 up -Ethernet36 27 eth-0-36 36 1000 up -Ethernet37 48 eth-0-37 37 1000 up -Ethernet38 49 eth-0-38 38 1000 up -Ethernet39 50 eth-0-39 39 1000 up -Ethernet40 51 eth-0-40 40 1000 up -Ethernet41 52 eth-0-41 41 1000 up -Ethernet42 53 eth-0-42 42 1000 up -Ethernet43 54 eth-0-43 43 1000 up -Ethernet44 55 eth-0-44 44 1000 up -Ethernet45 56 eth-0-45 45 1000 up -Ethernet46 57 eth-0-46 46 1000 up -Ethernet47 58 eth-0-47 47 1000 up -Ethernet48 59 eth-0-48 48 1000 up -Ethernet49 12 eth-0-49 49 10000 up -Ethernet50 13 eth-0-50 50 10000 up -Ethernet51 14 eth-0-51 51 10000 up -Ethernet52 15 eth-0-52 52 10000 up diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile deleted file mode 100644 index 5a5fe93dd4fe..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/sai.profile +++ /dev/null @@ -1,4 +0,0 @@ -SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-chip-profile.txt -SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-datapath.txt -SAI_PLATFORM_CFG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-board.json -SAI_PHY_DRIVER_PATH=/usr/share/sonic/hwsku/phy_drv \ No newline at end of file diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg deleted file mode 100644 index b012adedb252..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X/start_up.cfg +++ /dev/null @@ -1,48 +0,0 @@ - -chip set serdes 0 ffe mode user-define c0 0 c1 255 c2 10 c3 0 c4 0 -chip set serdes 1 ffe mode user-define c0 0 c1 240 c2 10 c3 0 c4 0 -chip set serdes 2 ffe mode user-define c0 0 c1 230 c2 10 c3 0 c4 0 -chip set serdes 3 ffe mode user-define c0 0 c1 220 c2 7 c3 0 c4 0 -chip set serdes 4 ffe mode user-define c0 0 c1 220 c2 8 c3 0 c4 0 -chip set serdes 5 ffe mode user-define c0 0 c1 210 c2 6 c3 0 c4 0 -chip set serdes 6 ffe mode user-define c0 0 c1 180 c2 6 c3 0 c4 0 -chip set serdes 7 ffe mode user-define c0 0 c1 180 c2 5 c3 0 c4 0 -chip set serdes 8 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0 -chip set serdes 9 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0 -chip set serdes 10 ffe mode user-define c0 3 c1 140 c2 9 c3 0 c4 0 -chip set serdes 11 ffe mode user-define c0 3 c1 140 c2 5 c3 0 c4 0 -chip set serdes 12 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 -chip set serdes 13 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 -chip set serdes 14 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 -chip set serdes 15 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0 - - -chip set serdes 0 ctle 6 14 2 -chip set serdes 1 ctle 6 14 2 -chip set serdes 2 ctle 6 14 2 -chip set serdes 3 ctle 6 14 2 -chip set serdes 4 ctle 6 14 2 -chip set serdes 5 ctle 6 14 2 -chip set serdes 6 ctle 6 14 2 -chip set serdes 7 ctle 6 14 2 -chip set serdes 8 ctle 6 14 2 -chip set serdes 9 ctle 6 14 2 -chip set serdes 10 ctle 6 14 2 -chip set serdes 11 ctle 6 14 2 - - - -# rtk eye param, post_amp|main_amp|pre_amp -port 0 phy-attr type 2001 value 0x1c1e00 -port 4 phy-attr type 2001 value 0x101600 -port 16 phy-attr type 2001 value 0x111500 -port 20 phy-attr type 2001 value 0x0e1100 -port 8 phy-attr type 2001 value 0x0f1000 -port 32 phy-attr type 2001 value 0x0e0f00 -port 36 phy-attr type 2001 value 0x0a0a00 -port 40 phy-attr type 2001 value 0x0a0900 -port 24 phy-attr type 2001 value 0x000c00 -port 48 phy-attr type 2001 value 0x000b00 -port 52 phy-attr type 2001 value 0x000b00 -port 56 phy-attr type 2001 value 0x000a00 - diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku deleted file mode 100644 index 2a8d51c1f241..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/default_sku +++ /dev/null @@ -1 +0,0 @@ -RA-B6010-48GT4X l1 diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf deleted file mode 100644 index a44cb9c23c93..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/installer.conf +++ /dev/null @@ -1,9 +0,0 @@ -CONSOLE_SPEED=9600 - -#fix env -config_env(){ - dd if=/dev/mtd1 of=env.bin - flashcp -v env.bin /dev/mtd4 -} -trap_push "config_env || true" - diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py deleted file mode 100644 index 93b331573d6d..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/config.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/python -# -*- coding: UTF-8 -*- -RAGILE_CARDID = 0x00004099 -RAGILE_PRODUCTNAME = "RA-B6010-48GT4X" -RAGILE_PART_NUMBER = "RJ000001" -RAGILE_LABEL_REVISION = "R01" -RAGILE_ONIE_VERSION = "2018.02" -RAGILE_MAC_SIZE = 3 -RAGILE_MANUF_NAME = "Ragile" -RAGILE_MANUF_COUNTRY = "CHN" -RAGILE_VENDOR_NAME = "Ragile" -RAGILE_DIAG_VERSION = "0.1.0.15" -RAGILE_SERVICE_TAG = "www.ragile.com" - -CPUEEPROMS = {"name":"cpueeprom","bus":5,"loc":0x57,"E2PRODUCT":'2', "E2TYPE":'4'} - -# rg_eeprom = "1-0056/eeprom" -E2_LOC = {"bus":1, "devno":0x56} -E2_PROTECT = {} -FAN_PROTECT = {"bus":1, "devno":0x0d, "addr":0x19, "open":0x00, "close":0xff} - - diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py deleted file mode 100644 index 77016e17944a..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/eeprom.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python - -try: - import exceptions - import binascii - import time - import optparse - import warnings - import os - import sys - from sonic_eeprom import eeprom_base - from sonic_eeprom import eeprom_tlvinfo -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - - -class board(eeprom_tlvinfo.TlvInfoDecoder): - - def __init__(self, name, path, cpld_root, ro): - self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" - super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py deleted file mode 100644 index ad619bf33469..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/plugins/sfputil.py +++ /dev/null @@ -1,455 +0,0 @@ -# sfputil.py -# -# Platform-specific SFP transceiver interface for SONiC -# - -try: - import time - import subprocess - import re - import os - import threading - from sonic_sfp.sfputilbase import SfpUtilBase -except ImportError as e: - raise ImportError("%s - required module not found" % str(e)) - - -class SfpUtil(SfpUtilBase): - """Platform-specific SfpUtil class""" - - PORT_START = 49 - PORT_END = 52 - PORTS_IN_BLOCK = 53 - EEPROM_OFFSET = 9 - SFP_DEVICE_TYPE = "optoe2" - QSFP_DEVICE_TYPE = "optoe1" - I2C_MAX_ATTEMPT = 3 - - SFP_STATUS_INSERTED = '1' - SFP_STATUS_REMOVED = '0' - - TXWRT_PROTECT = 0X4E - TXWRT_NO_PROTECT = 0X59 - - _port_to_eeprom_mapping = {} - port_to_i2cbus_mapping ={} - port_dict = {} - port_presence_info = {} - port_reset_info = {} - port_txdis_info = {} - port_txwrt_info = {} - port_led_info = {} - - port_rxlos_info = {} - port_txfault_info = {} - port_drop_info = {} - - @property - def port_start(self): - return self.PORT_START - - @property - def port_end(self): - return self.PORT_END - - @property - def sfp_ports(self): - return list(range(self.PORT_START, self.PORTS_IN_BLOCK)) - - @property - def qsfp_ports(self): - return [] - - @property - def port_to_eeprom_mapping(self): - return self._port_to_eeprom_mapping - - def __init__(self): - for x in range(self.PORT_START, self.PORTS_IN_BLOCK): - self.port_to_i2cbus_mapping[x] = (x - self.PORT_START + self.EEPROM_OFFSET) - self.port_presence_info["/sys/bus/i2c/devices/3-0030/sfp_presence1"] = [49, 50, 51, 52] - self.port_txdis_info["/sys/bus/i2c/devices/3-0030/tx_disable"] = [49, 50, 51, 52] - self.port_txwrt_info["/sys/bus/i2c/devices/3-0030/tx_write_protect"] = [49, 50, 51, 52] - - # bit 1: los - self.port_rxlos_info["/sys/bus/i2c/devices/3-0030/sfp_rx_loss1"] = [49, 50, 51, 52] - - # bit 1: fault - self.port_txfault_info["/sys/bus/i2c/devices/3-0030/sfp_tx_fault1"] = [49, 50, 51, 52] - - # bit 1: drop - self.port_drop_info["/sys/bus/i2c/devices/3-0030/sfp_drop_record1"] = [49, 50, 51, 52] - - SfpUtilBase.__init__(self) - - def _sfp_read_file_path(self, file_path, offset, num_bytes): - attempts = 0 - while attempts < self.I2C_MAX_ATTEMPT: - try: - file_path.seek(offset) - read_buf = file_path.read(num_bytes) - except: - attempts += 1 - time.sleep(0.05) - else: - return True, read_buf - return False, None - - def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset): - """Tries to read the eeprom file to determine if the - device/sfp is present or not. If sfp present, the read returns - valid bytes. If not, read returns error 'Connection timed out""" - - if not os.path.exists(sysfs_sfp_i2c_client_eeprompath): - return False - else: - with open(sysfs_sfp_i2c_client_eeprompath, "rb", buffering=0) as sysfsfile: - rv, buf = self._sfp_read_file_path(sysfsfile, offset, 1) - return rv - - def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype): - try: - sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path - - # Write device address to new_device file - nd_file = open(sysfs_nd_path, "w") - nd_str = "%s %s" % (devtype, hex(devaddr)) - nd_file.write(nd_str) - nd_file.close() - - except Exception as err: - print(("Error writing to new device file: %s" % str(err))) - return 1 - else: - return 0 - - def _get_port_eeprom_path(self, port_num, devid): - sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" - - if port_num in list(self.port_to_eeprom_mapping.keys()): - sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num] - else: - sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" - - i2c_adapter_id = self._get_port_i2c_adapter_id(port_num) - if i2c_adapter_id is None: - print("Error getting i2c bus num") - return None - - # Get i2c virtual bus path for the sfp - sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path, - str(i2c_adapter_id)) - - # If i2c bus for port does not exist - if not os.path.exists(sysfs_sfp_i2c_adapter_path): - print(("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path)) - return None - - sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path, - str(i2c_adapter_id), - hex(devid)[-2:]) - - # If sfp device is not present on bus, Add it - if not os.path.exists(sysfs_sfp_i2c_client_path): - if port_num in self.qsfp_ports: - ret = self._add_new_sfp_device( - sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE) - else: - ret = self._add_new_sfp_device( - sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE) - if ret != 0: - print("Error adding sfp device") - return None - - sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path - return sysfs_sfp_i2c_client_eeprom_path - - def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): - eeprom_raw = [] - for i in range(0, num_bytes): - eeprom_raw.append("0x00") - - rv, raw = self._sfp_read_file_path(sysfsfile_eeprom, offset, num_bytes) - if rv == False: - return None - - try: - if isinstance(raw, str): - for n in range(0, num_bytes): - eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) - else: - for n in range(0, num_bytes): - eeprom_raw[n] = hex(raw[n])[2:].zfill(2) - except Exception as err: - return None - return eeprom_raw - - def get_eeprom_dom_raw(self, port_num): - if port_num in self.qsfp_ports: - # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw - return None - else: - # Read dom eeprom at addr 0x51 - return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 256) - - def get_presence(self, port_num): - # Check for invalid port_num - if port_num < self.port_start or port_num > self.port_end: - return False - - presence_path = None - for presence_key in self.port_presence_info: - if port_num in self.port_presence_info[presence_key]: - presence_path = presence_key - presence_offset = self.port_presence_info[presence_key].index(port_num) - break - if presence_path == None: - return False - - try: - data = open(presence_path, "rb") - except IOError: - return False - - presence_data = data.read(2) - if presence_data == "": - return False - result = int(presence_data, 16) - data.close() - - # ModPrsL is active low - if result & (1 << presence_offset) == 0: - return True - - return False - - def get_low_power_mode(self, port_num): - return False - - def set_low_power_mode(self, port_num, lpmode): - return False - - def reset(self, port_num): - return False - - def reset_all(self): - return False - - def _do_write_file(self, file_handle, offset, value): - file_handle.seek(offset) - file_handle.write(hex(value)) - - def get_transceiver_change_event(self, timeout=0): - - start_time = time.time() - currernt_port_dict = {} - forever = False - - if timeout == 0: - forever = True - elif timeout > 0: - timeout = timeout / float(1000) # Convert to secs - else: - print(("get_transceiver_change_event:Invalid timeout value", timeout)) - return False, {} - - end_time = start_time + timeout - if start_time > end_time: - print(('get_transceiver_change_event:' \ - 'time wrap / invalid timeout value', timeout)) - - return False, {} # Time wrap or possibly incorrect timeout - - while timeout >= 0: - # Check for OIR events and return updated port_dict - for x in range(self.PORT_START, self.PORTS_IN_BLOCK): - if self.get_presence(x): - currernt_port_dict[x] = self.SFP_STATUS_INSERTED - else: - currernt_port_dict[x] = self.SFP_STATUS_REMOVED - if (currernt_port_dict == self.port_dict): - if forever: - time.sleep(1) - else: - timeout = end_time - time.time() - if timeout >= 1: - time.sleep(1) # We poll at 1 second granularity - else: - if timeout > 0: - time.sleep(timeout) - return True, {} - else: - # Update reg value - self.port_dict = currernt_port_dict - return True, self.port_dict - print ("get_transceiver_change_event: Should not reach here.") - return False, {} - - def tx_disable(self, port_num, disable): - if not self.get_presence(port_num): - return False - - if port_num in self.sfp_ports: - txwrt_path = None - txdis_path = None - txdis_offset = 0 - - for key in self.port_txwrt_info: - if port_num in self.port_txwrt_info[key]: - txwrt_path = key - break - if txwrt_path == None: - return False - - for key in self.port_txdis_info: - if port_num in self.port_txdis_info[key]: - txdis_path = key - txdis_offset = self.port_txdis_info[key].index(port_num) - break - if txdis_path == None: - return False - - - try: - with open(txwrt_path, "r+") as sys_file: - sres = hex(self.TXWRT_NO_PROTECT)[2:] - sys_file.write(sres) - - with open(txdis_path, "r+") as sys_file: - txdis_data = sys_file.read(2) - if not txdis_data: - return False - result = int(txdis_data, 16) - if disable: - result = result | (1 << txdis_offset) - else: - result = result & (~(1 << txdis_offset)) - sys_file.seek(0) - sres = hex(result)[2:] - print(result,sres) - sys_file.write(sres) - - with open(txwrt_path, "r+") as sys_file: - sres = hex(self.TXWRT_PROTECT)[2:] - sys_file.write(sres) - except Exception as err: - print(err) - return False - - return True - else: - return False - -########### sysdiag ########### - def _get_cpld_info(self, port_num, info): - path = None - offset = 0 - for key in info: - if port_num in info[key]: - path = key - offset = info[key].index(port_num) - break - return path, offset - - def get_tx_disable(self, port_num): - # cur only support sfp moudle - if port_num not in self.sfp_ports: - return False - - if not self.get_presence(port_num): - return False - - path, offset = self._get_cpld_info(port_num, self.port_txdis_info) - if path == None: - return False - - result = 0 - try: - with open(path, "r") as sys_file: - data = sys_file.read(2) - result = int(data, 16) - except Exception as e: - print((str(e))) - return False - - # 1: disable - if result & (1 << offset): - return True - else: - return False - - def get_rx_los(self, port_num): - # cur only support sfp moudle - if port_num not in self.sfp_ports: - return False - - path, offset = self._get_cpld_info(port_num, self.port_rxlos_info) - if path == None: - return False - - result = 0 - try: - with open(path, "r") as sys_file: - data = sys_file.read(2) - result = int(data, 16) - except Exception as e: - print((str(e))) - return False - - # 1: los - if result & (1 << offset): - return True - else: - return False - - def get_tx_fault(self, port_num): - # cur only support sfp moudle - if port_num not in self.sfp_ports: - return False - - if not self.get_presence(port_num): - return False - - path, offset = self._get_cpld_info(port_num, self.port_txfault_info) - if path == None: - return False - - result = 0 - try: - with open(path, "r") as sys_file: - data = sys_file.read(2) - result = int(data, 16) - except Exception as e: - print((str(e))) - return False - - # 1: fault - if result & (1 << offset): - return True - else: - return False - - return False - - def get_plug_record(self, port_num): - if not self.get_presence(port_num): - return False - - path, offset = self._get_cpld_info(port_num, self.port_drop_info) - if path == None: - return False - - result = 0 - try: - with open(path, "r") as sys_file: - data = sys_file.read(2) - result = int(data, 16) - except Exception as e: - print((str(e))) - return False - - # 1: drop - if result & (1 << offset): - return True - else: - return False diff --git a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json b/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json deleted file mode 100644 index 5fdf83f1b9e6..000000000000 --- a/device/ragile/arm64-ragile_ra-b6010-48gt4x-r0/arm64-ragile_ra-b6010-48gt4x-r0/pmon_daemon_control.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "skip_ledd": true, - "skip_xcvrd": false, - "skip_syseepromd": false, - "skip_thermalctld": false, - "skip_psud": false -} diff --git a/dockers/docker-platform-monitor/Dockerfile.j2 b/dockers/docker-platform-monitor/Dockerfile.j2 index 14fd2447793d..1c6b484814c7 100755 --- a/dockers/docker-platform-monitor/Dockerfile.j2 +++ b/dockers/docker-platform-monitor/Dockerfile.j2 @@ -41,6 +41,9 @@ RUN pip3 install grpcio==1.39.0 \ # Barefoot platform vendors' sonic_platform packages import these Python libraries RUN pip3 install thrift==0.13.0 netifaces +# Ragile platform vendors' sonic_platform packages import these Python libraries +RUN pip3 install requests + # We install the libpci module in order to be able to do PCI transactions RUN pip3 install libpci diff --git a/files/build_scripts/mask_disabled_services.py b/files/build_scripts/mask_disabled_services.py index 5c1a3695802f..291b8d7e0748 100755 --- a/files/build_scripts/mask_disabled_services.py +++ b/files/build_scripts/mask_disabled_services.py @@ -4,10 +4,20 @@ import subprocess INIT_CFG_FILE_PATH = '/etc/sonic/init_cfg.json' +WARM_OR_FAST_BOOT_DATAPLANE_NEEDED_SERVICES = ['database', 'swss', 'syncd', 'teamd', 'bgp'] with open(INIT_CFG_FILE_PATH) as init_cfg_file: init_cfg = json.load(init_cfg_file) if 'FEATURE' in init_cfg: for feature_name, feature_props in init_cfg['FEATURE'].items(): - if 'state' in feature_props and feature_props['state'] != 'enabled' and feature_props['state'] != 'always_enabled': - subprocess.run(['systemctl', 'mask', '{}.service'.format(feature_name)]) + # For warm/fast boot we want to have all crtical dataplane needed service + # to start immediately before hostcfgd can render `state` field unless the `state` field is marked disabled + # explicitly during build time rendering of init_cfg.json + if feature_name in WARM_OR_FAST_BOOT_DATAPLANE_NEEDED_SERVICES: + if 'state' in feature_props and (feature_props['state'] == 'disabled' or feature_props['state'] == 'always_disabled'): + subprocess.run(['systemctl', 'mask', '{}.service'.format(feature_name)]) + # For other services by default mask out the service if not enable explicitly. This service can get enable later on when + # hostcfgd render the state as enable. This should not cause dataplane impact. + else: + if 'state' in feature_props and feature_props['state'] != 'enabled' and feature_props['state'] != 'always_enabled': + subprocess.run(['systemctl', 'mask', '{}.service'.format(feature_name)]) diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local index 8692ff6484cd..15dec204eb4d 100755 --- a/files/image_config/platform/rc.local +++ b/files/image_config/platform/rc.local @@ -182,7 +182,7 @@ value_extract() { program_console_speed() { - speed=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+,[0-9]+' | cut -d "," -f2) + speed=$(cat /proc/cmdline | grep -Eo 'console=tty(S|AMA)[0-9]+,[0-9]+' | cut -d "," -f2) if [ -z "$speed" ]; then CONSOLE_SPEED=9600 else diff --git a/platform/centec-arm64/one-image.mk b/platform/centec-arm64/one-image.mk index b8ef82853e25..dbf8494f11f2 100755 --- a/platform/centec-arm64/one-image.mk +++ b/platform/centec-arm64/one-image.mk @@ -12,7 +12,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48S4X_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2Q_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(FS_S5800_48T4S_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(RA_B6010_48GT4X_PLATFORM_MODULE) -$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(RA_B6010_48GT4X_R_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(RA_B6 010_48GT4X_R_PLATFORM_MODULE) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk index d53943972eca..db042ca2577d 100755 --- a/platform/centec-arm64/sai.mk +++ b/platform/centec-arm64/sai.mk @@ -1,11 +1,12 @@ +# Centec SAI + export CENTEC_SAI_VERSION = 1.11.0-1 export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb export CENTEC_SAI_DEV = libsai-dev_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb -$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) -$(CENTEC_SAI_DEV)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI_DEV) +$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sai-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) +$(CENTEC_SAI_DEV)_URL = https://github.com/CentecNetworks/sai-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI_DEV) $(eval $(call add_conflict_package,$(CENTEC_SAI_DEV),$(LIBSAIVS_DEV))) SONIC_ONLINE_DEBS += $(CENTEC_SAI) SONIC_ONLINE_DEBS += $(CENTEC_SAI_DEV) - diff --git a/platform/centec-arm64/tsingma-bsp/debian/rules b/platform/centec-arm64/tsingma-bsp/debian/rules index 39744906e3cf..88167489cca1 100755 --- a/platform/centec-arm64/tsingma-bsp/debian/rules +++ b/platform/centec-arm64/tsingma-bsp/debian/rules @@ -17,6 +17,7 @@ KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) MODULE_DIRS:= ctc5236-mc ctc5236_switch ctcmac ctc_wdt ehci-ctc gpio-ctc i2c-ctc pinctrl-ctc pwm-ctc rtc-sd2405 sdhci-ctc5236 spi-ctc-qspi ctc-phy DTS_DIR := ctc-dts +DTS_DIR0 := ra-b6010-48gt4x MODULE_DIR := src UTILS_DIR := utils SERVICE_DIR := service @@ -36,6 +37,7 @@ build: make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$(MODULE_DIR)/$${mod}; \ done) make -C $(MOD_SRC_DIR)/$(MODULE_DIR)/$(DTS_DIR) + make -C $(MOD_SRC_DIR)/$(MODULE_DIR)/$(DTS_DIR0) binary: binary-arch binary-indep # Nothing to do diff --git a/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install index e072cb175189..5914f9f1ced4 100644 --- a/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install +++ b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install @@ -13,5 +13,6 @@ src/rtc-sd2405/rtc-sd2405.ko /lib/modules/5.10.0-18-2-arm64/kernel/extra src/sdhci-ctc5236/sdhci-ctc5236.ko /lib/modules/5.10.0-18-2-arm64/kernel/extra src/spi-ctc-qspi/spi-ctc-qspi.ko /lib/modules/5.10.0-18-2-arm64/kernel/extra src/ctc-dts/e530-ctc5236.dtb /boot/ +src/ra-b6010-48gt4x/ra-b6010-48gt4x-r0.dtb /boot/ src/config/fw_env.config /etc/ src/config/tsingma-bsp.service /lib/systemd/system diff --git a/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/Makefile b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/Makefile new file mode 100755 index 000000000000..8808f1d78b4e --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/Makefile @@ -0,0 +1,5 @@ +ra-b6010-48gt4x-r0.dtb: ra-b6010-48gt4x-r0.dts ctc5236.dtsi ctc5236-clock.dtsi + cpp -nostdinc -I. -undef -x assembler-with-cpp ra-b6010-48gt4x-r0.dts > tmp.dts + dtc -O dtb -o ra-b6010-48gt4x-r0.dtb tmp.dts + rm tmp.dts -rf + \ No newline at end of file diff --git a/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/arm-gic.h b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/arm-gic.h new file mode 100755 index 000000000000..ef79498bdde5 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/arm-gic.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * This header provides constants for the ARM GIC. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H + +#include "irq.h" + +/* interrupt specifier cell 0 */ + +#define GIC_SPI 0 +#define GIC_PPI 1 + +/* + * Interrupt specifier cell 2. + * The flags in irq.h are valid, plus those below. + */ +#define GIC_CPU_MASK_RAW(x) ((x) << 8) +#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) + +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clks.h b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clks.h new file mode 100755 index 000000000000..56d91da3130a --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clks.h @@ -0,0 +1,25 @@ +/* + * ctc5236 clock tree IDs + * + * (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * + * Jay Cao + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __CTC5236_CLKS_H +#define __CTC5236_CLKs_H + +#define CLKID_UNUSED 0 +#define CLKID_PLL_FIXED 1 +#define CLKID_UART0 2 + +#endif /* __CTC5236_CLKS_H */ diff --git a/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clock.dtsi b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clock.dtsi new file mode 100755 index 000000000000..ae6b00c00ba2 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236-clock.dtsi @@ -0,0 +1,63 @@ +/* + * dts file for Centec CTC5236(TsingMa) SoC + * + * (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * + * Jay Cao + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + + osc: oscillator { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + }; + + sup_clk: sup_clk_12m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <1200000000>; + clock-output-names = "sup_clk"; + }; + + uart_clk: uart_clk_20m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <20000000>; + clock-output-names = "uart_clk"; + }; + + i2c_clk: clkm { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + clock-output-names = "i2c_clk"; + }; + wdog_clk:wdog_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <1000000>; + clock-output-names = "wdog_clk"; + }; + timer_clk:timer_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <500000000>; + clock-output-names = "timer_clk"; + }; + mmc_clk:mmc_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + clock-output-names = "mmc_clk"; + }; + spi_clk:spi_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + clock-output-names = "spi_clk"; + }; diff --git a/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236.dtsi b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236.dtsi new file mode 100755 index 000000000000..bacf2eb17ddc --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ctc5236.dtsi @@ -0,0 +1,428 @@ +/* + * dts file for Centec CTC5236(TsingMa) SoC + * + * (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * + * Jay Cao + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include "arm-gic.h" +#include "ctc5236-clks.h" +#include "../pinctrl-ctc/pinctrl-ctc.h" + +/ { + compatible = "centec,ctc5236"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + }; + }; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0x000>; + enable-method = "spin-table"; + cpu-release-addr = <0 0x0010fff0>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0x001>; + enable-method = "spin-table"; + cpu-release-addr = <0 0x0010fff0>; + }; + }; + + gic: interrupt-controller@31201000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x31201000 0 0x1000>, + <0x0 0x31202000 0 0x2000>, + <0x0 0x31204000 0 0x2000>, + <0x0 0x31206000 0 0x2000>; + interrupts = ; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + #include "ctc5236-clock.dtsi" + ocram: sram@00100000 { + compatible = "mmio-sram"; + reg = <0x0 0x00100000 0x0 0x10000>; + }; + + memory-controller@30600000 { + compatible = "ctc,ctc5236-ddr-ctrl"; + reg = <0x0 0x30600000 0x0 0x100000>; + interrupts = , + , + , + ; + ctc,sysctrl = <&sysctrl>; + }; + + sysctrl: sysctrl@33200000 { + compatible = "ctc,ctc5236-sysctrl", "syscon"; + reg = <0x0 0x33200000 0x0 0x100000>; + little-endian; + }; + + serial0: serial@33000000 { + compatible = "arm,pl011","arm,primecell"; + reg = <0x0 0x33000000 0x0 0x1000>; + interrupts = ; + clocks = <&uart_clk>, <&sup_clk>; + clock-names = "uart_clk", "apb_pclk"; + status="disabled"; + }; + serial1: serial@33001000 { + compatible = "arm,pl011","arm,primecell"; + reg = <0x0 0x33001000 0x0 0x1000>; + interrupts = ; + clocks = <&uart_clk>, <&sup_clk>; + clock-names = "uart_clk", "apb_pclk"; + status="disabled"; + }; + serial2: serial@33002000 { + compatible = "arm,pl011","arm,primecell"; + reg = <0x0 0x33002000 0x0 0x1000>; + interrupts = ; + clocks = <&uart_clk>, <&sup_clk>; + clock-names = "uart_clk", "apb_pclk"; + status="disabled"; + }; + mdio: mdio@33620000 { + compatible = "ctc,mdio"; + reg = <0x0 0x33620000 0x0 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + enet0: ethernet@33410000 { + compatible = "ctc,mac"; + device_type = "network"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + status = "disabled"; + local-mac-address = [00 00 00 00 00 00]; + index = <0x00>; + reg = <0x0 0x33410000 0x0 0x10000>, + <0x0 0x33400000 0x0 0x10000>; + interrupts = , + , + , + , + ; + ctc,sysctrl = <&sysctrl>; + }; + + enet1: ethernet@33420000 { + compatible = "ctc,mac"; + device_type = "network"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + status = "disabled"; + local-mac-address = [00 00 00 00 00 00]; + index = <0x01>; + reg = <0x0 0x33420000 0x0 0x10000>, + <0x0 0x33400000 0x0 0x10000>; + interrupts = , + , + , + , + ; + ctc,sysctrl = <&sysctrl>; + }; + + ehci0: usb@30500000 { + compatible = "ctc-ehci"; + reg = <0x0 0x30500000 0x0 0x1000>; + interrupts = ; + ctc,sysctrl = <&sysctrl>; + status = "disabled"; + }; + + ohci0: usb@30580000 { + compatible = "generic-ohci"; + reg = <0x0 0x30580000 0x0 0x1000>; + interrupts = ; + status = "disabled"; + }; + + spi: spi@33100000 { + compatible = "arm,pl022","arm,primecell"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33100000 0x0 0x100000>; + clocks = <&spi_clk>, <&sup_clk>; + clock-names = "spi_clk", "apb_pclk"; + num-cs = <4>; + interrupts = ; + ctc,sysctrl = <&sysctrl>; + status ="disabled"; + }; + + qspi: qspi@10000000 { + compatible = "ctc, igdaxi001a-qspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x10000000 0x0 0x10000>; + pclk = <500000000>; + num-cs = <2>; + idle-cycle = <2>; + post-cycle = <1>; + pre-cycle = <2>; + interrupts = ; + status = "disabled"; + }; + switch: switch@31100000 { + compatible = "centec,dal-localbus"; + reg = <0x0 0x31100000 0x0 0x1000>, + <0x0 0x33290000 0x0 0x10000>; + interrupts = , + , + , + , + , + , + , + ; + status ="disabled"; + }; + switch1: switch1@31101000 { + compatible = "centec,switch"; + reg = <0x0 0x31101000 0x0 0x1000>; + status ="disabled"; + }; + + i2c0: i2c0@33700000{ + compatible = "ctc,i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33700000 0x0 0x1000>; + interrupts = ; + clocks = <&i2c_clk>; + ctc,sysctrl = <&sysctrl>; + i2c-num = <0>; + status ="disabled"; + }; + + i2c1: i2c1@33701000{ + compatible = "ctc,i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33701000 0x0 0x1000>; + interrupts = ; + clocks = <&i2c_clk>; + ctc,sysctrl = <&sysctrl>; + i2c-num = <1>; + status ="disabled"; + }; + + pcie: pcie@20000000 { + compatible = "centec,ctc5236-pcie"; + reg = <0x0 0x20000000 0x0 0x10000000 + 0x0 0x30000000 0x0 0x1000>; + reg-names = "cfg", "ctrl"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + interrupt-parent = <&gic>; + interrupts = , + , + ; + interrupt-names = "msi","aer","pme"; + msi-parent = <&pcie>; + bus-range = <0 0xff>; + ranges = <0x42000000 0 0x00000000 0 0x40000000 0 0x20000000 + 0x02000000 0 0x20000000 0 0x60000000 0 0x20000000>; + num-lanes = <1>; + ctc,sysctrl = <&sysctrl>; + status ="disabled"; + }; + + wtd0: wtd0@33500000{ + compatible = "arm,sp805-wdt", "arm,primecell"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33500000 0x0 0x1000>; + clocks = <&wdog_clk>, <&sup_clk>; + clock-names = "wdog_clk", "apb_pclk"; + ctc,sysctrl = <&sysctrl>; + interrupts = ; + status="disabled"; + }; + wtd1: wtd1@33501000{ + compatible = "arm,sp805-wdt", "arm,primecell"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33501000 0x0 0x1000>; + clocks = <&wdog_clk>, <&sup_clk>; + clock-names = "wdog_clk", "apb_pclk"; + ctc,sysctrl = <&sysctrl>; + interrupts = ; + status="disabled"; + }; + + sdhci: sdhci@30400000 { + compatible = "centec,ctc5236-sdhci"; + status = "disabled"; + interrupt-parent = <&gic>; + interrupts = ; + clocks = <&mmc_clk>; + clock-names = "mmc_clk"; + ctc,sysctrl = <&sysctrl>; + reg = <0x0 0x30400000 0x0 0x1000>; + }; + + timer0: timer0@33600000{ + compatible = "snps,dw-apb-timer"; + reg = <0x0 0x33600000 0x0 0x20>; + clocks = <&timer_clk>; + clock-names = "timer"; + interrupts = ; + DivNum = <0x3c>; + status="disabled"; + }; + timer1: timer1@33600020{ + compatible = "snps,dw-apb-timer"; + reg = <0x0 0x33600020 0x0 0x20>; + clocks = <&timer_clk>; + clock-names = "timer"; + interrupts = ; + DivNum = <0x3c>; + status="disabled"; + }; + + pwm: pwm@33200240{ + compatible = "centec-pwm"; + ctc,sysctrl = <&sysctrl>; + #pwm-cells = <2>; + + status="disabled"; + }; + + fan: fan-ctc5236 { + compatible = "fan-ctc5236"; + pwms = <&pwm 0 1000000>, + <&pwm 1 1000000>, + <&pwm 2 1000000>, + <&pwm 3 1000000>; + pwm-names = "pwm1","pwm2","pwm3","pwm4"; + }; + + gpio0: gpio@33610000 { + compatible = "ctc,apb-gpio"; + reg = <0x0 0x33610000 0x0 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + ctc,sysctrl = <&sysctrl>; + + porta: gpio-port@0 { + compatible = "ctc,apb-gpio-porta"; + gpio-controller; + #gpio-cells = <2>; + ctc,nr-gpios = <16>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + portb: gpio-port@1 { + compatible = "ctc,apb-gpio-portb"; + gpio-controller; + #gpio-cells = <2>; + ctc,nr-gpios = <18>; + reg = <1>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + }; + + pinctrl: pinctrl { + compatible = "ctc,ctc5236-pinctrl"; + #address-cells = <0x2>; + #size-cells = <0x2>; + ctc,pinctrl-bank0 = <16>; + ctc,pinctrl-bank1 = <8>; + ctc,sysctrl = <&sysctrl>; + + spi { + spi_pin: spi_pin { + ctc,pins = <0 0 PIN_FUNC_SPI>, + <0 2 PIN_FUNC_SPI>, + <0 3 PIN_FUNC_SPI>, + <0 4 PIN_FUNC_SPI>, + <0 5 PIN_FUNC_SPI>, + <0 6 PIN_FUNC_SPI>, + <0 7 PIN_FUNC_SPI>; + }; + }; + + uart2 { + uart2_pin: uart2_pin { + ctc,pins = <0 10 PIN_FUNC_UART>, + <0 11 PIN_FUNC_UART>, + <0 12 PIN_FUNC_UART>, + <0 13 PIN_FUNC_UART>, + <0 14 PIN_FUNC_UART>, + <0 15 PIN_FUNC_UART>; + }; + }; + + fc { + fc_pin: fc_pin { + ctc,pins = <1 0 PIN_FUNC_FC>, + <1 1 PIN_FUNC_FC>, + <1 2 PIN_FUNC_FC>, + <1 3 PIN_FUNC_FC>, + <1 4 PIN_FUNC_FC>, + <1 5 PIN_FUNC_FC>, + <1 6 PIN_FUNC_FC>, + <1 7 PIN_FUNC_FC>; + }; + }; + }; + }; + +}; + diff --git a/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/irq.h b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/irq.h new file mode 100755 index 000000000000..9e3d183e1381 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/irq.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * This header provides constants for most IRQ bindings. + * + * Most IRQ bindings include a flags cell as part of the IRQ specifier. + * In most cases, the format of the flags cell uses the standard values + * defined in this header. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H + +#define IRQ_TYPE_NONE 0 +#define IRQ_TYPE_EDGE_RISING 1 +#define IRQ_TYPE_EDGE_FALLING 2 +#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) +#define IRQ_TYPE_LEVEL_HIGH 4 +#define IRQ_TYPE_LEVEL_LOW 8 + +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ra-b6010-48gt4x-r0.dts b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ra-b6010-48gt4x-r0.dts new file mode 100755 index 000000000000..2b91196b7fc2 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ra-b6010-48gt4x/ra-b6010-48gt4x-r0.dts @@ -0,0 +1,333 @@ +/* + * dts file for Centec CTC5236(TsingMa) SoC E530-24X2C Board + * + * (C) Copyright 2004-2018 Centec Networks (suzhou) Co., LTD. + * + * liuht + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +/dts-v1/; +#include "ctc5236.dtsi" + +/ { + model = " CTC5236(TsingMa) E530 Board"; + compatible = "ctc5236,e530-ctc5236"; + + memory@0 { + device_type = "memory"; + reg = <0 0x80000000 0x1 0x00000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial0 = &serial0; + serial1 = &serial1; + ethernet0 = &enet0; + ethernet1 = &enet1; + + i2c0 = &i2c1; + /* 0 0x70 */ + i2c1 = &imux1; + i2c2 = &imux2; + i2c3 = &imux3; + i2c4 = &imux4; + i2c5 = &imux5; + i2c6 = &imux6; + i2c7 = &imux7; + i2c8 = &imux8; + /* 8 0x74 */ + i2c9 = &imux9; + i2c10 = &imux10; + i2c11 = &imux11; + i2c12 = &imux12; + i2c13 = &imux13; + i2c14 = &imux14; + i2c15 = &imux15; + i2c16 = &imux16; + }; + +}; + +&serial0 { + status = "okay"; +}; + +&serial1 { + status = "okay"; +}; + +&mdio { + status = "okay"; + phy0: ethernet-phy@0 { + index = <0x00>; + reg = <0x00>; + }; +}; + +&enet0 { + status = "okay"; + phy-handle = <&phy0>; + auto-nego-mode= "sgmii-mac"; +}; + +&qspi { + status = "okay"; + + qspiflash0: mx25u3235f@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-cpha; + spi-cpol; + spi-max-frequency = <25000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x300000>; + }; + partition@300000 { + label = "uboot-env"; + reg = <0x300000 0x10000>; + }; + partition@310000 { + label = "onie"; + reg = <0x310000 0x1cf0000>; + }; + }; + }; + + qspiflash1: mx25u3235f@1 { + compatible = "jedec,spi-nor"; + reg = <0x1>; + spi-cpha; + spi-cpol; + spi-max-frequency = <25000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot1"; + reg = <0x0 0x300000>; + }; + partition@300000 { + label = "uboot1-env"; + reg = <0x300000 0x10000>; + }; + partition@310000 { + label = "onie1"; + reg = <0x310000 0x1cf0000>; + }; + }; + }; +}; + +&spi { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_pin>; + + clock0: ad9559@1 { + compatible = "analog,ad9559"; + reg = <1>; + spi-max-frequency = <25000000>; + }; +}; + +&switch { + status = "okay"; +}; + +&switch1 { + status = "okay"; +}; + + +&i2c1{ + status = "okay"; + clock-frequency = <95000>; + + pca9548@70 { + compatible = "nxp,pca9548"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + imux1:i2c@0 { + reg = <0>; + eeprom@56 { + compatible = "at24,24c02"; + reg = <0x56>; + pagesize = <32>; + }; + }; + imux2:i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + imux3:i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + imux4:i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + imux5:i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + imux6:i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + }; + imux7:i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + }; + imux8:i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + pca9548@74 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nxp,pca9548"; + reg = <0x74>; + imux9:i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + imux10:i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + imux11:i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + imux12:i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + imux13:i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + imux14:i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + }; + imux15:i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + }; + imux16:i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + }; + }; + }; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&wtd0{ + status = "okay"; +}; + +&wtd1{ + status = "disabled"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <100000000>; + non-removable; + no-sd; + no-sdio; + voltage-ranges = <3300 3300>; + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&soc { + ctc-irq { + compatible = "centec,ctc-irq"; + device_type = "ctc-irq"; + interrupt-parent=<&porta>; + interrupts = < 0 IRQ_TYPE_LEVEL_LOW>, + < 1 IRQ_TYPE_LEVEL_LOW>, + <15 IRQ_TYPE_LEVEL_LOW>, + < 6 IRQ_TYPE_LEVEL_HIGH>, + < 7 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&pwm { + status = "disabled"; +}; + + +&pinctrl { + spi { + spi_pin: spi_pin { + status = "disabled"; + ctc,pins = <0 0 PIN_FUNC_SPI>, + <0 2 PIN_FUNC_SPI>, + <0 3 PIN_FUNC_SPI>, + <0 5 PIN_FUNC_SPI>; + }; + }; + + pwm0 { + pwm0_pin: pwm0_pin { + ctc,pins = <0 8 PIN_FUNC_PWM>, + <0 9 PIN_FUNC_PWM>, + <0 10 PIN_FUNC_PWM>, + <0 11 PIN_FUNC_PWM>, + <0 12 PIN_FUNC_PWM>, + <0 13 PIN_FUNC_PWM>, + <0 14 PIN_FUNC_PWM>, + <0 15 PIN_FUNC_PWM>; + }; + }; +}; diff --git a/rules/isc-dhcp.mk b/rules/isc-dhcp.mk index 1a1ad54678b8..0951836470ce 100644 --- a/rules/isc-dhcp.mk +++ b/rules/isc-dhcp.mk @@ -1,7 +1,7 @@ # isc-dhcp packages ISC_DHCP_VERSION = 4.4.1 -ISC_DHCP_VERSION_FULL = ${ISC_DHCP_VERSION}-2.3 +ISC_DHCP_VERSION_FULL = ${ISC_DHCP_VERSION}-2.3+deb11u1 export ISC_DHCP_VERSION ISC_DHCP_VERSION_FULL diff --git a/src/dhcpmon/src/dhcp_device.cpp b/src/dhcpmon/src/dhcp_device.cpp index 8ec91b057b64..f4f23526e136 100644 --- a/src/dhcpmon/src/dhcp_device.cpp +++ b/src/dhcpmon/src/dhcp_device.cpp @@ -41,6 +41,7 @@ #define DHCP_OPTIONS_HEADER_SIZE 240 /** Offset of DHCP GIADDR */ #define DHCP_GIADDR_OFFSET 24 +#define CLIENT_IF_PREFIX "Ethernet" #define OP_LDHA (BPF_LD | BPF_H | BPF_ABS) /** bpf ldh Abs */ #define OP_LDHI (BPF_LD | BPF_H | BPF_IND) /** bpf ldh Ind */ @@ -51,19 +52,54 @@ #define OP_JSET (BPF_JMP | BPF_JSET | BPF_K) /** bpf jset */ #define OP_LDXB (BPF_LDX | BPF_B | BPF_MSH) /** bpf ldxb */ +std::shared_ptr mConfigDbPtr = std::make_shared ("CONFIG_DB", 0); std::shared_ptr mStateDbPtr = std::make_shared ("STATE_DB", 0); std::shared_ptr mStateDbMuxTablePtr = std::make_shared ( mStateDbPtr.get(), "HW_MUX_CABLE_TABLE" ); -swss::DBConnector configDb("CONFIG_DB", 0); + +/* interface to vlan mapping */ +std::unordered_map vlan_map; + +/** Berkeley Packet Filter program for "udp and (port 67 or port 68)". + * This program is obtained using the following command tcpdump: + * `tcpdump -dd "outbound and udp and (port 67 or port 68)"` + */ +static struct sock_filter dhcp_outbound_bpf_code[] = { + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0xfffff004}, // (000) ldh #fffff004 + {.code = OP_JEQ, .jt = 0, .jf = 22, .k = 0x00000004}, // (001) jeq #0x04 jt 0 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x0000000c}, // (002) ldh [12] + {.code = OP_JEQ, .jt = 0, .jf = 7, .k = 0x000086dd}, // (003) jeq #0x86dd jt 2 jf 9 + {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000014}, // (004) ldb [20] + {.code = OP_JEQ, .jt = 0, .jf = 18, .k = 0x00000011}, // (005) jeq #0x11 jt 4 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000036}, // (006) ldh [54] + {.code = OP_JEQ, .jt = 15, .jf = 0, .k = 0x00000043}, // (007) jeq #0x43 jt 21 jf 6 + {.code = OP_JEQ, .jt = 14, .jf = 0, .k = 0x00000044}, // (008) jeq #0x44 jt 21 jf 7 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000038}, // (009) ldh [56] + {.code = OP_JEQ, .jt = 12, .jf = 11, .k = 0x00000043}, // (010) jeq #0x43 jt 21 jf 20 + {.code = OP_JEQ, .jt = 0, .jf = 12, .k = 0x00000800}, // (011) jeq #0x800 jt 10 jf 22 + {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000017}, // (012) ldb [23] + {.code = OP_JEQ, .jt = 0, .jf = 10, .k = 0x00000011}, // (013) jeq #0x11 jt 12 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000014}, // (014) ldh [20] + {.code = OP_JSET, .jt = 8, .jf = 0, .k = 0x00001fff}, // (015) jset #0x1fff jt 22 jf 14 + {.code = OP_LDXB, .jt = 0, .jf = 0, .k = 0x0000000e}, // (016) ldxb 4*([14]&0xf) + {.code = OP_LDHI, .jt = 0, .jf = 0, .k = 0x0000000e}, // (017) ldh [x + 14] + {.code = OP_JEQ, .jt = 4, .jf = 0, .k = 0x00000043}, // (018) jeq #0x43 jt 21 jf 17 + {.code = OP_JEQ, .jt = 3, .jf = 0, .k = 0x00000044}, // (019) jeq #0x44 jt 21 jf 18 + {.code = OP_LDHI, .jt = 0, .jf = 0, .k = 0x00000010}, // (020) ldh [x + 16] + {.code = OP_JEQ, .jt = 1, .jf = 0, .k = 0x00000043}, // (021) jeq #0x43 jt 21 jf 20 + {.code = OP_JEQ, .jt = 0, .jf = 1, .k = 0x00000044}, // (022) jeq #0x44 jt 21 jf 22 + {.code = OP_RET, .jt = 0, .jf = 0, .k = 0x00040000}, // (023) ret #262144 + {.code = OP_RET, .jt = 0, .jf = 0, .k = 0x00000000}, // (024) ret #0 +}; /** Berkeley Packet Filter program for "udp and (port 67 or port 68)". * This program is obtained using the following command tcpdump: * `tcpdump -dd "inbound and udp and (port 67 or port 68)"` */ -static struct sock_filter dhcp_bpf_code[] = { +static struct sock_filter dhcp_inbound_bpf_code[] = { {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0xfffff004}, // (000) ldh #fffff004 - {.code = OP_JEQ, .jt = 22, .jf = 0, .k = 0x00000004}, // (001) jeq #0x04 jt 22 jf 0 + {.code = OP_JEQ, .jt = 22, .jf = 0, .k = 0x00000004}, // (001) jeq #0x04 jt 22 jf 0 {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x0000000c}, // (002) ldh [12] {.code = OP_JEQ, .jt = 0, .jf = 7, .k = 0x000086dd}, // (003) jeq #0x86dd jt 2 jf 9 {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000014}, // (004) ldb [20] @@ -90,8 +126,11 @@ static struct sock_filter dhcp_bpf_code[] = { }; /** Filter program socket struct */ -static struct sock_fprog dhcp_sock_bfp = { - .len = sizeof(dhcp_bpf_code) / sizeof(*dhcp_bpf_code), .filter = dhcp_bpf_code +static struct sock_fprog dhcp_outbound_sock_bfp = { + .len = sizeof(dhcp_outbound_bpf_code) / sizeof(*dhcp_outbound_bpf_code), .filter = dhcp_outbound_bpf_code +}; +static struct sock_fprog dhcp_inbound_sock_bfp = { + .len = sizeof(dhcp_inbound_bpf_code) / sizeof(*dhcp_inbound_bpf_code), .filter = dhcp_inbound_bpf_code }; /** Aggregate device of DHCP interfaces. It contains aggregate counters from @@ -107,6 +146,17 @@ static dhcp_message_type_t monitored_msgs[] = { DHCP_MESSAGE_TYPE_ACK }; +void update_vlan_mapping(std::string vlan, std::shared_ptr mConfigDbPtr) { + auto match_pattern = std::string("VLAN_MEMBER|") + vlan + std::string("|*"); + auto keys = mConfigDbPtr->keys(match_pattern); + for (auto &itr : keys) { + auto found = itr.find_last_of('|'); + auto interface = itr.substr(found + 1); + vlan_map[interface] = vlan; + syslog(LOG_INFO, "add <%s, %s> into interface vlan map\n", interface.c_str(), vlan.c_str()); + } +} + /** Number of monitored DHCP message type */ static uint8_t monitored_msg_sz = sizeof(monitored_msgs) / sizeof(*monitored_msgs); @@ -163,9 +213,62 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context, } /** - * @code read_callback(fd, event, arg); + * @code client_packet_handler(dhcp_device_context_t *context, ssize_t buffer_sz); + * + * @brief packet handler to process received rx and tx packets + * + * @param context pointer to device (interface) context + * @param buffer_sz buffer that stores received packet data + * + * @return none + */ +static void client_packet_handler(dhcp_device_context_t *context, ssize_t buffer_sz) +{ + struct ether_header *ethhdr = (struct ether_header*) context->buffer; + struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET); + struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET); + uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET; + int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE; + + if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) && + (ntohs(udp->len) > DHCP_OPTIONS_HEADER_SIZE)) + { + int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ? + ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr); + int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE; + const u_char *dhcp_option = context->buffer + dhcp_option_offset; + dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] && + ethhdr->ether_shost[1] == context->mac[1] && + ethhdr->ether_shost[2] == context->mac[2] && + ethhdr->ether_shost[3] == context->mac[3] && + ethhdr->ether_shost[4] == context->mac[4] && + ethhdr->ether_shost[5] == context->mac[5]) ? + DHCP_TX : DHCP_RX; + int offset = 0; + while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) { + if (dhcp_option[offset] == OPTION_DHCP_MESSAGE_TYPE) { + if (offset < (dhcp_option_sz + 2)) { + handle_dhcp_option_53(context, &dhcp_option[offset], dir, iphdr, dhcphdr); + } + break; // break while loop since we are only interested in Option 53 + } + + if (dhcp_option[offset] == 0) { // DHCP Option Padding + offset++; + } else { + offset += dhcp_option[offset + 1] + 2; + } + } + } else { + syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options", + context->intf, buffer_sz); + } +} + +/** + * @code read_tx_callback(fd, event, arg); * - * @brief callback for libevent which is called every time out in order to read queued packet capture + * @brief callback for libevent which is called every time out in order to read queued outgoing packet capture * * @param fd socket to read from * @param event libevent triggered event @@ -173,68 +276,20 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context, * * @return none */ -static void read_callback(int fd, short event, void *arg) +static void read_tx_callback(int fd, short event, void *arg) { dhcp_device_context_t *context = (dhcp_device_context_t*) arg; ssize_t buffer_sz; - while ((event == EV_READ) && - ((buffer_sz = recv(fd, context->buffer, context->snaplen, MSG_DONTWAIT)) > 0)) { - struct ether_header *ethhdr = (struct ether_header*) context->buffer; - struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET); - struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET); - uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET; - int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE; - - if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) && - (ntohs(udp->len) > DHCP_OPTIONS_HEADER_SIZE)) { - int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ? - ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr); - int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE; - const u_char *dhcp_option = context->buffer + dhcp_option_offset; - dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] && - ethhdr->ether_shost[1] == context->mac[1] && - ethhdr->ether_shost[2] == context->mac[2] && - ethhdr->ether_shost[3] == context->mac[3] && - ethhdr->ether_shost[4] == context->mac[4] && - ethhdr->ether_shost[5] == context->mac[5]) ? - DHCP_TX : DHCP_RX; - int offset = 0; - int stop_dhcp_processing = 0; - while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) { - switch (dhcp_option[offset]) - { - case 53: - if (offset < (dhcp_option_sz + 2)) { - handle_dhcp_option_53(context, &dhcp_option[offset], dir, iphdr, dhcphdr); - } - stop_dhcp_processing = 1; // break while loop since we are only interested in Option 53 - break; - default: - break; - } - - if (stop_dhcp_processing == 1) { - break; - } - - if (dhcp_option[offset] == 0) { // DHCP Option Padding - offset++; - } else { - offset += dhcp_option[offset + 1] + 2; - } - } - } else { - syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options", - context->intf, buffer_sz); - } + while ((buffer_sz = recv(fd, context->buffer, context->snaplen, MSG_DONTWAIT)) > 0) { + client_packet_handler(context, buffer_sz); } } /** - * @code read_callback_dual_tor(fd, event, arg); + * @code read_rx_callback(fd, event, arg); * - * @brief callback for libevent which is called every time out in order to read queued packet capture when dual tor mode is enabled + * @brief callback for libevent which is called every time out in order to read queued incoming packet capture * * @param fd socket to read from * @param event libevent triggered event @@ -242,72 +297,37 @@ static void read_callback(int fd, short event, void *arg) * * @return none */ -static void read_callback_dual_tor(int fd, short event, void *arg) +static void read_rx_callback(int fd, short event, void *arg) { dhcp_device_context_t *context = (dhcp_device_context_t*) arg; ssize_t buffer_sz; struct sockaddr_ll sll; socklen_t slen = sizeof sll; - while ((event == EV_READ) && - ((buffer_sz = recvfrom(fd, context->buffer, context->snaplen, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0)) + while ((buffer_sz = recvfrom(fd, context->buffer, context->snaplen, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0) { - std::string member_table = std::string("VLAN_MEMBER|") + context->intf + "|"; char interfaceName[IF_NAMESIZE]; - char *interface = if_indextoname(sll.sll_ifindex, interfaceName); - std::string state; - std::string intf(interface); - mStateDbMuxTablePtr->hget(intf, "state", state); - if (state != "standby" && configDb.exists(member_table.append(interface))) { - struct ether_header *ethhdr = (struct ether_header*) context->buffer; - struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET); - struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET); - uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET; - int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE; - - if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) && - (ntohs(udp->len) > DHCP_OPTIONS_HEADER_SIZE)) - { - int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ? - ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr); - int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE; - const u_char *dhcp_option = context->buffer + dhcp_option_offset; - dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] && - ethhdr->ether_shost[1] == context->mac[1] && - ethhdr->ether_shost[2] == context->mac[2] && - ethhdr->ether_shost[3] == context->mac[3] && - ethhdr->ether_shost[4] == context->mac[4] && - ethhdr->ether_shost[5] == context->mac[5]) ? - DHCP_TX : DHCP_RX; - int offset = 0; - int stop_dhcp_processing = 0; - while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) { - switch (dhcp_option[offset]) - { - case 53: - if (offset < (dhcp_option_sz + 2)) { - handle_dhcp_option_53(context, &dhcp_option[offset], dir, iphdr, dhcphdr); - } - stop_dhcp_processing = 1; // break while loop since we are only interested in Option 53 - break; - default: - break; - } - - if (stop_dhcp_processing == 1) { - break; - } - - if (dhcp_option[offset] == 0) { // DHCP Option Padding - offset++; - } else { - offset += dhcp_option[offset + 1] + 2; - } - } - } else { - syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options", - context->intf, buffer_sz); + if (if_indextoname(sll.sll_ifindex, interfaceName) == NULL) { + syslog(LOG_WARNING, "invalid input interface index %d\n", sll.sll_ifindex); + continue; + } + std::string intf(interfaceName); + auto vlan = vlan_map.find(intf); + if (vlan == vlan_map.end()) { + if (intf.find(CLIENT_IF_PREFIX) != std::string::npos) { + syslog(LOG_WARNING, "invalid input interface %s\n", interfaceName); + } + continue; + } + + if (dual_tor_sock) { + std::string state; + mStateDbMuxTablePtr->hget(intf, "state", state); + if (state != "standby") { + client_packet_handler(context, buffer_sz); } + } else { + client_packet_handler(context, buffer_sz); } } } @@ -495,22 +515,33 @@ static int init_socket(dhcp_device_context_t *context, const char *intf) int rv = -1; do { - context->sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); - if (context->sock < 0) { + context->rx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); + context->tx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); + if (context->rx_sock < 0 || context->tx_sock < 0) { syslog(LOG_ALERT, "socket: failed to open socket with '%s'\n", strerror(errno)); - break; + exit(1); } - struct sockaddr_ll addr; - memset(&addr, 0, sizeof(addr)); - addr.sll_ifindex = 0; // any interface - addr.sll_family = AF_PACKET; - addr.sll_protocol = htons(ETH_P_ALL); - if (bind(context->sock, (struct sockaddr *) &addr, sizeof(addr))) { + struct sockaddr_ll rx_addr; + memset(&rx_addr, 0, sizeof(rx_addr)); + rx_addr.sll_ifindex = 0; // any interface + rx_addr.sll_family = AF_PACKET; + rx_addr.sll_protocol = htons(ETH_P_ALL); + if (bind(context->rx_sock, (struct sockaddr *) &rx_addr, sizeof(rx_addr))) { syslog(LOG_ALERT, "bind: failed to bind to interface '%s' with '%s'\n", intf, strerror(errno)); break; } + struct sockaddr_ll tx_addr; + memset(&tx_addr, 0, sizeof(tx_addr)); + tx_addr.sll_ifindex = if_nametoindex(intf); + tx_addr.sll_family = AF_PACKET; + tx_addr.sll_protocol = htons(ETH_P_ALL); + if (bind(context->tx_sock, (struct sockaddr *) &tx_addr, sizeof(tx_addr))) { + syslog(LOG_ALERT, "bind: failed to bind to interface '%s' with '%s'\n", intf, strerror(errno)); + exit(1); + } + strncpy(context->intf, intf, sizeof(context->intf) - 1); context->intf[sizeof(context->intf) - 1] = '\0'; @@ -644,17 +675,18 @@ int dhcp_device_start_capture(dhcp_device_context_t *context, in_addr_t giaddr_ip) { int rv = -1; - struct event *ev; + struct event *rx_ev; + struct event *tx_ev; do { if (context == NULL) { syslog(LOG_ALERT, "NULL interface context pointer'\n"); - break; + exit(1); } if (snaplen < UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) { syslog(LOG_ALERT, "dhcp_device_start_capture(%s): snap length is too low to capture DHCP options", context->intf); - break; + exit(1); } context->giaddr_ip = giaddr_ip; @@ -662,25 +694,31 @@ int dhcp_device_start_capture(dhcp_device_context_t *context, context->buffer = (uint8_t *) malloc(snaplen); if (context->buffer == NULL) { syslog(LOG_ALERT, "malloc: failed to allocate memory for socket buffer '%s'\n", strerror(errno)); - break; + exit(1); } context->snaplen = snaplen; - if (setsockopt(context->sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_sock_bfp, sizeof(dhcp_sock_bfp)) != 0) { + if (setsockopt(context->rx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_inbound_sock_bfp, sizeof(dhcp_inbound_sock_bfp)) != 0) { syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno)); - break; + exit(1); } - if (dual_tor_sock) - ev = event_new(base, context->sock, EV_READ | EV_PERSIST, read_callback_dual_tor, context); - else - ev = event_new(base, context->sock, EV_READ | EV_PERSIST, read_callback, context); + if (setsockopt(context->tx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_outbound_sock_bfp, sizeof(dhcp_outbound_sock_bfp)) != 0) { + syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno)); + exit(1); + } + + update_vlan_mapping(context->intf, mConfigDbPtr); - if (ev == NULL) { + rx_ev = event_new(base, context->rx_sock, EV_READ | EV_PERSIST, read_rx_callback, context); + tx_ev = event_new(base, context->tx_sock, EV_READ | EV_PERSIST, read_tx_callback, context); + + if (rx_ev == NULL || tx_ev == NULL) { syslog(LOG_ALERT, "event_new: failed to allocate memory for libevent event '%s'\n", strerror(errno)); - break; + exit(1); } - event_add(ev, NULL); + event_add(rx_ev, NULL); + event_add(tx_ev, NULL); rv = 0; } while (0); diff --git a/src/dhcpmon/src/dhcp_device.h b/src/dhcpmon/src/dhcp_device.h index a2b2a789fca6..2e376ac77e6f 100644 --- a/src/dhcpmon/src/dhcp_device.h +++ b/src/dhcpmon/src/dhcp_device.h @@ -35,6 +35,11 @@ typedef enum DHCP_MESSAGE_TYPE_COUNT } dhcp_message_type_t; +enum +{ + OPTION_DHCP_MESSAGE_TYPE = 53, +}; + /** packet direction */ typedef enum { @@ -71,7 +76,8 @@ typedef enum /** DHCP device (interface) context */ typedef struct { - int sock; /** Raw socket associated with this device/interface */ + int rx_sock; /** Raw socket associated with this device/interface to count rx packets */ + int tx_sock; /** Raw socket associated with this device/interface to count tx packets*/ in_addr_t ip; /** network address of this device (interface) */ uint8_t mac[ETHER_ADDR_LEN]; /** hardware address of this device (interface) */ in_addr_t giaddr_ip; /** Gateway IP address */ diff --git a/src/dhcpmon/src/dhcp_mon.cpp b/src/dhcpmon/src/dhcp_mon.cpp index 4860b2b06a55..662f507c2b5e 100644 --- a/src/dhcpmon/src/dhcp_mon.cpp +++ b/src/dhcpmon/src/dhcp_mon.cpp @@ -99,7 +99,7 @@ static void check_dhcp_relay_health(dhcp_mon_state_t *state_data) case DHCP_MON_STATUS_UNHEALTHY: if (++state_data->count > dhcp_unhealthy_max_count) { auto duration = state_data->count * window_interval_sec; - std::string vlan(context->intf); + std::string vlan(context->intf); syslog(LOG_ALERT, state_data->msg, duration, context->intf); if (state_data->check_type == DHCP_MON_CHECK_POSITIVE) { event_params_t params = {