From 04e7a2688a6f9c631e1e2186ebca997f5db99c64 Mon Sep 17 00:00:00 2001 From: Kroos Date: Wed, 10 Jun 2026 11:08:19 +0800 Subject: [PATCH] add cpo bailly rlm dom Signed-off-by: Kroos --- setup.py | 8 +- .../sonic_xcvr/api/bailly/bailly_api.py | 105 ----- .../api/{bailly => broadcom}/__init__.py | 0 .../sonic_xcvr/api/broadcom/bailly.py | 378 ++++++++++++++++++ .../codes/{bailly => broadcom}/__init__.py | 0 .../bailly_codes.py => broadcom/bailly.py} | 1 - .../fields/{bailly => broadcom}/__init__.py | 0 .../bailly_consts.py => broadcom/bailly.py} | 55 +-- .../mem_maps/bailly/bailly_mem_map.py | 239 ----------- .../mem_maps/{bailly => broadcom}/__init__.py | 0 .../sonic_xcvr/mem_maps/broadcom/bailly.py | 224 +++++++++++ tests/sonic_xcvr/test_bailly_cmis.py | 225 ++++++++++- 12 files changed, 838 insertions(+), 397 deletions(-) delete mode 100644 sonic_platform_base/sonic_xcvr/api/bailly/bailly_api.py rename sonic_platform_base/sonic_xcvr/api/{bailly => broadcom}/__init__.py (100%) create mode 100644 sonic_platform_base/sonic_xcvr/api/broadcom/bailly.py rename sonic_platform_base/sonic_xcvr/codes/{bailly => broadcom}/__init__.py (100%) rename sonic_platform_base/sonic_xcvr/codes/{bailly/bailly_codes.py => broadcom/bailly.py} (95%) rename sonic_platform_base/sonic_xcvr/fields/{bailly => broadcom}/__init__.py (100%) rename sonic_platform_base/sonic_xcvr/fields/{bailly/bailly_consts.py => broadcom/bailly.py} (61%) delete mode 100644 sonic_platform_base/sonic_xcvr/mem_maps/bailly/bailly_mem_map.py rename sonic_platform_base/sonic_xcvr/mem_maps/{bailly => broadcom}/__init__.py (100%) create mode 100644 sonic_platform_base/sonic_xcvr/mem_maps/broadcom/bailly.py diff --git a/setup.py b/setup.py index ff177bab5..cb0d4360a 100644 --- a/setup.py +++ b/setup.py @@ -43,20 +43,20 @@ 'sonic_platform_base.sonic_xcvr', 'sonic_platform_base.sonic_xcvr.fields', 'sonic_platform_base.sonic_xcvr.fields.public', - 'sonic_platform_base.sonic_xcvr.fields.bailly', + 'sonic_platform_base.sonic_xcvr.fields.broadcom', 'sonic_platform_base.sonic_xcvr.mem_maps', 'sonic_platform_base.sonic_xcvr.mem_maps.public', - 'sonic_platform_base.sonic_xcvr.mem_maps.bailly', + 'sonic_platform_base.sonic_xcvr.mem_maps.broadcom', 'sonic_platform_base.sonic_xcvr.mem_maps.public.cmis', 'sonic_platform_base.sonic_xcvr.mem_maps.public.cmis.pages', 'sonic_platform_base.sonic_xcvr.mem_maps.public.cmis.elsfp', 'sonic_platform_base.sonic_xcvr.mem_maps.public.cmis.elsfp.pages', 'sonic_platform_base.sonic_xcvr.api', 'sonic_platform_base.sonic_xcvr.api.public', - 'sonic_platform_base.sonic_xcvr.api.bailly', + 'sonic_platform_base.sonic_xcvr.api.broadcom', 'sonic_platform_base.sonic_xcvr.codes', 'sonic_platform_base.sonic_xcvr.codes.public', - 'sonic_platform_base.sonic_xcvr.codes.bailly', + 'sonic_platform_base.sonic_xcvr.codes.broadcom', 'sonic_platform_base.sonic_xcvr.utils', 'sonic_platform_base.sonic_xcvr.api.credo', 'sonic_platform_base.sonic_xcvr.mem_maps.credo', diff --git a/sonic_platform_base/sonic_xcvr/api/bailly/bailly_api.py b/sonic_platform_base/sonic_xcvr/api/bailly/bailly_api.py deleted file mode 100644 index 7c1a2d450..000000000 --- a/sonic_platform_base/sonic_xcvr/api/bailly/bailly_api.py +++ /dev/null @@ -1,105 +0,0 @@ -""" - bailly_api.py - - Implementation of Micas Bailly CPO specific in addition to the CMIS specification. -""" -from ..public.cmis import CmisApi -from ...fields.bailly import bailly_consts - -class BaillyApi(CmisApi): - def __init__(self, xcvr_eeprom): - super(BaillyApi, self).__init__(xcvr_eeprom) - - def get_dpinit_pending(self): - ''' - Bailly not supported, return fake value. - ''' - dpinit_pending_dict = {} - for lane in range(self.NUM_CHANNELS): - key = "DPInitPending{}".format(lane + 1) - dpinit_pending_dict[key] = True - return dpinit_pending_dict - - def get_active_apsel_hostlane(self): - ''' - Bailly not supported Deinit, if it is deinit return fake value. - ''' - has_zero = False - current_map = {} - for lane in range(self.NUM_CHANNELS): - lane_key = 'ActiveAppSelLane{}'.format(lane + 1) - app_lane = self.get_application(lane) - current_map[lane_key] = app_lane - if app_lane == 0: - has_zero = True - - if has_zero: - return current_map - else: - normal = super().get_active_apsel_hostlane() - return normal - def _format_revision(self, revision): - if revision is None: - return None - return "{}.{}".format((revision >> 4) & 0xf, revision & 0xf) - - def get_transceiver_info(self): - info = super().get_transceiver_info() - if info is None: - return None - - els_info = self.get_els_info() - cpo_info = els_info.get("cpo_info") - vendor_info = els_info.get("vendor_info") - laser_power_mode = els_info.get("laser_power_mode") - if cpo_info is None and vendor_info is None and laser_power_mode is None: - return info - - if cpo_info is not None: - info.update({ - "els_identifier": cpo_info.get(bailly_consts.CPO_IDENTIFIER), - "els_revision": self._format_revision(cpo_info.get(bailly_consts.CPO_REVISION)), - "els_laser_grid_and_count": cpo_info.get(bailly_consts.LASER_GRID_AND_COUNT), - "els_laser_wavelength_grid": cpo_info.get(bailly_consts.LASER_WAVELENGTH_GRID), - "els_laser_count": cpo_info.get(bailly_consts.LASER_COUNT), - }) - - if vendor_info is not None: - info.update({ - "els_vendor_name": self._strip_str( - vendor_info.get(bailly_consts.VENDOR_NAME_ASCII_FIELD) - ), - "els_vendor_oui": vendor_info.get(bailly_consts.VENDOR_OUI_HEX_FIELD), - "els_vendor_pn": self._strip_str( - vendor_info.get(bailly_consts.VENDOR_PART_NUMBER_ASCII_FIELD) - ), - "els_vendor_rev": self._strip_str( - vendor_info.get(bailly_consts.VENDOR_REVISION_ASCII_FIELD) - ), - "els_vendor_sn": self._strip_str( - vendor_info.get(bailly_consts.VENDOR_SERIAL_NUMBER_ASCII_FIELD) - ), - "els_date_code": self._strip_str( - vendor_info.get(bailly_consts.DATE_CODE_FIELD) - ), - "els_max_power": vendor_info.get(bailly_consts.MAX_POWER_CONSUMPTION_FIELD), - }) - - if laser_power_mode is not None: - info.update({ - "els_laser_power_mode_control": laser_power_mode.get( - bailly_consts.LASER_POWER_MODE_CONTROL_BITS_FIELD - ), - }) - - return info - - def get_els_vendor_info(self): - return self.xcvr_eeprom.read(bailly_consts.CPO_VENDOR_INFO_FIELD) - - def get_els_info(self): - return { - "cpo_info": self.xcvr_eeprom.read(bailly_consts.CPO_INFO_FIELD), - "vendor_info": self.get_els_vendor_info(), - "laser_power_mode": self.xcvr_eeprom.read(bailly_consts.LASER_POWER_MODE_CONTROL_FIELD), - } diff --git a/sonic_platform_base/sonic_xcvr/api/bailly/__init__.py b/sonic_platform_base/sonic_xcvr/api/broadcom/__init__.py similarity index 100% rename from sonic_platform_base/sonic_xcvr/api/bailly/__init__.py rename to sonic_platform_base/sonic_xcvr/api/broadcom/__init__.py diff --git a/sonic_platform_base/sonic_xcvr/api/broadcom/bailly.py b/sonic_platform_base/sonic_xcvr/api/broadcom/bailly.py new file mode 100644 index 000000000..cb7efb399 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/api/broadcom/bailly.py @@ -0,0 +1,378 @@ +""" + bailly.py + + Implementation of Micas Bailly CPO specific in addition to the CMIS specification. +""" +from ..public.cmis import CmisApi +from ...fields.broadcom import bailly + +class BaillyApi(CmisApi): + RLM_THRESHOLD_FIELDS = { + "els_temphighalarm": bailly.RLM_TEMP_HIGH_ALARM_FIELD, + "els_templowalarm": bailly.RLM_TEMP_LOW_ALARM_FIELD, + "els_temphighwarning": bailly.RLM_TEMP_HIGH_WARNING_FIELD, + "els_templowwarning": bailly.RLM_TEMP_LOW_WARNING_FIELD, + "els_vcchighalarm": bailly.RLM_VCC_HIGH_ALARM_FIELD, + "els_vcclowalarm": bailly.RLM_VCC_LOW_ALARM_FIELD, + "els_vcchighwarning": bailly.RLM_VCC_HIGH_WARNING_FIELD, + "els_vcclowwarning": bailly.RLM_VCC_LOW_WARNING_FIELD, + "els_txpowerhighalarm": bailly.RLM_TX_POWER_HIGH_ALARM_FIELD, + "els_txpowerlowalarm": bailly.RLM_TX_POWER_LOW_ALARM_FIELD, + "els_txpowerhighwarning": bailly.RLM_TX_POWER_HIGH_WARNING_FIELD, + "els_txpowerlowwarning": bailly.RLM_TX_POWER_LOW_WARNING_FIELD, + "els_txbiashighalarm": bailly.RLM_TX_BIAS_HIGH_ALARM_FIELD, + "els_txbiashighwarning": bailly.RLM_TX_BIAS_HIGH_WARNING_FIELD, + } + + # CMIS compatibility overrides. + + def __init__(self, xcvr_eeprom): + super(BaillyApi, self).__init__(xcvr_eeprom) + + def get_dpinit_pending(self): + ''' + Bailly not supported, return fake value, always return True + ''' + dpinit_pending_dict = {} + for lane in range(self.NUM_CHANNELS): + key = "DPInitPending{}".format(lane + 1) + dpinit_pending_dict[key] = True + return dpinit_pending_dict + + def get_active_apsel_hostlane(self): + ''' + Bailly not supported 0 appl.When the API detects that Page 0x10 is set to 0, return the value from Page 0x10 instead. + ''' + has_zero = False + current_map = {} + for lane in range(self.NUM_CHANNELS): + lane_key = 'ActiveAppSelLane{}'.format(lane + 1) + app_lane = self.get_application(lane) + current_map[lane_key] = app_lane + if app_lane == 0: + has_zero = True + + if has_zero: + return current_map + else: + normal = super().get_active_apsel_hostlane() + return normal + + # Helper methods. + + def _format_revision(self, revision): + ''' + Format RLM revision byte as major.minor string. + ''' + if revision is None: + return None + return "{}.{}".format((revision >> 4) & 0xf, revision & 0xf) + + def _format_float(self, value): + ''' + Format RLM numeric value to three decimal places. + ''' + if value is None: + return None + if isinstance(value, dict): + return None + return float("{:.3f}".format(value)) + + # RLM single-read APIs. + + def get_rlm_temperature(self): + ''' + This function returns RLM module temperature. + ''' + monitors = self.xcvr_eeprom.read(bailly.CPO_MODULE_MONITORS_FIELD) + if monitors is None: + return None + temperature = monitors.get(bailly.MODULE_TEMPERATURE_MONITOR) + return self._format_float(temperature) + + def get_rlm_vendor_info(self): + ''' + This function returns RLM vendor information. + ''' + return self.xcvr_eeprom.read(bailly.CPO_VENDOR_INFO_FIELD) + + def get_rlm_laser_current(self): + ''' + This function returns RLM laser current monitor values. + ''' + return self.xcvr_eeprom.read(bailly.LASER_CURRENT_MONITOR_FIELD) + + def get_rlm_laser_voltage(self): + ''' + This function returns RLM laser voltage monitor values. + ''' + return self.xcvr_eeprom.read(bailly.LASER_VOLTAGE_MONITOR_FIELD) + + def get_rlm_laser_power(self): + ''' + This function returns RLM laser optical power monitor values. + ''' + return self.xcvr_eeprom.read(bailly.LASER_OPTICAL_POWER_MONITOR_FIELD) + + # RLM aggregate-read APIs. + + def get_rlm_monitor_values(self): + """ + Retrieves RLM DOM sensor values for the RLM laser module + + The returned dictionary contains floating-point values corresponding to + RLM temperature, voltage and TEC current readings, as defined in the + TRANSCEIVER_DOM_SENSOR table in STATE_DB. + + Returns: + Dictionary + """ + monitors = self.xcvr_eeprom.read(bailly.CPO_MODULE_MONITORS_FIELD) + if monitors is None: + return None + + monitor_values = { + "els_temperature": self._format_float(monitors.get(bailly.MODULE_TEMPERATURE_MONITOR)), + "els_voltage": self._format_float(monitors.get(bailly.MODULE_SUPPLY_VOLTAGE_MONITOR)), + "rlm_tec_current": self._format_float(monitors.get(bailly.TEC_CURRENT_MONITOR)), + } + + return monitor_values + + def get_rlm_thresholds(self): + """ + Retrieves RLM threshold values for the RLM laser module + + The returned dictionary contains floating-point values corresponding to + RLM DOM sensor threshold readings, as defined in the + TRANSCEIVER_DOM_THRESHOLD table in STATE_DB. + + Returns: + Dictionary + """ + laser_power_mode = self.xcvr_eeprom.read(bailly.LASER_POWER_MODE_CONTROL_FIELD) + if laser_power_mode is None: + return None + + thresholds = laser_power_mode.get(bailly.THRESHOLD_VALUES_FIELD) + if thresholds is None: + return None + + return { + key: self._format_float(thresholds.get(field)) + for key, field in self.RLM_THRESHOLD_FIELDS.items() + } + + def get_rlm_flags(self): + ''' + This function returns RLM alarm and warning flags. + ''' + module_alarms = self.xcvr_eeprom.read(bailly.MODULE_ALARMS_FIELD) + if module_alarms is None: + return None + + flags = { + "els_tempHAlarm": module_alarms.get(bailly.TEMP_HIGH_ALARM_FLAG), + "els_tempLAlarm": module_alarms.get(bailly.TEMP_LOW_ALARM_FLAG), + "els_tempHWarn": module_alarms.get(bailly.TEMP_HIGH_WARN_FLAG), + "els_tempLWarn": module_alarms.get(bailly.TEMP_LOW_WARN_FLAG), + "els_vccHAlarm": module_alarms.get(bailly.VOLTAGE_HIGH_ALARM_FLAG), + "els_vccLAlarm": module_alarms.get(bailly.VOLTAGE_LOW_ALARM_FLAG), + "els_vccHWarn": module_alarms.get(bailly.VOLTAGE_HIGH_WARN_FLAG), + "els_vccLWarn": module_alarms.get(bailly.VOLTAGE_LOW_WARN_FLAG), + } + + return flags + + def get_rlm_status(self): + ''' + This function returns RLM module status flags. + ''' + status = self.xcvr_eeprom.read(bailly.LASER_STATUS_FIELD) + if status is None: + return None + + return { + "els_module_low_power_state": status.get(bailly.MODULE_LOW_POWER_STATE), + "els_interrupt_status": status.get(bailly.INTL_INTERRUPT_STATUS), + } + + def get_rlm_info(self): + ''' + This function returns RLM CPO, vendor and laser power mode information. + ''' + return { + "cpo_info": self.xcvr_eeprom.read(bailly.CPO_INFO_FIELD), + "rlm_vendor_info": self.get_rlm_vendor_info(), + "laser_power_mode": self.xcvr_eeprom.read(bailly.LASER_POWER_MODE_CONTROL_FIELD), + } + + # RLM subset APIs. + + def get_transceiver_dom_real_value(self): + """ + Retrieves DOM sensor values for the RLM laser module + + The returned dictionary extends the parent CMIS DOM sensor values with + RLM sensor readings, as defined in the TRANSCEIVER_DOM_SENSOR table in + STATE_DB. + + Returns: + Dictionary + """ + dom_info = super().get_transceiver_dom_real_value() + if dom_info is None: + dom_info = {} + + rlm_monitors = self.get_rlm_monitor_values() + if rlm_monitors is not None: + dom_info.update({ + key: value for key, value in rlm_monitors.items() + if value is not None + }) + + return dom_info + + def get_transceiver_threshold_info(self): + """ + Retrieves threshold info for the RLM laser module + + The returned dictionary extends the parent CMIS threshold values with RLM + DOM sensor threshold readings, as defined in the TRANSCEIVER_DOM_THRESHOLD + table in STATE_DB. + + Returns: + Dictionary + """ + threshold_info = super().get_transceiver_threshold_info() + if threshold_info is None: + threshold_info = {} + + rlm_thresholds = self.get_rlm_thresholds() + if rlm_thresholds is not None: + threshold_info.update({ + key: value for key, value in rlm_thresholds.items() + if value is not None + }) + + return threshold_info + + def get_transceiver_dom_flags(self): + """ + Retrieves DOM flag values for the RLM laser module + + The returned dictionary extends the parent CMIS DOM flag values with RLM + alarm and warning flags, as defined in the TRANSCEIVER_DOM_FLAG table in + STATE_DB. + + Returns: + Dictionary + """ + dom_flags = super().get_transceiver_dom_flags() + if dom_flags is None: + dom_flags = {} + + rlm_flags = self.get_rlm_flags() + if rlm_flags is not None: + dom_flags.update({ + key: value for key, value in rlm_flags.items() + if value is not None + }) + + return dom_flags + + def get_transceiver_status_flags(self): + """ + Retrieves status flag values for the RLM laser module + + The returned dictionary extends the parent CMIS status flag values with + RLM alarm, warning and module status flags, as defined in status tables + in STATE_DB. + + Returns: + Dictionary + """ + status_flags = super().get_transceiver_status_flags() + if status_flags is None: + status_flags = {} + + rlm_flags = self.get_rlm_flags() + if rlm_flags is not None: + status_flags.update({ + key: value for key, value in rlm_flags.items() + if value is not None + }) + + rlm_status = self.get_rlm_status() + if rlm_status is not None: + status_flags.update({ + key: value for key, value in rlm_status.items() + if value is not None + }) + + return status_flags + + def get_transceiver_info(self): + """ + Retrieves module information with RLM laser module fields + + The returned dictionary extends the parent CMIS module information + with RLM vendor, identifier, revision and laser capability fields. + + Returns: + Dictionary + """ + info = super().get_transceiver_info() + if info is None: + return None + + rlm_info = self.get_rlm_info() + cpo_info = rlm_info.get("cpo_info") + rlm_vendor_info = rlm_info.get("rlm_vendor_info") + laser_power_mode = rlm_info.get("laser_power_mode") + if cpo_info is None and rlm_vendor_info is None and laser_power_mode is None: + return info + + if cpo_info is not None: + info.update({ + "els_identifier": cpo_info.get(bailly.CPO_IDENTIFIER), + "els_revision": self._format_revision(cpo_info.get(bailly.CPO_REVISION)), + "els_laser_count": cpo_info.get(bailly.LASER_COUNT), + "rlm_laser_wavelength_grid": cpo_info.get(bailly.LASER_WAVELENGTH_GRID), + }) + + if rlm_vendor_info is not None: + info.update({ + "els_vendor_name": self._strip_str( + rlm_vendor_info.get(bailly.VENDOR_NAME_ASCII_FIELD) + ), + "els_vendor_oui": rlm_vendor_info.get(bailly.VENDOR_OUI_HEX_FIELD), + "els_vendor_pn": self._strip_str( + rlm_vendor_info.get(bailly.VENDOR_PART_NUMBER_ASCII_FIELD) + ), + "els_vendor_rev": self._strip_str( + rlm_vendor_info.get(bailly.VENDOR_REVISION_ASCII_FIELD) + ), + "els_vendor_sn": self._strip_str( + rlm_vendor_info.get(bailly.VENDOR_SERIAL_NUMBER_ASCII_FIELD) + ), + "els_date_code": self._strip_str( + rlm_vendor_info.get(bailly.DATE_CODE_FIELD) + ), + "els_max_power": rlm_vendor_info.get(bailly.MAX_POWER_CONSUMPTION_FIELD), + }) + + if laser_power_mode is not None: + info.update({ + "rlm_laser_lpmode_control": laser_power_mode.get( + bailly.LASER_POWER_MODE_CONTROL_BITS_FIELD + ), + }) + + return info + + def get_laser_temperature(self): + """ + Bailly has no laser temperature acquisition register, return none. + """ + return None diff --git a/sonic_platform_base/sonic_xcvr/codes/bailly/__init__.py b/sonic_platform_base/sonic_xcvr/codes/broadcom/__init__.py similarity index 100% rename from sonic_platform_base/sonic_xcvr/codes/bailly/__init__.py rename to sonic_platform_base/sonic_xcvr/codes/broadcom/__init__.py diff --git a/sonic_platform_base/sonic_xcvr/codes/bailly/bailly_codes.py b/sonic_platform_base/sonic_xcvr/codes/broadcom/bailly.py similarity index 95% rename from sonic_platform_base/sonic_xcvr/codes/bailly/bailly_codes.py rename to sonic_platform_base/sonic_xcvr/codes/broadcom/bailly.py index 353cb4150..efe04fd2e 100644 --- a/sonic_platform_base/sonic_xcvr/codes/bailly/bailly_codes.py +++ b/sonic_platform_base/sonic_xcvr/codes/broadcom/bailly.py @@ -1,7 +1,6 @@ from ..public.cmis import CmisCodes class BaillyCodes(CmisCodes): - # Vendor specific implementation to be added here XCVR_IDENTIFIERS = { **CmisCodes.XCVR_IDENTIFIERS, 128: 'CPO Bailly', diff --git a/sonic_platform_base/sonic_xcvr/fields/bailly/__init__.py b/sonic_platform_base/sonic_xcvr/fields/broadcom/__init__.py similarity index 100% rename from sonic_platform_base/sonic_xcvr/fields/bailly/__init__.py rename to sonic_platform_base/sonic_xcvr/fields/broadcom/__init__.py diff --git a/sonic_platform_base/sonic_xcvr/fields/bailly/bailly_consts.py b/sonic_platform_base/sonic_xcvr/fields/broadcom/bailly.py similarity index 61% rename from sonic_platform_base/sonic_xcvr/fields/bailly/bailly_consts.py rename to sonic_platform_base/sonic_xcvr/fields/broadcom/bailly.py index a85c94371..73a7f8db1 100644 --- a/sonic_platform_base/sonic_xcvr/fields/bailly/bailly_consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/broadcom/bailly.py @@ -1,4 +1,4 @@ -from ...fields.consts import * # noqa: F401,F403 +from ...fields.consts import * DIAG_BANK_SIZE_SUPPORT_ADVT_FIELD = "BankSizeSupport" @@ -68,34 +68,20 @@ LASER_POWER_MODE_CONTROL_BITS_FIELD = "LaserPowerModeControlBits" CHANNEL_LASER_POWER_MODE_ENABLE = "Channel{}LaserPowerModeEnable" THRESHOLD_VALUES_FIELD = "ThresholdValues" -TEMP_HIGH_ALARM_MSB_FIELD = "TempHighAlarmMSB" -TEMP_HIGH_ALARM_LSB_FIELD = "TempHighAlarmLSB" -TEMP_LOW_ALARM_MSB_FIELD = "TempLowAlarmMSB" -TEMP_LOW_ALARM_LSB_FIELD = "TempLowAlarmLSB" -TEMP_HIGH_WARNING_MSB_FIELD = "TempHighWarningMSB" -TEMP_HIGH_WARNING_LSB_FIELD = "TempHighWarningLSB" -TEMP_LOW_WARNING_MSB_FIELD = "TempLowWarningMSB" -TEMP_LOW_WARNING_LSB_FIELD = "TempLowWarningLSB" -VCC_HIGH_ALARM_MSB_FIELD = "VccHighAlarmMSB" -VCC_HIGH_ALARM_LSB_FIELD = "VccHighAlarmLSB" -VCC_LOW_ALARM_MSB_FIELD = "VccLowAlarmMSB" -VCC_LOW_ALARM_LSB_FIELD = "VccLowAlarmLSB" -VCC_HIGH_WARNING_MSB_FIELD = "VccHighWarningMSB" -VCC_HIGH_WARNING_LSB_FIELD = "VccHighWarningLSB" -VCC_LOW_WARNING_MSB_FIELD = "VccLowWarningMSB" -VCC_LOW_WARNING_LSB_FIELD = "VccLowWarningLSB" -TX_POWER_HIGH_ALARM_MSB_FIELD = "TxPowerHighAlarmMSB" -TX_POWER_HIGH_ALARM_LSB_FIELD = "TxPowerHighAlarmLSB" -TX_POWER_LOW_ALARM_MSB_FIELD = "TxPowerLowAlarmMSB" -TX_POWER_LOW_ALARM_LSB_FIELD = "TxPowerLowAlarmLSB" -TX_POWER_HIGH_WARNING_MSB_FIELD = "TxPowerHighWarningMSB" -TX_POWER_HIGH_WARNING_LSB_FIELD = "TxPowerHighWarningLSB" -TX_POWER_LOW_WARNING_MSB_FIELD = "TxPowerLowWarningMSB" -TX_POWER_LOW_WARNING_LSB_FIELD = "TxPowerLowWarningLSB" -TX_BIAS_HIGH_ALARM_MSB_FIELD = "TxBiasHighAlarmMSB" -TX_BIAS_HIGH_ALARM_LSB_FIELD = "TxBiasHighAlarmLSB" -TX_BIAS_HIGH_WARNING_MSB_FIELD = "TxBiasHighWarningMSB" -TX_BIAS_HIGH_WARNING_LSB_FIELD = "TxBiasHighWarningLSB" +RLM_TEMP_HIGH_ALARM_FIELD = "RlmTempHighAlarm" +RLM_TEMP_LOW_ALARM_FIELD = "RlmTempLowAlarm" +RLM_TEMP_HIGH_WARNING_FIELD = "RlmTempHighWarning" +RLM_TEMP_LOW_WARNING_FIELD = "RlmTempLowWarning" +RLM_VCC_HIGH_ALARM_FIELD = "RlmVccHighAlarm" +RLM_VCC_LOW_ALARM_FIELD = "RlmVccLowAlarm" +RLM_VCC_HIGH_WARNING_FIELD = "RlmVccHighWarning" +RLM_VCC_LOW_WARNING_FIELD = "RlmVccLowWarning" +RLM_TX_POWER_HIGH_ALARM_FIELD = "RlmTxPowerHighAlarm" +RLM_TX_POWER_LOW_ALARM_FIELD = "RlmTxPowerLowAlarm" +RLM_TX_POWER_HIGH_WARNING_FIELD = "RlmTxPowerHighWarning" +RLM_TX_POWER_LOW_WARNING_FIELD = "RlmTxPowerLowWarning" +RLM_TX_BIAS_HIGH_ALARM_FIELD = "RlmTxBiasHighAlarm" +RLM_TX_BIAS_HIGH_WARNING_FIELD = "RlmTxBiasHighWarning" RESERVED_BYTES_FIELD = "ReservedBytes" RESERVED_BYTE_FIELD = "Reserved{}" @@ -108,17 +94,6 @@ LASER_ACTIVE_STATUS = "Laser{}ActiveStatus" LASER_BIAS_WARNING = "Laser{}BiasWarning" LASER_BIAS_ALARM = "Laser{}BiasAlarm" -MODULE_TEMPERATURE_MONITOR_MSB = "ModuleTemperatureMonitorMSB" -MODULE_TEMPERATURE_MONITOR_LSB = "ModuleTemperatureMonitorLSB" -MODULE_SUPPLY_VOLTAGE_MONITOR_MSB = "ModuleSupplyVoltageMonitorMSB" -MODULE_SUPPLY_VOLTAGE_MONITOR_LSB = "ModuleSupplyVoltageMonitorLSB" LASER_CURRENT_MONITOR = "Laser{}CurrentMonitor" -LASER_CURRENT_MONITOR_MSB = "Laser{}CurrentMonitorMSB" -LASER_CURRENT_MONITOR_LSB = "Laser{}CurrentMonitorLSB" LASER_VOLTAGE_MONITOR = "Laser{}VoltageMonitor" LASER_OPTICAL_POWER_MONITOR = "Laser{}OpticalPowerMonitor" -LASER_OPTICAL_POWER_MONITOR_MSB = "Laser{}OpticalPowerMonitorMSB" -LASER_OPTICAL_POWER_MONITOR_LSB = "Laser{}OpticalPowerMonitorLSB" -TEC_CURRENT_MONITOR_MSB = "TecCurrentMonitorMSB" -TEC_CURRENT_MONITOR_LSB = "TecCurrentMonitorLSB" - diff --git a/sonic_platform_base/sonic_xcvr/mem_maps/bailly/bailly_mem_map.py b/sonic_platform_base/sonic_xcvr/mem_maps/bailly/bailly_mem_map.py deleted file mode 100644 index f1fd09f7a..000000000 --- a/sonic_platform_base/sonic_xcvr/mem_maps/bailly/bailly_mem_map.py +++ /dev/null @@ -1,239 +0,0 @@ -""" - bailly_mem_map.py - - Implementation of XcvrMemMap for Bailly extending CMIS Rev 5.0 -""" - -from ..public.cmis import CmisMemMap -from ..public.cmis.pages.page import CmisPage -from ...fields.xcvr_field import ( - CodeRegField, - DateField, - HexRegField, - NumberRegField, - RegBitField, - RegBitsField, - RegGroupField, - StringRegField, -) -from ...fields.consts import * -from ...fields.bailly import bailly_consts - -class _BaillyElsControlPage(CmisPage): - """Bailly-specific fields on CMIS Page 0xB0h""" - def __init__(self, codes, page=0xB0, bank=0): - super().__init__(codes, page=page, bank=bank) - - self.fields[bailly_consts.CPO_INFO_FIELD] = [ - RegGroupField(bailly_consts.CPO_INFO_FIELD, - CodeRegField(bailly_consts.CPO_IDENTIFIER, self.getaddr(128), codes.XCVR_IDENTIFIERS), - NumberRegField(bailly_consts.CPO_REVISION, self.getaddr(129), format="B", size=1), - NumberRegField(bailly_consts.LASER_GRID_AND_COUNT, self.getaddr(130), size=1, format="B"), - CodeRegField(bailly_consts.LASER_WAVELENGTH_GRID, self.getaddr(130), - codes.LASER_WAVELENGTH_GRID, - RegBitField(bailly_consts.BIT4_FIELD, bitpos=4, ro=True) - ), - CodeRegField(bailly_consts.LASER_COUNT, self.getaddr(130), - codes.LASER_COUNT, - RegBitsField(bailly_consts.BITS0_3_FIELD, bitpos=0, size=4, ro=True) - ), - ) - ] - - self.fields[bailly_consts.LASER_CONTROL_FIELD] = [ - RegGroupField(bailly_consts.LASER_CONTROL_FIELD, - NumberRegField(bailly_consts.MODULE_LOW_POWER_CONTROL, self.getaddr(132), - RegBitField(bailly_consts.BIT0_FIELD, bitpos=0, ro=False), size=1, ro=False - ), - NumberRegField(bailly_consts.LASER_DISABLE_CONTROL_7_0, self.getaddr(133), format="B", size=1, ro=False), - NumberRegField(bailly_consts.LASER_DISABLE_CONTROL_15_8, self.getaddr(134), format="B", size=1, ro=False), - RegGroupField(bailly_consts.LASER_DISABLE_CONTROL_FIELD, - *(NumberRegField(bailly_consts.LASER_DISABLE_CONTROL.format(laser), - self.getaddr(133 + laser // 8), - RegBitField(bailly_consts.BIT_FIELD.format(laser % 8), bitpos=laser % 8, ro=False), - size=1, ro=False) - for laser in range(0, 16)) - ), - ) - ] - - self.fields[bailly_consts.LASER_STATUS_FIELD] = [ - RegGroupField(bailly_consts.LASER_STATUS_FIELD, - NumberRegField(bailly_consts.MODULE_STATE_AND_INTERRUPT, self.getaddr(131), size=1, format="B"), - CodeRegField(bailly_consts.MODULE_LOW_POWER_STATE, self.getaddr(131), - codes.POWER_MODE, - RegBitField(bailly_consts.BIT1_FIELD, bitpos=1) - ), - CodeRegField(bailly_consts.INTL_INTERRUPT_STATUS, self.getaddr(131), - codes.INTERRUPT_STATUS, - RegBitField(bailly_consts.BIT0_FIELD, bitpos=0) - ), - NumberRegField(bailly_consts.LASER_ACTIVE_STATUS_7_0, self.getaddr(135), format="B", size=1), - NumberRegField(bailly_consts.LASER_ACTIVE_STATUS_15_8, self.getaddr(136), format="B", size=1), - RegGroupField(bailly_consts.LASER_ACTIVE_STATUS_FIELD, - *(CodeRegField(bailly_consts.LASER_ACTIVE_STATUS.format(laser), - self.getaddr(135 + laser // 8), - codes.LASER_ACTIVE_STATUS, - RegBitField(bailly_consts.BIT_FIELD.format(laser % 8), bitpos=laser % 8), - size=1) - for laser in range(0, 16)) - ), - ) - ] - - self.fields[bailly_consts.MODULE_ALARMS_FIELD] = [ - RegGroupField(bailly_consts.MODULE_ALARMS_FIELD, - NumberRegField(bailly_consts.VCC_3V3_TEMPERATURE_WARNING_ALARM, self.getaddr(137), format="B", size=1), - RegBitField(bailly_consts.TEMP_HIGH_ALARM_FLAG, offset=self.getaddr(137), bitpos=0), - RegBitField(bailly_consts.TEMP_LOW_ALARM_FLAG, offset=self.getaddr(137), bitpos=1), - RegBitField(bailly_consts.TEMP_HIGH_WARN_FLAG, offset=self.getaddr(137), bitpos=2), - RegBitField(bailly_consts.TEMP_LOW_WARN_FLAG, offset=self.getaddr(137), bitpos=3), - RegBitField(bailly_consts.VOLTAGE_HIGH_ALARM_FLAG, offset=self.getaddr(137), bitpos=4), - RegBitField(bailly_consts.VOLTAGE_LOW_ALARM_FLAG, offset=self.getaddr(137), bitpos=5), - RegBitField(bailly_consts.VOLTAGE_HIGH_WARN_FLAG, offset=self.getaddr(137), bitpos=6), - RegBitField(bailly_consts.VOLTAGE_LOW_WARN_FLAG, offset=self.getaddr(137), bitpos=7), - NumberRegField(bailly_consts.LASER_BIAS_WARNING_7_0, self.getaddr(138), format="B", size=1), - NumberRegField(bailly_consts.LASER_BIAS_WARNING_15_8, self.getaddr(139), format="B", size=1), - RegGroupField(bailly_consts.LASER_BIAS_WARNING_FIELD, - *(NumberRegField(bailly_consts.LASER_BIAS_WARNING.format(laser), - self.getaddr(138 + laser // 8), - RegBitField(bailly_consts.BIT_FIELD.format(laser % 8), bitpos=laser % 8), - size=1) - for laser in range(0, 16)) - ), - NumberRegField(bailly_consts.LASER_BIAS_ALARM_7_0, self.getaddr(140), format="B", size=1), - NumberRegField(bailly_consts.LASER_BIAS_ALARM_15_8, self.getaddr(141), format="B", size=1), - RegGroupField(bailly_consts.LASER_BIAS_ALARM_FIELD, - *(NumberRegField(bailly_consts.LASER_BIAS_ALARM.format(laser), - self.getaddr(140 + laser // 8), - RegBitField(bailly_consts.BIT_FIELD.format(laser % 8), bitpos=laser % 8), - size=1) - for laser in range(0, 16)) - ), - ) - ] - - self.fields[bailly_consts.CPO_MODULE_MONITORS_FIELD] = [ - RegGroupField(bailly_consts.CPO_MODULE_MONITORS_FIELD, - NumberRegField(bailly_consts.MODULE_TEMPERATURE_MONITOR_MSB, self.getaddr(150), format="B", size=1), - NumberRegField(bailly_consts.MODULE_TEMPERATURE_MONITOR_LSB, self.getaddr(151), format="B", size=1), - NumberRegField(bailly_consts.MODULE_TEMPERATURE_MONITOR, self.getaddr(150), size=2, format=">h", scale=256.0), - NumberRegField(bailly_consts.MODULE_SUPPLY_VOLTAGE_MONITOR_MSB, self.getaddr(152), format="B", size=1), - NumberRegField(bailly_consts.MODULE_SUPPLY_VOLTAGE_MONITOR_LSB, self.getaddr(153), format="B", size=1), - NumberRegField(bailly_consts.MODULE_SUPPLY_VOLTAGE_MONITOR, self.getaddr(152), size=2, format=">H", scale=10000.0), - RegGroupField(bailly_consts.LASER_CURRENT_MONITOR_FIELD, - *(RegGroupField(bailly_consts.LASER_CURRENT_MONITOR.format(laser), - NumberRegField(bailly_consts.LASER_CURRENT_MONITOR_MSB.format(laser), self.getaddr(154 + 2 * laser), format="B", size=1), - NumberRegField(bailly_consts.LASER_CURRENT_MONITOR_LSB.format(laser), self.getaddr(155 + 2 * laser), format="B", size=1), - NumberRegField(bailly_consts.LASER_CURRENT_MONITOR.format(laser), self.getaddr(154 + 2 * laser), size=2, format=">H", scale=10.0), - ) for laser in range(0, 16)) - ), - RegGroupField(bailly_consts.LASER_VOLTAGE_MONITOR_FIELD, - *(NumberRegField(bailly_consts.LASER_VOLTAGE_MONITOR.format(laser), - self.getaddr(186 + laser), size=1, format="B", scale=100.0) - for laser in range(0, 16)) - ), - RegGroupField(bailly_consts.LASER_OPTICAL_POWER_MONITOR_FIELD, - *(RegGroupField(bailly_consts.LASER_OPTICAL_POWER_MONITOR.format(laser), - NumberRegField(bailly_consts.LASER_OPTICAL_POWER_MONITOR_MSB.format(laser), self.getaddr(203 + 2 * laser), format="B", size=1), - NumberRegField(bailly_consts.LASER_OPTICAL_POWER_MONITOR_LSB.format(laser), self.getaddr(204 + 2 * laser), format="B", size=1), - NumberRegField(bailly_consts.LASER_OPTICAL_POWER_MONITOR.format(laser), self.getaddr(203 + 2 * laser), size=2, format=">H", scale=100.0), - ) for laser in range(0, 16)) - ), - NumberRegField(bailly_consts.TEC_CURRENT_MONITOR_MSB, self.getaddr(250), format="B", size=1), - NumberRegField(bailly_consts.TEC_CURRENT_MONITOR_LSB, self.getaddr(251), format="B", size=1), - NumberRegField(bailly_consts.TEC_CURRENT_MONITOR, self.getaddr(250), size=2, format=">h", scale=327.67), - ) - ] - -class _BaillyElsInfoPage(CmisPage): - """Bailly-specific fields on CMIS Page 0xB1h""" - def __init__(self, codes, page=0xB1, bank=0): - super().__init__(codes, page=page, bank=bank) - - self.fields[bailly_consts.CPO_VENDOR_INFO_FIELD] = [ - RegGroupField(bailly_consts.CPO_VENDOR_INFO_FIELD, - StringRegField(bailly_consts.VENDOR_NAME_ASCII_FIELD, self.getaddr(129), size=16), - HexRegField(bailly_consts.VENDOR_OUI_HEX_FIELD, self.getaddr(145), size=3), - StringRegField(bailly_consts.VENDOR_PART_NUMBER_ASCII_FIELD, self.getaddr(148), size=16), - StringRegField(bailly_consts.VENDOR_REVISION_ASCII_FIELD, self.getaddr(164), size=2), - StringRegField(bailly_consts.VENDOR_SERIAL_NUMBER_ASCII_FIELD, self.getaddr(166), size=16), - StringRegField(bailly_consts.DATE_CODE_YY_FIELD, self.getaddr(182), size=2), - StringRegField(bailly_consts.DATE_CODE_MM_FIELD, self.getaddr(184), size=2), - StringRegField(bailly_consts.DATE_CODE_DD_FIELD, self.getaddr(186), size=2), - StringRegField(bailly_consts.DATE_CODE_LOT_FIELD, self.getaddr(188), size=2), - DateField(bailly_consts.DATE_CODE_FIELD, self.getaddr(182), size=8), - StringRegField(bailly_consts.CLEI_CODE_FIELD, self.getaddr(190), size=10), - NumberRegField(bailly_consts.MAX_POWER_CONSUMPTION_FIELD, self.getaddr(200), format="B", size=1, scale=4.0), - NumberRegField(bailly_consts.CHECKSUM_FIELD, self.getaddr(251), format="B", size=1), - ) - ] - -class _BaillyElsThresholdPage(CmisPage): - """Bailly-specific fields on CMIS Page 0xB2h""" - def __init__(self, codes, page=0xB2, bank=0): - super().__init__(codes, page=page, bank=bank) - - self.fields[bailly_consts.LASER_POWER_MODE_CONTROL_FIELD] = [ - RegGroupField(bailly_consts.LASER_POWER_MODE_CONTROL_FIELD, - NumberRegField(bailly_consts.LASER_POWER_MODE_CONTROL_BITS_FIELD, self.getaddr(128), format="B", size=1, ro=False, - *(RegBitField(bailly_consts.CHANNEL_LASER_POWER_MODE_ENABLE.format(channel), bitpos=channel, ro=False) - for channel in range(0, 8)) - ), - RegGroupField(bailly_consts.LASER_POWER_MODE_CONTROL_CHANNELS_FIELD, - *(NumberRegField(bailly_consts.CHANNEL_LASER_POWER_MODE_ENABLE.format(channel), - self.getaddr(128), - RegBitField(bailly_consts.BIT_FIELD.format(channel), bitpos=channel, ro=False), - size=1, ro=False) - for channel in range(0, 8)) - ), - RegGroupField(bailly_consts.THRESHOLD_VALUES_FIELD, - NumberRegField(bailly_consts.TEMP_HIGH_ALARM_MSB_FIELD, self.getaddr(162), format="B", size=1), - NumberRegField(bailly_consts.TEMP_HIGH_ALARM_LSB_FIELD, self.getaddr(163), format="B", size=1), - NumberRegField(bailly_consts.TEMP_LOW_ALARM_MSB_FIELD, self.getaddr(164), format="B", size=1), - NumberRegField(bailly_consts.TEMP_LOW_ALARM_LSB_FIELD, self.getaddr(165), format="B", size=1), - NumberRegField(bailly_consts.TEMP_HIGH_WARNING_MSB_FIELD, self.getaddr(166), format="B", size=1), - NumberRegField(bailly_consts.TEMP_HIGH_WARNING_LSB_FIELD, self.getaddr(167), format="B", size=1), - NumberRegField(bailly_consts.TEMP_LOW_WARNING_MSB_FIELD, self.getaddr(168), format="B", size=1), - NumberRegField(bailly_consts.TEMP_LOW_WARNING_LSB_FIELD, self.getaddr(169), format="B", size=1), - NumberRegField(bailly_consts.VCC_HIGH_ALARM_MSB_FIELD, self.getaddr(170), format="B", size=1), - NumberRegField(bailly_consts.VCC_HIGH_ALARM_LSB_FIELD, self.getaddr(171), format="B", size=1), - NumberRegField(bailly_consts.VCC_LOW_ALARM_MSB_FIELD, self.getaddr(172), format="B", size=1), - NumberRegField(bailly_consts.VCC_LOW_ALARM_LSB_FIELD, self.getaddr(173), format="B", size=1), - NumberRegField(bailly_consts.VCC_HIGH_WARNING_MSB_FIELD, self.getaddr(174), format="B", size=1), - NumberRegField(bailly_consts.VCC_HIGH_WARNING_LSB_FIELD, self.getaddr(175), format="B", size=1), - NumberRegField(bailly_consts.VCC_LOW_WARNING_MSB_FIELD, self.getaddr(176), format="B", size=1), - NumberRegField(bailly_consts.VCC_LOW_WARNING_LSB_FIELD, self.getaddr(177), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_HIGH_ALARM_MSB_FIELD, self.getaddr(178), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_HIGH_ALARM_LSB_FIELD, self.getaddr(179), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_LOW_ALARM_MSB_FIELD, self.getaddr(180), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_LOW_ALARM_LSB_FIELD, self.getaddr(181), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_HIGH_WARNING_MSB_FIELD, self.getaddr(182), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_HIGH_WARNING_LSB_FIELD, self.getaddr(183), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_LOW_WARNING_MSB_FIELD, self.getaddr(184), format="B", size=1), - NumberRegField(bailly_consts.TX_POWER_LOW_WARNING_LSB_FIELD, self.getaddr(185), format="B", size=1), - NumberRegField(bailly_consts.TX_BIAS_HIGH_ALARM_MSB_FIELD, self.getaddr(186), format="B", size=1), - NumberRegField(bailly_consts.TX_BIAS_HIGH_ALARM_LSB_FIELD, self.getaddr(187), format="B", size=1), - NumberRegField(bailly_consts.TX_BIAS_HIGH_WARNING_MSB_FIELD, self.getaddr(188), format="B", size=1), - NumberRegField(bailly_consts.TX_BIAS_HIGH_WARNING_LSB_FIELD, self.getaddr(189), format="B", size=1), - ), - NumberRegField(bailly_consts.CHECKSUM_FIELD, self.getaddr(255), format="B", size=1), - ) - ] - -# -------------------------- Bailly Main Memory Map Class -------------------------- -class BaillyMemMap(CmisMemMap): - def __init__(self, codes, bank=0, base_page=0): - self._bank = bank - self._base_page = base_page - super().__init__(codes, bank) - - ELS_CONTROL_PAGE = 0xB0 - ELS_INFO_PAGE = 0xB1 - ELS_THRESHOLD_PAGE = 0xB2 - - self.add_pages( - _BaillyElsControlPage(codes, ELS_CONTROL_PAGE + base_page), - _BaillyElsInfoPage(codes, ELS_INFO_PAGE + base_page), - _BaillyElsThresholdPage(codes, ELS_THRESHOLD_PAGE + base_page), - ) diff --git a/sonic_platform_base/sonic_xcvr/mem_maps/bailly/__init__.py b/sonic_platform_base/sonic_xcvr/mem_maps/broadcom/__init__.py similarity index 100% rename from sonic_platform_base/sonic_xcvr/mem_maps/bailly/__init__.py rename to sonic_platform_base/sonic_xcvr/mem_maps/broadcom/__init__.py diff --git a/sonic_platform_base/sonic_xcvr/mem_maps/broadcom/bailly.py b/sonic_platform_base/sonic_xcvr/mem_maps/broadcom/bailly.py new file mode 100644 index 000000000..6f054ef22 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/mem_maps/broadcom/bailly.py @@ -0,0 +1,224 @@ +""" + bailly.py + + Implementation of XcvrMemMap for Bailly extending CMIS +""" + +from ..public.cmis import CmisMemMap +from ..public.cmis.pages.page import CmisPage +from ...fields.xcvr_field import ( + CodeRegField, + DateField, + HexRegField, + NumberRegField, + RegBitField, + RegBitsField, + RegGroupField, + StringRegField, +) +from ...fields.consts import * +from ...fields.broadcom import bailly + + +class _BaillyRlmControlPage(CmisPage): + """Bailly-specific fields on CMIS Page 0xB0h""" + + def __init__(self, codes, page=0xB0, bank=0): + super().__init__(codes, page=page, bank=bank) + + self.fields[bailly.CPO_INFO_FIELD] = [ + RegGroupField(bailly.CPO_INFO_FIELD, + CodeRegField(bailly.CPO_IDENTIFIER, self.getaddr(128), codes.XCVR_IDENTIFIERS), + NumberRegField(bailly.CPO_REVISION, self.getaddr(129), format="B", size=1), + NumberRegField(bailly.LASER_GRID_AND_COUNT, self.getaddr(130), size=1, format="B"), + CodeRegField(bailly.LASER_WAVELENGTH_GRID, self.getaddr(130), + codes.LASER_WAVELENGTH_GRID, + RegBitField(bailly.BIT4_FIELD, bitpos=4, ro=True) + ), + CodeRegField(bailly.LASER_COUNT, self.getaddr(130), + codes.LASER_COUNT, + RegBitsField(bailly.BITS0_3_FIELD, bitpos=0, size=4, ro=True) + ), + ) + ] + + self.fields[bailly.LASER_CONTROL_FIELD] = [ + RegGroupField(bailly.LASER_CONTROL_FIELD, + CodeRegField(bailly.MODULE_LOW_POWER_CONTROL, self.getaddr(132), + codes.POWER_MODE, + RegBitField(bailly.BIT0_FIELD, bitpos=0, ro=False) + ), + NumberRegField(bailly.LASER_DISABLE_CONTROL_7_0, self.getaddr(133), format="B", size=1, ro=False), + NumberRegField(bailly.LASER_DISABLE_CONTROL_15_8, self.getaddr(134), format="B", size=1, ro=False), + RegGroupField(bailly.LASER_DISABLE_CONTROL_FIELD, + *(CodeRegField(bailly.LASER_DISABLE_CONTROL.format(laser), + self.getaddr(133 + laser // 8), + codes.LASER_DISABLE_CONTROL, + RegBitField(bailly.BIT_FIELD.format(laser % 8), bitpos=laser % 8, ro=False), + ) + for laser in range(0, 16)) + ), + ) + ] + + self.fields[bailly.LASER_STATUS_FIELD] = [ + RegGroupField(bailly.LASER_STATUS_FIELD, + NumberRegField(bailly.MODULE_STATE_AND_INTERRUPT, self.getaddr(131), size=1, format="B"), + CodeRegField(bailly.MODULE_LOW_POWER_STATE, self.getaddr(131), + codes.POWER_MODE, + RegBitField(bailly.BIT1_FIELD, bitpos=1) + ), + CodeRegField(bailly.INTL_INTERRUPT_STATUS, self.getaddr(131), + codes.INTERRUPT_STATUS, + RegBitField(bailly.BIT0_FIELD, bitpos=0) + ), + NumberRegField(bailly.LASER_ACTIVE_STATUS_7_0, self.getaddr(135), format="B", size=1), + NumberRegField(bailly.LASER_ACTIVE_STATUS_15_8, self.getaddr(136), format="B", size=1), + RegGroupField(bailly.LASER_ACTIVE_STATUS_FIELD, + *(CodeRegField(bailly.LASER_ACTIVE_STATUS.format(laser), + self.getaddr(135 + laser // 8), + codes.LASER_ACTIVE_STATUS, + RegBitField(bailly.BIT_FIELD.format(laser % 8), bitpos=laser % 8), + size=1) + for laser in range(0, 16)) + ), + ) + ] + + self.fields[bailly.MODULE_ALARMS_FIELD] = [ + RegGroupField(bailly.MODULE_ALARMS_FIELD, + NumberRegField(bailly.VCC_3V3_TEMPERATURE_WARNING_ALARM, self.getaddr(137), format="B", size=1), + RegBitField(bailly.TEMP_HIGH_ALARM_FLAG, offset=self.getaddr(137), bitpos=0), + RegBitField(bailly.TEMP_LOW_ALARM_FLAG, offset=self.getaddr(137), bitpos=1), + RegBitField(bailly.TEMP_HIGH_WARN_FLAG, offset=self.getaddr(137), bitpos=2), + RegBitField(bailly.TEMP_LOW_WARN_FLAG, offset=self.getaddr(137), bitpos=3), + RegBitField(bailly.VOLTAGE_HIGH_ALARM_FLAG, offset=self.getaddr(137), bitpos=4), + RegBitField(bailly.VOLTAGE_LOW_ALARM_FLAG, offset=self.getaddr(137), bitpos=5), + RegBitField(bailly.VOLTAGE_HIGH_WARN_FLAG, offset=self.getaddr(137), bitpos=6), + RegBitField(bailly.VOLTAGE_LOW_WARN_FLAG, offset=self.getaddr(137), bitpos=7), + NumberRegField(bailly.LASER_BIAS_WARNING_7_0, self.getaddr(138), format="B", size=1), + NumberRegField(bailly.LASER_BIAS_WARNING_15_8, self.getaddr(139), format="B", size=1), + RegGroupField(bailly.LASER_BIAS_WARNING_FIELD, + *(NumberRegField(bailly.LASER_BIAS_WARNING.format(laser), + self.getaddr(138 + laser // 8), + RegBitField(bailly.BIT_FIELD.format(laser % 8), bitpos=laser % 8), + size=1) + for laser in range(0, 16)) + ), + NumberRegField(bailly.LASER_BIAS_ALARM_7_0, self.getaddr(140), format="B", size=1), + NumberRegField(bailly.LASER_BIAS_ALARM_15_8, self.getaddr(141), format="B", size=1), + RegGroupField(bailly.LASER_BIAS_ALARM_FIELD, + *(NumberRegField(bailly.LASER_BIAS_ALARM.format(laser), + self.getaddr(140 + laser // 8), + RegBitField(bailly.BIT_FIELD.format(laser % 8), bitpos=laser % 8), + size=1) + for laser in range(0, 16)) + ), + ) + ] + + self.fields[bailly.CPO_MODULE_MONITORS_FIELD] = [ + RegGroupField(bailly.CPO_MODULE_MONITORS_FIELD, + NumberRegField(bailly.MODULE_TEMPERATURE_MONITOR, self.getaddr(150), size=2, format=">h", scale=256.0), + NumberRegField(bailly.MODULE_SUPPLY_VOLTAGE_MONITOR, self.getaddr(152), size=2, format=">H", scale=10000.0), + RegGroupField(bailly.LASER_CURRENT_MONITOR_FIELD, + *(NumberRegField(bailly.LASER_CURRENT_MONITOR.format(laser), + self.getaddr(154 + 2 * laser), size=2, format=">H", scale=100.0) + for laser in range(0, 16)) + ), + RegGroupField(bailly.LASER_VOLTAGE_MONITOR_FIELD, + *(NumberRegField(bailly.LASER_VOLTAGE_MONITOR.format(laser), + self.getaddr(186 + laser), size=1, format="B", scale=100.0) + for laser in range(0, 16)) + ), + RegGroupField(bailly.LASER_OPTICAL_POWER_MONITOR_FIELD, + *(NumberRegField(bailly.LASER_OPTICAL_POWER_MONITOR.format(laser), + self.getaddr(203 + 2 * laser), size=2, format=">H", scale=100.0) + for laser in range(0, 16)) + ), + NumberRegField(bailly.TEC_CURRENT_MONITOR, self.getaddr(250), size=2, format=">h", scale=327.67), + ) + ] + + +class _BaillyRlmInfoPage(CmisPage): + """Bailly-specific fields on CMIS Page 0xB1h""" + + def __init__(self, codes, page=0xB1, bank=0): + super().__init__(codes, page=page, bank=bank) + + self.fields[bailly.CPO_VENDOR_INFO_FIELD] = [ + RegGroupField(bailly.CPO_VENDOR_INFO_FIELD, + StringRegField(bailly.VENDOR_NAME_ASCII_FIELD, self.getaddr(129), size=16), + HexRegField(bailly.VENDOR_OUI_HEX_FIELD, self.getaddr(145), size=3), + StringRegField(bailly.VENDOR_PART_NUMBER_ASCII_FIELD, self.getaddr(148), size=16), + StringRegField(bailly.VENDOR_REVISION_ASCII_FIELD, self.getaddr(164), size=2), + StringRegField(bailly.VENDOR_SERIAL_NUMBER_ASCII_FIELD, self.getaddr(166), size=16), + StringRegField(bailly.DATE_CODE_YY_FIELD, self.getaddr(182), size=2), + StringRegField(bailly.DATE_CODE_MM_FIELD, self.getaddr(184), size=2), + StringRegField(bailly.DATE_CODE_DD_FIELD, self.getaddr(186), size=2), + StringRegField(bailly.DATE_CODE_LOT_FIELD, self.getaddr(188), size=2), + DateField(bailly.DATE_CODE_FIELD, self.getaddr(182), size=8), + StringRegField(bailly.CLEI_CODE_FIELD, self.getaddr(190), size=10), + NumberRegField(bailly.MAX_POWER_CONSUMPTION_FIELD, self.getaddr(200), format="B", size=1, scale=4.0), + NumberRegField(bailly.CHECKSUM_FIELD, self.getaddr(251), format="B", size=1), + ) + ] + + +class _BaillyRlmThresholdPage(CmisPage): + """Bailly-specific fields on CMIS Page 0xB2h""" + + def __init__(self, codes, page=0xB2, bank=0): + super().__init__(codes, page=page, bank=bank) + + self.fields[bailly.LASER_POWER_MODE_CONTROL_FIELD] = [ + RegGroupField(bailly.LASER_POWER_MODE_CONTROL_FIELD, + NumberRegField(bailly.LASER_POWER_MODE_CONTROL_BITS_FIELD, self.getaddr(128), format="B", size=1, ro=False, + *(RegBitField(bailly.CHANNEL_LASER_POWER_MODE_ENABLE.format(channel), bitpos=channel, ro=False) + for channel in range(0, 8)) + ), + RegGroupField(bailly.LASER_POWER_MODE_CONTROL_CHANNELS_FIELD, + *(CodeRegField(bailly.CHANNEL_LASER_POWER_MODE_ENABLE.format(channel), + self.getaddr(128), + codes.LASER_POWER_MODE_ENABLE, + RegBitField(bailly.BIT_FIELD.format(channel), bitpos=channel, ro=False), + ) + for channel in range(0, 8)) + ), + RegGroupField(bailly.THRESHOLD_VALUES_FIELD, + NumberRegField(bailly.RLM_TEMP_HIGH_ALARM_FIELD, self.getaddr(162), size=2, format=">h", scale=256.0), + NumberRegField(bailly.RLM_TEMP_LOW_ALARM_FIELD, self.getaddr(164), size=2, format=">h", scale=256.0), + NumberRegField(bailly.RLM_TEMP_HIGH_WARNING_FIELD, self.getaddr(166), size=2, format=">h", scale=256.0), + NumberRegField(bailly.RLM_TEMP_LOW_WARNING_FIELD, self.getaddr(168), size=2, format=">h", scale=256.0), + NumberRegField(bailly.RLM_VCC_HIGH_ALARM_FIELD, self.getaddr(170), size=2, format=">H", scale=10000.0), + NumberRegField(bailly.RLM_VCC_LOW_ALARM_FIELD, self.getaddr(172), size=2, format=">H", scale=10000.0), + NumberRegField(bailly.RLM_VCC_HIGH_WARNING_FIELD, self.getaddr(174), size=2, format=">H", scale=10000.0), + NumberRegField(bailly.RLM_VCC_LOW_WARNING_FIELD, self.getaddr(176), size=2, format=">H", scale=10000.0), + NumberRegField(bailly.RLM_TX_POWER_HIGH_ALARM_FIELD, self.getaddr(178), size=2, format=">H", scale=100.0), + NumberRegField(bailly.RLM_TX_POWER_LOW_ALARM_FIELD, self.getaddr(180), size=2, format=">H", scale=100.0), + NumberRegField(bailly.RLM_TX_POWER_HIGH_WARNING_FIELD, self.getaddr(182), size=2, format=">H", scale=100.0), + NumberRegField(bailly.RLM_TX_POWER_LOW_WARNING_FIELD, self.getaddr(184), size=2, format=">H", scale=100.0), + NumberRegField(bailly.RLM_TX_BIAS_HIGH_ALARM_FIELD, self.getaddr(186), size=2, format=">H", scale=100.0), + NumberRegField(bailly.RLM_TX_BIAS_HIGH_WARNING_FIELD, self.getaddr(188), size=2, format=">H", scale=100.0), + ), + NumberRegField(bailly.CHECKSUM_FIELD, self.getaddr(255), format="B", size=1), + ) + ] + + +class BaillyMemMap(CmisMemMap): + def __init__(self, codes, bank=0, base_page=0): + self._bank = bank + self._base_page = base_page + super().__init__(codes, bank) + + RLM_CONTROL_PAGE = 0xB0 + RLM_INFO_PAGE = 0xB1 + RLM_THRESHOLD_PAGE = 0xB2 + + self.add_pages( + _BaillyRlmControlPage(codes, RLM_CONTROL_PAGE + base_page), + _BaillyRlmInfoPage(codes, RLM_INFO_PAGE + base_page), + _BaillyRlmThresholdPage(codes, RLM_THRESHOLD_PAGE + base_page), + ) diff --git a/tests/sonic_xcvr/test_bailly_cmis.py b/tests/sonic_xcvr/test_bailly_cmis.py index a5f06b3fc..bfc9f1530 100644 --- a/tests/sonic_xcvr/test_bailly_cmis.py +++ b/tests/sonic_xcvr/test_bailly_cmis.py @@ -1,8 +1,9 @@ import pytest from unittest.mock import MagicMock, patch, Mock -from sonic_platform_base.sonic_xcvr.api.bailly.bailly_api import BaillyApi -from sonic_platform_base.sonic_xcvr.mem_maps.bailly.bailly_mem_map import BaillyMemMap -from sonic_platform_base.sonic_xcvr.codes.bailly.bailly_codes import BaillyCodes +from sonic_platform_base.sonic_xcvr.api.broadcom.bailly import BaillyApi +from sonic_platform_base.sonic_xcvr.mem_maps.broadcom.bailly import BaillyMemMap +from sonic_platform_base.sonic_xcvr.codes.broadcom.bailly import BaillyCodes +from sonic_platform_base.sonic_xcvr.fields.broadcom import bailly from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom # Test BaillyCodes @@ -70,16 +71,224 @@ def test_get_active_apsel_hostlane_no_zero_calls_parent(self): mock_super.assert_called_once() def test_get_transceiver_info(self): - with patch.object(self.api, 'get_els_info') as mock_els: - mock_els.return_value = {} + with patch.object(self.api, 'get_rlm_info') as mock_rlm: + mock_rlm.return_value = {} with patch('sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_info') as mock_super: mock_super.return_value = {} self.api.get_transceiver_info() mock_super.assert_called_once() - mock_els.assert_called_once() + mock_rlm.assert_called_once() - def test_get_els_info(self): + def test_get_rlm_info(self): self.mock_eeprom.read.return_value = 0 - result = self.api.get_els_info() + result = self.api.get_rlm_info() assert isinstance(result, dict) + def test__format_float(self): + assert self.api._format_float(None) is None + assert self.api._format_float({'nested': 1}) is None + assert self.api._format_float(12.34567) == 12.346 + + def test_get_rlm_temperature(self): + self.mock_eeprom.read.return_value = { + bailly.MODULE_TEMPERATURE_MONITOR: 25.1234 + } + assert self.api.get_rlm_temperature() == 25.123 + self.mock_eeprom.read.assert_called_with(bailly.CPO_MODULE_MONITORS_FIELD) + + def test_get_rlm_temperature_none(self): + self.mock_eeprom.read.return_value = None + assert self.api.get_rlm_temperature() is None + + def test_get_rlm_single_read_apis(self): + expected = {'value': 1} + self.mock_eeprom.read.return_value = expected + assert self.api.get_rlm_vendor_info() == expected + self.mock_eeprom.read.assert_called_with(bailly.CPO_VENDOR_INFO_FIELD) + assert self.api.get_rlm_laser_current() == expected + self.mock_eeprom.read.assert_called_with(bailly.LASER_CURRENT_MONITOR_FIELD) + assert self.api.get_rlm_laser_voltage() == expected + self.mock_eeprom.read.assert_called_with(bailly.LASER_VOLTAGE_MONITOR_FIELD) + assert self.api.get_rlm_laser_power() == expected + self.mock_eeprom.read.assert_called_with(bailly.LASER_OPTICAL_POWER_MONITOR_FIELD) + + def test_get_rlm_monitor_values(self): + self.mock_eeprom.read.return_value = { + bailly.MODULE_TEMPERATURE_MONITOR: 25.1234, + bailly.MODULE_SUPPLY_VOLTAGE_MONITOR: 3.3462, + bailly.TEC_CURRENT_MONITOR: None, + } + assert self.api.get_rlm_monitor_values() == { + 'els_temperature': 25.123, + 'els_voltage': 3.346, + 'rlm_tec_current': None, + } + + def test_get_rlm_monitor_values_none(self): + self.mock_eeprom.read.return_value = None + assert self.api.get_rlm_monitor_values() is None + + def test_get_rlm_thresholds(self): + thresholds = { + bailly.RLM_TEMP_HIGH_ALARM_FIELD: 85.1234, + bailly.RLM_TEMP_LOW_ALARM_FIELD: -5.0, + bailly.RLM_TEMP_HIGH_WARNING_FIELD: 75.0, + bailly.RLM_TEMP_LOW_WARNING_FIELD: 0.0, + bailly.RLM_VCC_HIGH_ALARM_FIELD: 3.63, + bailly.RLM_VCC_LOW_ALARM_FIELD: 2.97, + bailly.RLM_VCC_HIGH_WARNING_FIELD: 3.465, + bailly.RLM_VCC_LOW_WARNING_FIELD: 3.135, + bailly.RLM_TX_POWER_HIGH_ALARM_FIELD: 7.0, + bailly.RLM_TX_POWER_LOW_ALARM_FIELD: -6.9, + bailly.RLM_TX_POWER_HIGH_WARNING_FIELD: 4.0, + bailly.RLM_TX_POWER_LOW_WARNING_FIELD: -2.9, + bailly.RLM_TX_BIAS_HIGH_ALARM_FIELD: 162.5, + bailly.RLM_TX_BIAS_HIGH_WARNING_FIELD: 156.248, + } + self.mock_eeprom.read.return_value = { + bailly.THRESHOLD_VALUES_FIELD: thresholds + } + assert self.api.get_rlm_thresholds() == { + 'els_temphighalarm': 85.123, + 'els_templowalarm': -5.0, + 'els_temphighwarning': 75.0, + 'els_templowwarning': 0.0, + 'els_vcchighalarm': 3.63, + 'els_vcclowalarm': 2.97, + 'els_vcchighwarning': 3.465, + 'els_vcclowwarning': 3.135, + 'els_txpowerhighalarm': 7.0, + 'els_txpowerlowalarm': -6.9, + 'els_txpowerhighwarning': 4.0, + 'els_txpowerlowwarning': -2.9, + 'els_txbiashighalarm': 162.5, + 'els_txbiashighwarning': 156.248, + } + + def test_get_rlm_thresholds_none(self): + self.mock_eeprom.read.return_value = None + assert self.api.get_rlm_thresholds() is None + self.mock_eeprom.read.return_value = {} + assert self.api.get_rlm_thresholds() is None + + def test_get_rlm_flags(self): + self.mock_eeprom.read.return_value = { + bailly.TEMP_HIGH_ALARM_FLAG: True, + bailly.TEMP_LOW_ALARM_FLAG: False, + bailly.TEMP_HIGH_WARN_FLAG: True, + bailly.TEMP_LOW_WARN_FLAG: False, + bailly.VOLTAGE_HIGH_ALARM_FLAG: True, + bailly.VOLTAGE_LOW_ALARM_FLAG: False, + bailly.VOLTAGE_HIGH_WARN_FLAG: True, + bailly.VOLTAGE_LOW_WARN_FLAG: False, + } + assert self.api.get_rlm_flags() == { + 'els_tempHAlarm': True, + 'els_tempLAlarm': False, + 'els_tempHWarn': True, + 'els_tempLWarn': False, + 'els_vccHAlarm': True, + 'els_vccLAlarm': False, + 'els_vccHWarn': True, + 'els_vccLWarn': False, + } + + def test_get_rlm_flags_none(self): + self.mock_eeprom.read.return_value = None + assert self.api.get_rlm_flags() is None + + def test_get_rlm_status(self): + self.mock_eeprom.read.return_value = { + bailly.MODULE_LOW_POWER_STATE: 'Low power mode', + bailly.INTL_INTERRUPT_STATUS: 'Interrupt event occurred', + } + assert self.api.get_rlm_status() == { + 'els_module_low_power_state': 'Low power mode', + 'els_interrupt_status': 'Interrupt event occurred', + } + + def test_get_rlm_status_none(self): + self.mock_eeprom.read.return_value = None + assert self.api.get_rlm_status() is None + + def test_get_transceiver_dom_real_value_adds_rlm_values(self): + with patch('sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_dom_real_value') as mock_super: + mock_super.return_value = {'temperature': 55.0} + with patch.object(self.api, 'get_rlm_monitor_values', return_value={'els_temperature': 25.123, 'els_voltage': None}): + assert self.api.get_transceiver_dom_real_value() == { + 'temperature': 55.0, + 'els_temperature': 25.123, + } + + def test_get_transceiver_threshold_info_adds_rlm_thresholds(self): + with patch('sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_threshold_info') as mock_super: + mock_super.return_value = {'temphighalarm': 85.0} + with patch.object(self.api, 'get_rlm_thresholds', return_value={'els_temphighalarm': 90.0, 'els_templowalarm': None}): + assert self.api.get_transceiver_threshold_info() == { + 'temphighalarm': 85.0, + 'els_temphighalarm': 90.0, + } + + def test_get_transceiver_dom_flags_adds_rlm_flags(self): + with patch('sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_dom_flags') as mock_super: + mock_super.return_value = {'tempHAlarm': False} + with patch.object(self.api, 'get_rlm_flags', return_value={'els_tempHAlarm': True, 'els_tempLAlarm': None}): + assert self.api.get_transceiver_dom_flags() == { + 'tempHAlarm': False, + 'els_tempHAlarm': True, + } + + def test_get_transceiver_status_flags_adds_rlm_flags_and_status(self): + with patch('sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_status_flags') as mock_super: + mock_super.return_value = {'module_state': 'Ready'} + with patch.object(self.api, 'get_rlm_flags', return_value={'els_tempHAlarm': True}): + with patch.object(self.api, 'get_rlm_status', return_value={'els_interrupt_status': 'Interrupt event occurred'}): + assert self.api.get_transceiver_status_flags() == { + 'module_state': 'Ready', + 'els_tempHAlarm': True, + 'els_interrupt_status': 'Interrupt event occurred', + } + + def test_get_transceiver_info_adds_rlm_info(self): + with patch('sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_info') as mock_super: + mock_super.return_value = {'type': 'CPO Bailly'} + with patch.object(self.api, 'get_rlm_info') as mock_rlm: + mock_rlm.return_value = { + 'cpo_info': { + bailly.CPO_IDENTIFIER: 'ELS Identifier', + bailly.CPO_REVISION: 0x12, + bailly.LASER_WAVELENGTH_GRID: 'CWDM4', + bailly.LASER_COUNT: 8, + }, + 'rlm_vendor_info': { + bailly.VENDOR_NAME_ASCII_FIELD: 'BROADCOM ', + bailly.VENDOR_OUI_HEX_FIELD: 'ec-01-e2', + bailly.VENDOR_PART_NUMBER_ASCII_FIELD: 'ARLM ', + bailly.VENDOR_REVISION_ASCII_FIELD: 'A0 ', + bailly.VENDOR_SERIAL_NUMBER_ASCII_FIELD: 'SN ', + bailly.DATE_CODE_FIELD: '2024-02-26 ', + bailly.MAX_POWER_CONSUMPTION_FIELD: 12.0, + }, + 'laser_power_mode': { + bailly.LASER_POWER_MODE_CONTROL_BITS_FIELD: 0, + }, + } + result = self.api.get_transceiver_info() + assert result['type'] == 'CPO Bailly' + assert result['els_identifier'] == 'ELS Identifier' + assert result['els_revision'] == '1.2' + assert result['els_laser_count'] == 8 + assert result['els_vendor_name'] == 'BROADCOM' + assert result['els_vendor_oui'] == 'ec-01-e2' + assert result['els_vendor_pn'] == 'ARLM' + assert result['els_vendor_rev'] == 'A0' + assert result['els_vendor_sn'] == 'SN' + assert result['els_date_code'] == '2024-02-26' + assert result['els_max_power'] == 12.0 + assert result['rlm_laser_wavelength_grid'] == 'CWDM4' + assert result['rlm_laser_lpmode_control'] == 0 + + def test_get_transceiver_info_parent_none(self): + with patch('sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_info') as mock_super: + mock_super.return_value = None + assert self.api.get_transceiver_info() is None