From 077fb392fe8b824ad523d3a07ac83ad2972a939e Mon Sep 17 00:00:00 2001 From: lkunjumon Date: Thu, 27 May 2021 07:38:05 +0530 Subject: [PATCH] Updated pmon2 sfp support --- .../db98cx8540/sonic_platform/chassis.py | 130 +++++++++++++++++- .../db98cx8540/sonic_platform/eeprom.py | 2 +- .../db98cx8540/sonic_platform/sfp.py | 122 +++++++++------- .../db98cx8540/sonic_platform/sfp_event.py | 21 ++- 4 files changed, 216 insertions(+), 59 deletions(-) diff --git a/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/chassis.py b/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/chassis.py index df24d90aa..fe230e658 100644 --- a/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/chassis.py +++ b/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/chassis.py @@ -20,6 +20,104 @@ SFP_PORT_START = 1 SFP_PORT_END = 132 PORT_END = 132 + + +profile_16x400G = { + 0:"0x70,4", 1:"0x70,4", 2:"0x70,4", 3:"0x70,4", 4:"0x70,4", 5:"0x70,4", 6:"0x70,4", 7:"0x70,4", + 8:"0x70,5", 9:"0x70,5", 10:"0x70,5", 11:"0x70,5", 12:"0x70,5", 13:"0x70,5", 14:"0x70,5", 15:"0x70,5", + 16:"0x70,6", 17:"0x70,6", 18:"0x70,6", 19:"0x70,6", 20:"0x70,6", 21:"0x70,6", 22:"0x70,6", 23:"0x70,6", + 24:"0x70,7", 25:"0x70,7", 26:"0x70,7", 27:"0x70,7", 28:"0x70,7", 29:"0x70,7", 30:"0x70,7", 31:"0x70,7", + 32:"0x70,0", 33:"0x70,0", 34:"0x70,0", 35:"0x70,0", 36:"0x70,0", 37:"0x70,0", 38:"0x70,0", 39:"0x70,0", + 40:"0x70,1", 41:"0x70,1", 42:"0x70,1", 43:"0x70,1", 44:"0x70,1", 45:"0x70,1", 46:"0x70,1", 47:"0x70,1", + 48:"0x70,2", 49:"0x70,2", 50:"0x70,2", 51:"0x70,2", 52:"0x70,2", 53:"0x70,2", 54:"0x70,2", 55:"0x70,2", + 56:"0x70,3", 57:"0x70,3", 58:"0x70,3", 59:"0x70,3", 60:"0x70,3", 61:"0x70,3", 62:"0x70,3", 63:"0x70,3", + 64:"0x71,4", 65:"0x71,4", 66:"0x71,4", 67:"0x71,4", 68:"0x71,4", 69:"0x71,4", 70:"0x71,4", 71:"0x71,4", + 72:"0x71,5", 73:"0x71,5", 74:"0x71,5", 75:"0x71,5", 76:"0x71,5", 77:"0x71,5", 78:"0x71,5", 79:"0x71,5", + 80:"0x71,6", 81:"0x71,6", 82:"0x71,6", 83:"0x71,6", 84:"0x71,6", 85:"0x71,6", 86:"0x71,6", 87:"0x71,6", + 88:"0x71,7", 89:"0x71,7", 90:"0x71,7", 91:"0x71,7", 92:"0x71,7", 93:"0x71,7", 94:"0x71,7", 95:"0x71,7", + 96:"0x71,0", 97:"0x71,0", 98:"0x71,0", 99:"0x71,0", 100:"0x71,0", 101:"0x71,0", 102:"0x71,0", 103:"0x71,0", +104:"0x71,1", 105:"0x71,1", 106:"0x71,1", 107:"0x71,1", 108:"0x71,1", 109:"0x71,1", 110:"0x71,1", 111:"0x71,1", +112:"0x71,2", 113:"0x71,2", 114:"0x71,2", 115:"0x71,2", 116:"0x71,2", 117:"0x71,2", 118:"0x71,2", 119:"0x71,2", +120:"0x71,3", 121:"0x71,3", 122:"0x71,3", 123:"0x71,3", 124:"0x71,3", 125:"0x71,3", 126:"0x71,3", 127:"0x71,3", +128:"0x74,4", 129:"0x74,5" } + +profile_64x25G = { + 0:"0x70,4", 1:"0x70,4", 2:"0x70,4", 3:"0x70,4", 4:"0x70,5", 5:"0x70,5", 6:"0x70,5", 7:"0x70,5", + 8:"0x70,6", 9:"0x70,6", 10:"0x70,6", 11:"0x70,6", 12:"0x70,7", 13:"0x70,7", 14:"0x70,7", 15:"0x70,7", + 16:"0x70,0", 17:"0x70,0", 18:"0x70,0", 19:"0x70,0", 20:"0x70,1", 21:"0x70,1", 22:"0x70,1", 23:"0x70,1", + 24:"0x70,2", 25:"0x70,2", 26:"0x70,2", 27:"0x70,2", 28:"0x70,3", 29:"0x70,3", 30:"0x70,3", 31:"0x70,3", + 32:"0x71,4", 33:"0x71,4", 34:"0x71,4", 35:"0x71,4", 36:"0x71,5", 37:"0x71,5", 38:"0x71,5", 39:"0x71,5", + 40:"0x71,6", 41:"0x71,6", 42:"0x71,6", 43:"0x71,6", 44:"0x71,7", 45:"0x71,7", 46:"0x71,7", 47:"0x71,7", + 48:"0x71,0", 49:"0x71,0", 50:"0x71,0", 51:"0x71,0", 52:"0x71,1", 53:"0x71,1", 54:"0x71,1", 55:"0x71,1", + 56:"0x71,2", 57:"0x71,2", 58:"0x71,2", 59:"0x71,2", 60:"0x71,3", 61:"0x71,3", 62:"0x71,3", 63:"0x71,3", + 64:"0x74,4", 65:"0x74,5" } + +profile_32x25G = { + 0:"0x70,4", 1:"0x70,4", 2:"0x70,5", 3:"0x70,5", 4:"0x70,6", 5:"0x70,6", 6:"0x70,7", 7:"0x70,7", + 8:"0x70,0", 9:"0x70,0", 10:"0x70,1", 11:"0x70,1", 12:"0x70,2", 13:"0x70,2", 14:"0x70,3", 15:"0x70,3", + 16:"0x71,4", 17:"0x71,4", 18:"0x71,5", 19:"0x71,5", 20:"0x71,6", 21:"0x71,6", 22:"0x71,7", 23:"0x71,7", + 24:"0x71,0", 25:"0x71,0", 26:"0x71,1", 27:"0x71,1", 28:"0x71,2", 29:"0x71,2", 30:"0x71,3", 31:"0x71,3", + 32:"0x74,4", 33:"0x74,5" } + +profile_16x25G = { + 0:"0x70,4", 1:"0x70,5", 2:"0x70,6", 3:"0x70,7", 4:"0x70,0", 5:"0x70,1", 6:"0x70,2", 7:"0x70,3", + 8:"0x71,4", 9:"0x71,5", 10:"0x71,6", 11:"0x71,7", 12:"0x71,0", 13:"0x71,1", 14:"0x71,2", 15:"0x71,3", +16:"0x74,4", 17:"0x74,5" } + +profile_16x25G_ixia = { + 0:"0x70,4", 1:"0x70,4", 2:"0x70,4", 3:"0x70,4", 4:"0x70,5", 5:"0x70,5", 6:"0x70,5", 7:"0x70,5", + 8:"0x70,6", 9:"0x70,6", 10:"0x70,6", 11:"0x70,6", 12:"0x70,7", 13:"0x70,7", 14:"0x70,7", 15:"0x70,7", +16:"0x74,4", 17:"0x74,5" } + +profile_24x25G_4x200G = { + 0:"0x70,4", 1:"0x70,4", 2:"0x70,5", 3:"0x70,5", 4:"0x70,6", 5:"0x70,6", 6:"0x70,7", 7:"0x70,7", + 8:"0x70,0", 9:"0x70,0", 10:"0x70,1", 11:"0x70,1", 12:"0x70,2", 13:"0x70,2", 14:"0x70,3", 15:"0x70,3", + 16:"0x71,4", 17:"0x71,4", 18:"0x71,5", 19:"0x71,5", 20:"0x71,6", 21:"0x71,6", 22:"0x71,7", 23:"0x71,7", + 24:"0x71,0", 25:"0x71,0", 26:"0x71,0", 27:"0x71,0", 28:"0x71,1", 29:"0x71,1", 30:"0x71,1", 31:"0x71,1", + 32:"0x71,2", 33:"0x71,2", 34:"0x71,2", 35:"0x71,2", 36:"0x71,3", 37:"0x71,3", 38:"0x71,3", 39:"0x71,3", + 40:"0x74,4", 41:"0x74,5" } + +profile_24x25G_8x200G = { + 0:"0x70,4", 1:"0x70,4", 2:"0x70,5", 3:"0x70,5", 4:"0x70,6", 5:"0x70,6", 6:"0x70,7", 7:"0x70,7", + 8:"0x70,0", 9:"0x70,0", 10:"0x70,1", 11:"0x70,1", 12:"0x70,2", 13:"0x70,2", 14:"0x70,3", 15:"0x70,3", + 16:"0x71,4", 17:"0x71,4", 18:"0x71,5", 19:"0x71,5", 20:"0x71,6", 21:"0x71,6", 22:"0x71,7", 23:"0x71,7", + 24:"0x71,0", 25:"0x71,0", 26:"0x71,0", 27:"0x71,0", 28:"0x71,0", 29:"0x71,0", 30:"0x71,0", 31:"0x71,0", + 32:"0x71,1", 33:"0x71,1", 34:"0x71,1", 35:"0x71,1", 36:"0x71,1", 37:"0x71,1", 38:"0x71,1", 39:"0x71,1", + 40:"0x71,2", 41:"0x71,2", 42:"0x71,2", 43:"0x71,2", 44:"0x71,2", 45:"0x71,2", 46:"0x71,2", 47:"0x71,2", + 48:"0x71,3", 49:"0x71,3", 50:"0x71,3", 51:"0x71,3", 52:"0x71,3", 53:"0x71,3", 54:"0x71,3", 55:"0x71,3", + 56:"0x74,4", 57:"0x74,5" } + +profile_48x25G_8x100G = { + 0:"0x70,4", 1:"0x70,4", 2:"0x70,4", 3:"0x70,4", 4:"0x70,5", 5:"0x70,5", 6:"0x70,5", 7:"0x70,5", + 8:"0x70,6", 9:"0x70,6", 10:"0x70,6", 11:"0x70,6", 12:"0x70,7", 13:"0x70,7", 14:"0x70,7", 15:"0x70,7", + 16:"0x70,0", 17:"0x70,0", 18:"0x70,0", 19:"0x70,0", 20:"0x70,1", 21:"0x70,1", 22:"0x70,1", 23:"0x70,1", + 24:"0x70,2", 25:"0x70,2", 26:"0x70,2", 27:"0x70,2", 28:"0x70,3", 29:"0x70,3", 30:"0x70,3", 31:"0x70,3", + 32:"0x71,4", 33:"0x71,4", 34:"0x71,4", 35:"0x71,4", 36:"0x71,5", 37:"0x71,5", 38:"0x71,5", 39:"0x71,5", + 40:"0x71,6", 41:"0x71,6", 42:"0x71,6", 43:"0x71,6", 44:"0x71,7", 45:"0x71,7", 46:"0x71,7", 47:"0x71,7", + 48:"0x71,0", 49:"0x71,0", 50:"0x71,0", 51:"0x71,0", 52:"0x71,0", 53:"0x71,0", 54:"0x71,0", 55:"0x71,0", + 56:"0x71,1", 57:"0x71,1", 58:"0x71,1", 59:"0x71,1", 60:"0x71,1", 61:"0x71,1", 62:"0x71,1", 63:"0x71,1", + 64:"0x71,2", 65:"0x71,2", 66:"0x71,2", 67:"0x71,2", 68:"0x71,2", 69:"0x71,2", 70:"0x71,2", 71:"0x71,2", + 72:"0x71,3", 73:"0x71,3", 74:"0x71,3", 75:"0x71,3", 76:"0x71,3", 77:"0x71,3", 78:"0x71,3", 79:"0x71,3", + 80:"0x74,4", 81:"0x74,5" } + +sfputil_profiles = { + "FALCON16X25G":profile_16x25G, + "FC16x25GIXIA":profile_16x25G_ixia, + "FALCON16x400G":profile_16x400G, + "FALCON128x50G":profile_16x400G, + "FALCON64x100G":profile_16x400G, + "FC16x100G8x400G":profile_16x400G, + "FC24x100G4x400G":profile_16x400G, + "FC32x100G8x400G":profile_16x400G, + "FALCON64x25G":profile_64x25G, + "FALCON32x25G64":profile_32x25G, + "FC24x254x200G64":profile_24x25G_4x200G, + "FC24x258x100G64":profile_24x25G_8x200G, + "FC48x10G8x100G":profile_48x25G_8x100G, + "FC48x25G8x100G":profile_48x25G_8x100G +} + + SYSLOG_IDENTIFIER = "chassis" logger = Logger() @@ -35,6 +133,12 @@ class Chassis(ChassisBase): reset_reason_dict[0x08] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU reset_reason_dict[0x10] = ChassisBase.REBOOT_CAUSE_WATCHDOG + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + HOST_CHK_CMD = "docker > /dev/null 2>&1" + PLATFORM = "arm64-marvell_db98cx8540_16cd-r0" + HWSKU = "db98cx8540_16cd" + def __init__(self): ChassisBase.__init__(self) @@ -44,20 +148,40 @@ def __init__(self): self.SFP_PORT_START = SFP_PORT_START self.SFP_PORT_END = SFP_PORT_END self.PORT_END = PORT_END + + sai_profile_path=self.__get_path_to_sai_profile_file() + cmd = "cat " + sai_profile_path + " | grep hwId | cut -f2 -d=" + port_profile = os.popen(cmd).read() + self._port_profile = port_profile.split("\n")[0] + + if not os.path.exists("/sys/bus/i2c/devices/0-0050") : + os.system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-0/new_device") eeprom_path = '/sys/bus/i2c/devices/0-0050/eeprom' for index in range(self.SFP_PORT_START, self.SFP_PORT_END+1): i2cdev = 0 port_eeprom_path = eeprom_path + profile = sfputil_profiles[self._port_profile] if not os.path.exists(port_eeprom_path): logger.log_info(" DEBUG - path %s -- did not exist " % port_eeprom_path ) - sfp_node = Sfp(index, 'SFP', port_eeprom_path, i2cdev ) - self._sfp_list.append(sfp_node) - + if index in profile: + sfp_node = Sfp(index, 'SFP', port_eeprom_path, i2cdev ) + self._sfp_list.append(sfp_node) self.sfp_event_initialized = False + # Instantiate ONIE system eeprom object self._eeprom = Eeprom() + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_sai_profile_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "sai.profile"]) + + def get_sfp(self, index): """ Retrieves sfp represented by (1-based) index diff --git a/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/eeprom.py b/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/eeprom.py index 1a0be9efd..0111150b3 100644 --- a/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/eeprom.py +++ b/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/eeprom.py @@ -47,7 +47,7 @@ def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0): if self.is_sys_eeprom: self.start_offset = 0 - self.eeprom_path = self.I2C_DIR + "i2c-0/0-0050/eeprom" + self.eeprom_path = "/etc/sonic/eeprom" # System EEPROM is in ONIE TlvInfo EEPROM format super(Eeprom, self).__init__(self.eeprom_path, self.start_offset, '', True) diff --git a/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/sfp.py b/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/sfp.py index a9d80bd2b..df25349fd 100644 --- a/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/sfp.py +++ b/platform/marvell-arm64/sonic-platform-db98cx8540-16cd/db98cx8540/sonic_platform/sfp.py @@ -25,7 +25,7 @@ try: import smbus -except ImportError as e: +except ImportError, e: smbus_present = 0 profile_16x400G = { @@ -123,10 +123,8 @@ "FC48x25G8x100G":profile_48x25G_8x100G } - INFO_OFFSET = 128 DOM_OFFSET = 0 - # definitions of the offset and width for values in XCVR info eeprom XCVR_INTFACE_BULK_OFFSET = 0 XCVR_INTFACE_BULK_WIDTH_QSFP = 20 @@ -253,50 +251,33 @@ SFP_TYPE = "SFP" QSFP_TYPE = "QSFP" OSFP_TYPE = "OSFP" - -# SFP PORT numbers -SFP_PORT_START = 1 -SFP_PORT_END = 132 - SYSLOG_IDENTIFIER = "xcvrd" logger = Logger(SYSLOG_IDENTIFIER) class Sfp(SfpBase): - #Hwsku and profile.ini path PLATFORM_ROOT_PATH = "/usr/share/sonic/device" PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" HOST_CHK_CMD = "docker > /dev/null 2>&1" - #Define PLATFORM_NAME and HWSKU PLATFORM = "arm64-marvell_db98cx8540_16cd-r0" HWSKU = "db98cx8540_16cd" - #Default Profile - _port_profile = "FALCON16X25G" _port_start = 1 _port_end = 132 - ports_in_block = 132 port_to_i2c_mapping = 0 - _port_to_eeprom_mapping = {} - _qsfp_ports = range(_port_start, ports_in_block + 1) def __init__(self, index, sfp_type, eeprom_path, port_i2c_map): - if not os.path.exists("/sys/bus/i2c/devices/0-0050") : - os.system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-0/new_device") - eeprom_path = '/sys/bus/i2c/devices/0-0050/eeprom' - - sai_profile_path=self.__get_path_to_sai_profile_file() - cmd = "cat " + path + " | grep hwId | cut -f2 -d=" - port_profile = os.popen(cmd).read() - self._port_profile = port_profile.split("\n")[0] - #SFP Initilization SfpBase.__init__(self) - self.index = index + self.index = index self.port_num = index - self.sfp_type = sfp_type - self.eeprom_path = eeprom_path - self.port_to_i2c_mapping = port_i2c_map + self.sfp_type = sfp_type + self.eeprom_path = eeprom_path + self.port_to_i2c_mapping = port_i2c_map self.port_name = sfp_type + str(index) self.port_to_eeprom_mapping = {} self.port_to_eeprom_mapping[index] = eeprom_path + sai_profile_path = self.__get_path_to_sai_profile_file() + cmd = "cat " + sai_profile_path + " | grep hwId | cut -f2 -d=" + port_profile = os.popen(cmd).read() + self._port_profile = port_profile.split("\n")[0] self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', @@ -324,7 +305,6 @@ def __init__(self, index, sfp_type, eeprom_path, port_i2c_map): self.dom_rx_power_supported = False self.dom_tx_power_supported = False self.calibration = 0 - self._dom_capability_detect() def __convert_string_to_num(self, value_str): @@ -351,26 +331,25 @@ def __is_host(self): return os.system(self.HOST_CHK_CMD) == 0 def i2c_set(self, device_addr, offset, value): - if smbus_present == 0: - cmd = "i2cset -y 0 " + hex(device_addr) + " " + hex(offset) + " " + hex(value) - os.system(cmd) - else: - bus = smbus.SMBus(0) - bus.write_byte_data(device_addr, offset, value) + if smbus_present == 0: + cmd = "i2cset -y 0 " + hex(device_addr) + " " + hex(offset) + " " + hex(value) + os.system(cmd) + else: + bus = smbus.SMBus(0) + bus.write_byte_data(device_addr, offset, value) def __get_path_to_port_config_file(self): platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) hwsku_path = "/".join([platform_path, self.HWSKU] ) if self.__is_host() else self.PMON_HWSKU_PATH return "/".join([hwsku_path, "port_config.ini"]) - + def __get_path_to_sai_profile_file(self): platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) hwsku_path = "/".join([platform_path, self.HWSKU] ) if self.__is_host() else self.PMON_HWSKU_PATH return "/".join([hwsku_path, "sai.profile"]) - def __read_eeprom_specific_bytes(self, offset, num_bytes): sysfsfile_eeprom = None @@ -378,7 +357,7 @@ def __read_eeprom_specific_bytes(self, offset, num_bytes): for i in range(0, num_bytes): eeprom_raw.append("0x00") - sysfs_sfp_i2c_client_eeprom_path = '/sys/bus/i2c/devices/0-0050/eeprom' + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] try: sysfsfile_eeprom = open( @@ -830,6 +809,7 @@ def get_transceiver_bulk_status(self): transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( dom_channel_monitor_data['data']['TXPower']['value']) + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() transceiver_dom_info_dict['reset_status'] = self.get_reset_status() transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() @@ -1004,7 +984,6 @@ def get_rx_los(self): A Boolean, True if SFP has RX LOS, False if not. """ return False - def get_tx_fault(self): """ Retrieves the TX fault status of SFP @@ -1012,7 +991,6 @@ def get_tx_fault(self): A Boolean, True if SFP has TX fault, False if not Note : TX fault status is lached until a call to get_tx_fault or a reset. """ - return False def get_tx_disable(self): @@ -1022,7 +1000,7 @@ def get_tx_disable(self): A Boolean, True if tx_disable is enabled, False if disabled """ return False - + def get_tx_disable_channel(self): """ Retrieves the TX disabled channels in this SFP @@ -1032,7 +1010,14 @@ def get_tx_disable_channel(self): As an example, a returned value of 0x5 indicates that channel 0 and channel 2 have been disabled. """ - return False + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled def get_lpmode(self): """ @@ -1054,7 +1039,6 @@ def get_power_override(self): if self.sfp_type == COPPER_TYPE: return False if self.sfp_type == QSFP_TYPE: - offset = 0 sfpd_obj = sff8436Dom() if sfpd_obj is None: return False @@ -1240,7 +1224,6 @@ def reset(self): """ if self.sfp_type == COPPER_TYPE: return False - # Check for invalid port_num if self.port_num < self._port_start or self.port_num > self._port_end: return False @@ -1260,6 +1243,7 @@ def reset(self): reg_file.close() return True + def tx_disable(self, tx_disable): """ Disable SFP TX for all channels @@ -1269,6 +1253,25 @@ def tx_disable(self, tx_disable): Returns: A boolean, True if tx_disable is set successfully, False if not """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True return False def tx_disable_channel(self, channel, disable): @@ -1282,6 +1285,29 @@ def tx_disable_channel(self, channel, disable): Returns: A boolean, True if successful, False if not """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + tx_enable_mask = [0xe, 0xd, 0xb, 0x7] + tx_disable_mask = [0x1, 0x3, 0x7, 0xf] + tx_disable_ctl = channel_state | tx_disable_mask[ + channel] if disable else channel_state & tx_enable_mask[channel] + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True return False def set_lpmode(self, lpmode): @@ -1350,7 +1376,7 @@ def get_name(self): """ sfputil_helper = SfpUtilHelper() sfputil_helper.read_porttab_mappings( - self.__get_path_to_port_config_file()) + self.__get_path_to_port_config_file()) name = sfputil_helper.logical[self.index] or "Unknown" return name @@ -1361,6 +1387,7 @@ def get_presence(self): bool: True if is present, False if not """ port_index = self.port_num-1 + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] profile = sfputil_profiles[self._port_profile] if port_index not in profile: return False @@ -1369,16 +1396,15 @@ def get_presence(self): bin_offset = 1<