diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py new file mode 100644 index 000000000000..bcf5c2683b31 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -0,0 +1,923 @@ +""" + c-cmis.py + + Implementation of XcvrApi that corresponds to C-CMIS +""" +from ...fields import consts +from .cmis import CmisApi +import time +BYTELENGTH = 8 +VDM_FREEZE = 128 +VDM_UNFREEZE = 0 + +class CCmisApi(CmisApi): + def __init__(self, xcvr_eeprom): + super(CCmisApi, self).__init__(xcvr_eeprom) + + def get_freq_grid(self): + ''' + This function returns the configured frequency grid. Unit in GHz + ''' + freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) + if freq_grid == 7: + return 75 + elif freq_grid == 6: + return 33 + elif freq_grid == 5: + return 100 + elif freq_grid == 4: + return 50 + elif freq_grid == 3: + return 25 + elif freq_grid == 2: + return 12.5 + elif freq_grid == 1: + return 6.25 + elif freq_grid == 0: + return 3.125 + else: + return None + + def get_laser_config_freq(self): + ''' + This function returns the configured laser frequency. Unit in GHz + ''' + freq_grid = self.get_freq_grid() + channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) + if freq_grid == 75: + config_freq = 193100 + channel * freq_grid/3 + else: + config_freq = 193100 + channel * freq_grid + return config_freq + + def get_current_laser_freq(self): + ''' + This function returns the monitored laser frequency. Unit in GHz + ''' + return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ) + + def get_tuning_in_progress(self): + ''' + This function returns tuning in progress status on media lane + False means tuning not in progress + True means tuning in progress + ''' + return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) + + def get_wavelength_unlocked(self): + ''' + This function returns wavelength unlocked status on media lane + False means wavelength locked + True means wavelength unlocked + ''' + return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) + + def get_laser_tuning_summary(self): + ''' + This function returns laser tuning status summary on media lane + ''' + result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) + laser_tuning_summary = [] + if (result >> 5) & 0x1: + laser_tuning_summary.append("TargetOutputPowerOOR") + if (result >> 4) & 0x1: + laser_tuning_summary.append("FineTuningOutOfRange") + if (result >> 3) & 0x1: + laser_tuning_summary.append("TuningNotAccepted") + if (result >> 2) & 0x1: + laser_tuning_summary.append("InvalidChannel") + if (result >> 1) & 0x1: + laser_tuning_summary.append("WavelengthUnlocked") + if (result >> 0) & 0x1: + laser_tuning_summary.append("TuningComplete") + return laser_tuning_summary + + def get_supported_freq_config(self): + ''' + This function returns the supported freq grid, low and high supported channel in 75GHz grid, + and low and high frequency supported in GHz. + allowed channel number bound in 75 GHz grid + allowed frequency bound in 75 GHz grid + ''' + grid_supported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) + low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) + hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) + low_freq_supported = 193100 + low_ch_num * 25 + high_freq_supported = 193100 + hi_ch_num * 25 + return grid_supported, low_ch_num, hi_ch_num, low_freq_supported, high_freq_supported + + def set_laser_freq(self, freq): + ''' + This function sets the laser frequency. Unit in GHz + ZR application will not support fine tuning of the laser + SONiC will only support 75 GHz frequency grid + Return True if the provision succeeds, False if it fails + ''' + grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() + grid_supported_75GHz = (grid_supported >> 7) & 0x1 + assert grid_supported_75GHz + freq_grid = 0x70 + self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) + channel_number = int(round((freq - 193100)/25)) + assert channel_number % 3 == 0 + if channel_number > hi_ch_num or channel_number < low_ch_num: + raise ValueError('Provisioned frequency out of range. Max Freq: 196100; Min Freq: 191300 GHz.') + self.set_low_power(True) + time.sleep(5) + status = self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) + time.sleep(1) + self.set_low_power(False) + time.sleep(1) + return status + + def set_tx_power(self, tx_power): + ''' + This function sets the TX output power. Unit in dBm + Return True if the provision succeeds, False if it fails + ''' + min_prog_tx_output_power, max_prog_tx_output_power = self.get_supported_power_config() + if tx_power > max_prog_tx_output_power or tx_power < min_prog_tx_output_power: + raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' + %(max_prog_tx_output_power, min_prog_tx_output_power)) + status = self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, tx_power) + time.sleep(1) + return status + + def get_pm_all(self): + ''' + This function returns the PMs reported in Page 34h and 35h in OIF C-CMIS document + CD: unit in ps/nm + DGD: unit in ps + SOPMD: unit in ps^2 + PDL: unit in dB + OSNR: unit in dB + ESNR: unit in dB + CFO: unit in MHz + TXpower:unit in dBm + RXpower:unit in dBm + RX sig power: unit in dBm + SOPROC: unit in krad/s + MER: unit in dB + ''' + # When raised by the host, causes the module to freeze and hold all + # reported statistics reporting registers (minimum, maximum and + # average values)in Pages 24h-27h. + # When ceased by the host, releases the freeze request, allowing the + # reported minimum, maximum and average values to update again. + self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_FREEZE) + time.sleep(1) + self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_UNFREEZE) + PM_dict = dict() + + rx_bits_pm = self.xcvr_eeprom.read(consts.RX_BITS_PM) + rx_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_BITS_SUB_INTERVAL_PM) + rx_corr_bits_pm = self.xcvr_eeprom.read(consts.RX_CORR_BITS_PM) + rx_min_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_CORR_BITS_SUB_INTERVAL_PM) + rx_max_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MAX_CORR_BITS_SUB_INTERVAL_PM) + + if (rx_bits_subint_pm != 0) and (rx_bits_pm != 0): + PM_dict['preFEC_BER_avg'] = rx_corr_bits_pm*1.0/rx_bits_pm + PM_dict['preFEC_BER_min'] = rx_min_corr_bits_subint_pm*1.0/rx_bits_subint_pm + PM_dict['preFEC_BER_max'] = rx_max_corr_bits_subint_pm*1.0/rx_bits_subint_pm + # when module is low power, still need these values to show 1.0 + else: + PM_dict['preFEC_BER_avg'] = 1.0 + PM_dict['preFEC_BER_min'] = 1.0 + PM_dict['preFEC_BER_max'] = 1.0 + rx_frames_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_PM) + rx_frames_subint_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_SUB_INTERVAL_PM) + rx_frames_uncorr_err_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_UNCORR_ERR_PM) + rx_min_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) + rx_max_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) + + if (rx_frames_subint_pm != 0) and (rx_frames_pm != 0): + PM_dict['preFEC_uncorr_frame_ratio_avg'] = rx_frames_uncorr_err_pm*1.0/rx_frames_subint_pm + PM_dict['preFEC_uncorr_frame_ratio_min'] = rx_min_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm + PM_dict['preFEC_uncorr_frame_ratio_max'] = rx_max_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm + # when module is low power, still need these values + else: + PM_dict['preFEC_uncorr_frame_ratio_avg'] = 0 + PM_dict['preFEC_uncorr_frame_ratio_min'] = 0 + PM_dict['preFEC_uncorr_frame_ratio_max'] = 0 + PM_dict['rx_cd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CD_PM) + PM_dict['rx_cd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CD_PM) + PM_dict['rx_cd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CD_PM) + + PM_dict['rx_dgd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_DGD_PM) + PM_dict['rx_dgd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_DGD_PM) + PM_dict['rx_dgd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_DGD_PM) + + PM_dict['rx_sopmd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPMD_PM) + PM_dict['rx_sopmd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPMD_PM) + PM_dict['rx_sopmd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPMD_PM) + + PM_dict['rx_pdl_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_PDL_PM) + PM_dict['rx_pdl_min'] = self.xcvr_eeprom.read(consts.RX_MIN_PDL_PM) + PM_dict['rx_pdl_max'] = self.xcvr_eeprom.read(consts.RX_MAX_PDL_PM) + + PM_dict['rx_osnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_OSNR_PM) + PM_dict['rx_osnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_OSNR_PM) + PM_dict['rx_osnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_OSNR_PM) + + PM_dict['rx_esnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_ESNR_PM) + PM_dict['rx_esnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_ESNR_PM) + PM_dict['rx_esnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_ESNR_PM) + + PM_dict['rx_cfo_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CFO_PM) + PM_dict['rx_cfo_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CFO_PM) + PM_dict['rx_cfo_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CFO_PM) + + PM_dict['rx_evm_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_EVM_PM) + PM_dict['rx_evm_min'] = self.xcvr_eeprom.read(consts.RX_MIN_EVM_PM) + PM_dict['rx_evm_max'] = self.xcvr_eeprom.read(consts.RX_MAX_EVM_PM) + + PM_dict['tx_power_avg'] = self.xcvr_eeprom.read(consts.TX_AVG_POWER_PM) + PM_dict['tx_power_min'] = self.xcvr_eeprom.read(consts.TX_MIN_POWER_PM) + PM_dict['tx_power_max'] = self.xcvr_eeprom.read(consts.TX_MAX_POWER_PM) + + PM_dict['rx_power_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_POWER_PM) + PM_dict['rx_power_min'] = self.xcvr_eeprom.read(consts.RX_MIN_POWER_PM) + PM_dict['rx_power_max'] = self.xcvr_eeprom.read(consts.RX_MAX_POWER_PM) + + PM_dict['rx_sigpwr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SIG_POWER_PM) + PM_dict['rx_sigpwr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SIG_POWER_PM) + PM_dict['rx_sigpwr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SIG_POWER_PM) + + PM_dict['rx_soproc_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPROC_PM) + PM_dict['rx_soproc_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPROC_PM) + PM_dict['rx_soproc_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPROC_PM) + + PM_dict['rx_mer_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_MER_PM) + PM_dict['rx_mer_min'] = self.xcvr_eeprom.read(consts.RX_MIN_MER_PM) + PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM) + return PM_dict + + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_INFO|ifname ; information for module on port + ; field = value + module_media_type = 1*255VCHAR ; module media interface ID + host_electrical_interface = 1*255VCHAR ; host electrical interface ID + media_interface_code = 1*255VCHAR ; media interface code + host_lane_count = INTEGER ; host lane count + media_lane_count = INTEGER ; media lane count + host_lane_assignment_option = INTEGER ; permissible first host lane number for application + media_lane_assignment_option = INTEGER ; permissible first media lane number for application + active_apsel_hostlane1 = INTEGER ; active application selected code assigned to host lane 1 + active_apsel_hostlane2 = INTEGER ; active application selected code assigned to host lane 2 + active_apsel_hostlane3 = INTEGER ; active application selected code assigned to host lane 3 + active_apsel_hostlane4 = INTEGER ; active application selected code assigned to host lane 4 + active_apsel_hostlane5 = INTEGER ; active application selected code assigned to host lane 5 + active_apsel_hostlane6 = INTEGER ; active application selected code assigned to host lane 6 + active_apsel_hostlane7 = INTEGER ; active application selected code assigned to host lane 7 + active_apsel_hostlane8 = INTEGER ; active application selected code assigned to host lane 8 + media_interface_technology = 1*255VCHAR ; media interface technology + hardwarerev = 1*255VCHAR ; module hardware revision + serialnum = 1*255VCHAR ; module serial number + manufacturename = 1*255VCHAR ; module venndor name + modelname = 1*255VCHAR ; module model name + vendor_rev = 1*255VCHAR ; module vendor revision + vendor_oui = 1*255VCHAR ; vendor organizationally unique identifier + vendor_date = 1*255VCHAR ; module manufacture date + connector_type = 1*255VCHAR ; connector type + specification_compliance = 1*255VCHAR ; electronic or optical interfaces that supported + active_firmware = 1*255VCHAR ; active firmware + inactive_firmware = 1*255VCHAR ; inactive firmware + supported_max_tx_power = FLOAT ; support maximum tx power + supported_min_tx_power = FLOAT ; support minimum tx power + supported_max_laser_freq = FLOAT ; support maximum laser frequency + supported_min_laser_freq = FLOAT ; support minimum laser frequency + ================================================================================ + """ + trans_info = super(CCmisApi,self).get_transceiver_info() + min_power, max_power = self.get_supported_power_config() + trans_info['supported_max_tx_power'] = max_power + trans_info['supported_min_tx_power'] = min_power + _, _, _, low_freq_supported, high_freq_supported = self.get_supported_freq_config() + trans_info['supported_max_laser_freq'] = high_freq_supported + trans_info['supported_min_laser_freq'] = low_freq_supported + return trans_info + + def get_transceiver_bulk_status(self): + """ + Retrieves bulk status info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_DOM_SENSOR|ifname ; information module DOM sensors on port + ; field = value + temperature = FLOAT ; temperature value in Celsius + voltage = FLOAT ; voltage value + txpower = FLOAT ; tx power in mW + rxpower = FLOAT ; rx power in mW + txbias = FLOAT ; tx bias in mA + laser_temperature = FLOAT ; laser temperature value in Celsius + prefec_ber = FLOAT ; prefec ber + postfec_ber = FLOAT ; postfec ber + cd_shortlink = FLOAT ; chromatic dispersion, high granularity, short link in ps/nm + cd_longlink = FLOAT ; chromatic dispersion, low granularity, long link in ps/nm + dgd = FLOAT ; differential group delay in ps + sopmd = FLOAT ; second order polarization mode dispersion in ps^2 + pdl = FLOAT ; polarization dependent loss in db + osnr = FLOAT ; optical signal to noise ratio in db + esnr = FLOAT ; electrical signal to noise ratio in db + cfo = FLOAT ; carrier frequency offset in MHz + soproc = FLOAT ; state of polarization rate of change in krad/s + laser_config_freq = FLOAT ; laser configured frequency in MHz + laser_curr_freq = FLOAT ; laser current frequency in MHz + tx_config_power = FLOAT ; configured tx output power in dbm + tx_curr_power = FLOAT ; tx current output power in dbm + rx_tot_power = FLOAT ; rx total power in dbm + rx_sig_power = FLOAT ; rx signal power in dbm + bias_xi = FLOAT ; modulator bias xi + bias_xq = FLOAT ; modulator bias xq + bias_xp = FLOAT ; modulator bias xp + bias_yi = FLOAT ; modulator bias yi + bias_yq = FLOAT ; modulator bias yq + bias_yp = FLOAT ; modulator bias yp + ======================================================================== + """ + trans_dom = super(CCmisApi,self).get_transceiver_bulk_status() + trans_dom['bias_xi'] = self.vdm_dict['Modulator Bias X/I [%]'][1][0] + trans_dom['bias_xq'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][0] + trans_dom['bias_xp'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][0] + trans_dom['bias_yi'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][0] + trans_dom['bias_yq'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][0] + trans_dom['bias_yp'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][0] + trans_dom['cd_shortlink'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][0] + try: + trans_dom['cd_longlink'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][0] + except KeyError: + pass + trans_dom['dgd'] = self.vdm_dict['DGD [ps]'][1][0] + try: + trans_dom['sopmd'] = self.vdm_dict['SOPMD [ps^2]'][1][0] + except KeyError: + pass + trans_dom['pdl'] = self.vdm_dict['PDL [dB]'][1][0] + trans_dom['osnr'] = self.vdm_dict['OSNR [dB]'][1][0] + trans_dom['esnr'] = self.vdm_dict['eSNR [dB]'][1][0] + trans_dom['cfo'] = self.vdm_dict['CFO [MHz]'][1][0] + trans_dom['tx_curr_power'] = self.vdm_dict['Tx Power [dBm]'][1][0] + trans_dom['rx_tot_power'] = self.vdm_dict['Rx Total Power [dBm]'][1][0] + try: + trans_dom['rx_sig_power'] = self.vdm_dict['Rx Signal Power [dBm]'][1][0] + except KeyError: + pass + trans_dom['laser_config_freq'] = self.get_laser_config_freq() + trans_dom['laser_curr_freq'] = self.get_current_laser_freq() + trans_dom['tx_config_power'] = self.get_tx_config_power() + return trans_dom + + def get_transceiver_threshold_info(self): + """ + Retrieves threshold info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_STATUS|ifname ; DOM threshold information for module on port + ; field = value + temphighalarm = FLOAT ; temperature high alarm threshold in Celsius + temphighwarning = FLOAT ; temperature high warning threshold in Celsius + templowalarm = FLOAT ; temperature low alarm threshold in Celsius + templowwarning = FLOAT ; temperature low warning threshold in Celsius + vcchighalarm = FLOAT ; vcc high alarm threshold in V + vcchighwarning = FLOAT ; vcc high warning threshold in V + vcclowalarm = FLOAT ; vcc low alarm threshold in V + vcclowwarning = FLOAT ; vcc low warning threshold in V + txpowerhighalarm = FLOAT ; tx power high alarm threshold in mW + txpowerlowalarm = FLOAT ; tx power low alarm threshold in mW + txpowerhighwarning = FLOAT ; tx power high warning threshold in mW + txpowerlowwarning = FLOAT ; tx power low alarm threshold in mW + rxpowerhighalarm = FLOAT ; rx power high alarm threshold in mW + rxpowerlowalarm = FLOAT ; rx power low alarm threshold in mW + rxpowerhighwarning = FLOAT ; rx power high warning threshold in mW + rxpowerlowwarning = FLOAT ; rx power low warning threshold in mW + txbiashighalarm = FLOAT ; tx bias high alarm threshold in mA + txbiaslowalarm = FLOAT ; tx bias low alarm threshold in mA + txbiashighwarning = FLOAT ; tx bias high warning threshold in mA + txbiaslowwarning = FLOAT ; tx bias low warning threshold in mA + lasertemphighalarm = FLOAT ; laser temperature high alarm threshold in Celsius + lasertemplowalarm = FLOAT ; laser temperature low alarm threshold in Celsius + lasertemphighwarning = FLOAT ; laser temperature high warning threshold in Celsius + lasertemplowwarning = FLOAT ; laser temperature low warning threshold in Celsius + prefecberhighalarm = FLOAT ; prefec ber high alarm threshold + prefecberlowalarm = FLOAT ; prefec ber low alarm threshold + prefecberhighwarning = FLOAT ; prefec ber high warning threshold + prefecberlowwarning = FLOAT ; prefec ber low warning threshold + postfecberhighalarm = FLOAT ; postfec ber high alarm threshold + postfecberlowalarm = FLOAT ; postfec ber low alarm threshold + postfecberhighwarning = FLOAT ; postfec ber high warning threshold + postfecberlowwarning = FLOAT ; postfec ber low warning threshold + biasxihighalarm = FLOAT ; bias xi high alarm threshold in percent + biasxilowalarm = FLOAT ; bias xi low alarm threshold in percent + biasxihighwarning = FLOAT ; bias xi high warning threshold in percent + biasxilowwarning = FLOAT ; bias xi low warning threshold in percent + biasxqhighalarm = FLOAT ; bias xq high alarm threshold in percent + biasxqlowalarm = FLOAT ; bias xq low alarm threshold in percent + biasxqhighwarning = FLOAT ; bias xq high warning threshold in percent + biasxqlowwarning = FLOAT ; bias xq low warning threshold in percent + biasxphighalarm = FLOAT ; bias xp high alarm threshold in percent + biasxplowalarm = FLOAT ; bias xp low alarm threshold in percent + biasxphighwarning = FLOAT ; bias xp high warning threshold in percent + biasxplowwarning = FLOAT ; bias xp low warning threshold in percent + biasyihighalarm = FLOAT ; bias yi high alarm threshold in percent + biasyilowalarm = FLOAT ; bias yi low alarm threshold in percent + biasyihighwarning = FLOAT ; bias yi high warning threshold in percent + biasyilowwarning = FLOAT ; bias yi low warning threshold in percent + biasyqhighalarm = FLOAT ; bias yq high alarm threshold in percent + biasyqlowalarm = FLOAT ; bias yq low alarm threshold in percent + biasyqhighwarning = FLOAT ; bias yq high warning threshold in percent + biasyqlowwarning = FLOAT ; bias yq low warning threshold in percent + biasyphighalarm = FLOAT ; bias yp high alarm threshold in percent + biasyplowalarm = FLOAT ; bias yp low alarm threshold in percent + biasyphighwarning = FLOAT ; bias yp high warning threshold in percent + biasyplowwarning = FLOAT ; bias yp low warning threshold in percent + cdshorthighalarm = FLOAT ; cd short high alarm threshold in ps/nm + cdshortlowalarm = FLOAT ; cd short low alarm threshold in ps/nm + cdshorthighwarning = FLOAT ; cd short high warning threshold in ps/nm + cdshortlowwarning = FLOAT ; cd short low warning threshold in ps/nm + cdlonghighalarm = FLOAT ; cd long high alarm threshold in ps/nm + cdlonglowalarm = FLOAT ; cd long low alarm threshold in ps/nm + cdlonghighwarning = FLOAT ; cd long high warning threshold in ps/nm + cdlonglowwarning = FLOAT ; cd long low warning threshold in ps/nm + dgdhighalarm = FLOAT ; dgd high alarm threshold in ps + dgdlowalarm = FLOAT ; dgd low alarm threshold in ps + dgdhighwarning = FLOAT ; dgd high warning threshold in ps + dgdlowwarning = FLOAT ; dgd low warning threshold in ps + sopmdhighalarm = FLOAT ; sopmd high alarm threshold in ps^2 + sopmdlowalarm = FLOAT ; sopmd low alarm threshold in ps^2 + sopmdhighwarning = FLOAT ; sopmd high warning threshold in ps^2 + sopmdlowwarning = FLOAT ; sopmd low warning threshold in ps^2 + pdlhighalarm = FLOAT ; pdl high alarm threshold in db + pdllowalarm = FLOAT ; pdl low alarm threshold in db + pdlhighwarning = FLOAT ; pdl high warning threshold in db + pdllowwarning = FLOAT ; pdl low warning threshold in db + osnrhighalarm = FLOAT ; osnr high alarm threshold in db + osnrlowalarm = FLOAT ; osnr low alarm threshold in db + osnrhighwarning = FLOAT ; osnr high warning threshold in db + osnrlowwarning = FLOAT ; osnr low warning threshold in db + esnrhighalarm = FLOAT ; esnr high alarm threshold in db + esnrlowalarm = FLOAT ; esnr low alarm threshold in db + esnrhighwarning = FLOAT ; esnr high warning threshold in db + esnrlowwarning = FLOAT ; esnr low warning threshold in db + cfohighalarm = FLOAT ; cfo high alarm threshold in MHz + cfolowalarm = FLOAT ; cfo low alarm threshold in MHz + cfohighwarning = FLOAT ; cfo high warning threshold in MHz + cfolowwarning = FLOAT ; cfo low warning threshold in MHz + txcurrpowerhighalarm = FLOAT ; txcurrpower high alarm threshold in dbm + txcurrpowerlowalarm = FLOAT ; txcurrpower low alarm threshold in dbm + txcurrpowerhighwarning = FLOAT ; txcurrpower high warning threshold in dbm + txcurrpowerlowwarning = FLOAT ; txcurrpower low warning threshold in dbm + rxtotpowerhighalarm = FLOAT ; rxtotpower high alarm threshold in dbm + rxtotpowerlowalarm = FLOAT ; rxtotpower low alarm threshold in dbm + rxtotpowerhighwarning = FLOAT ; rxtotpower high warning threshold in dbm + rxtotpowerlowwarning = FLOAT ; rxtotpower low warning threshold in dbm + rxsigpowerhighalarm = FLOAT ; rxsigpower high alarm threshold in dbm + rxsigpowerlowalarm = FLOAT ; rxsigpower low alarm threshold in dbm + rxsigpowerhighwarning = FLOAT ; rxsigpower high warning threshold in dbm + rxsigpowerlowwarning = FLOAT ; rxsigpower low warning threshold in dbm + ======================================================================== + """ + trans_dom_th = super(CCmisApi,self).get_transceiver_threshold_info() + trans_dom_th['biasxihighalarm'] = self.vdm_dict['Modulator Bias X/I [%]'][1][1] + trans_dom_th['biasxilowalarm'] = self.vdm_dict['Modulator Bias X/I [%]'][1][2] + trans_dom_th['biasxihighwarning'] = self.vdm_dict['Modulator Bias X/I [%]'][1][3] + trans_dom_th['biasxilowwarning'] = self.vdm_dict['Modulator Bias X/I [%]'][1][4] + trans_dom_th['biasxqhighalarm'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][1] + trans_dom_th['biasxqlowalarm'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][2] + trans_dom_th['biasxqhighwarning'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][3] + trans_dom_th['biasxqlowwarning'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][4] + trans_dom_th['biasxphighalarm'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][1] + trans_dom_th['biasxplowalarm'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][2] + trans_dom_th['biasxphighwarning'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][3] + trans_dom_th['biasxplowwarning'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][4] + trans_dom_th['biasyihighalarm'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][1] + trans_dom_th['biasyilowalarm'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][2] + trans_dom_th['biasyihighwarning'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][3] + trans_dom_th['biasyilowwarning'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][4] + trans_dom_th['biasyqhighalarm'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][1] + trans_dom_th['biasyqlowalarm'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][2] + trans_dom_th['biasyqhighwarning'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][3] + trans_dom_th['biasyqlowwarning'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][4] + trans_dom_th['biasyphighalarm'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][1] + trans_dom_th['biasyplowalarm'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][2] + trans_dom_th['biasyphighwarning'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][3] + trans_dom_th['biasyplowwarning'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][4] + trans_dom_th['cdshorthighalarm'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][1] + trans_dom_th['cdshortlowalarm'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][2] + trans_dom_th['cdshorthighwarning'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][3] + trans_dom_th['cdshortlowwarning'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][4] + try: + trans_dom_th['cdlonghighalarm'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][1] + trans_dom_th['cdlonglowalarm'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][2] + trans_dom_th['cdlonghighwarning'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][3] + trans_dom_th['cdlonglowwarning'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][4] + except KeyError: + pass + trans_dom_th['dgdhighalarm'] = self.vdm_dict['DGD [ps]'][1][1] + trans_dom_th['dgdlowalarm'] = self.vdm_dict['DGD [ps]'][1][2] + trans_dom_th['dgdhighwarning'] = self.vdm_dict['DGD [ps]'][1][3] + trans_dom_th['dgdlowwarning'] = self.vdm_dict['DGD [ps]'][1][4] + try: + trans_dom_th['sopmdhighalarm'] = self.vdm_dict['SOPMD [ps^2]'][1][1] + trans_dom_th['sopmdlowalarm'] = self.vdm_dict['SOPMD [ps^2]'][1][2] + trans_dom_th['sopmdhighwarning'] = self.vdm_dict['SOPMD [ps^2]'][1][3] + trans_dom_th['sopmdlowwarning'] = self.vdm_dict['SOPMD [ps^2]'][1][4] + except KeyError: + pass + trans_dom_th['pdlhighalarm'] = self.vdm_dict['PDL [dB]'][1][1] + trans_dom_th['pdllowalarm'] = self.vdm_dict['PDL [dB]'][1][2] + trans_dom_th['pdlhighwarning'] = self.vdm_dict['PDL [dB]'][1][3] + trans_dom_th['pdllowwarning'] = self.vdm_dict['PDL [dB]'][1][4] + trans_dom_th['osnrhighalarm'] = self.vdm_dict['OSNR [dB]'][1][1] + trans_dom_th['osnrlowalarm'] = self.vdm_dict['OSNR [dB]'][1][2] + trans_dom_th['osnrhighwarning'] = self.vdm_dict['OSNR [dB]'][1][3] + trans_dom_th['osnrlowwarning'] = self.vdm_dict['OSNR [dB]'][1][4] + trans_dom_th['esnrhighalarm'] = self.vdm_dict['eSNR [dB]'][1][1] + trans_dom_th['esnrlowalarm'] = self.vdm_dict['eSNR [dB]'][1][2] + trans_dom_th['esnrhighwarning'] = self.vdm_dict['eSNR [dB]'][1][3] + trans_dom_th['esnrlowwarning'] = self.vdm_dict['eSNR [dB]'][1][4] + trans_dom_th['cfohighalarm'] = self.vdm_dict['CFO [MHz]'][1][1] + trans_dom_th['cfolowalarm'] = self.vdm_dict['CFO [MHz]'][1][2] + trans_dom_th['cfohighwarning'] = self.vdm_dict['CFO [MHz]'][1][3] + trans_dom_th['cfolowwarning'] = self.vdm_dict['CFO [MHz]'][1][4] + trans_dom_th['txcurrpowerhighalarm'] = self.vdm_dict['Tx Power [dBm]'][1][1] + trans_dom_th['txcurrpowerlowalarm'] = self.vdm_dict['Tx Power [dBm]'][1][2] + trans_dom_th['txcurrpowerhighwarning'] = self.vdm_dict['Tx Power [dBm]'][1][3] + trans_dom_th['txcurrpowerlowwarning'] = self.vdm_dict['Tx Power [dBm]'][1][4] + trans_dom_th['rxtotpowerhighalarm'] = self.vdm_dict['Rx Total Power [dBm]'][1][1] + trans_dom_th['rxtotpowerlowalarm'] = self.vdm_dict['Rx Total Power [dBm]'][1][2] + trans_dom_th['rxtotpowerhighwarning'] = self.vdm_dict['Rx Total Power [dBm]'][1][3] + trans_dom_th['rxtotpowerlowwarning'] = self.vdm_dict['Rx Total Power [dBm]'][1][4] + try: + trans_dom_th['rxsigpowerhighalarm'] = self.vdm_dict['Rx Signal Power [dBm]'][1][1] + trans_dom_th['rxsigpowerlowalarm'] = self.vdm_dict['Rx Signal Power [dBm]'][1][2] + trans_dom_th['rxsigpowerhighwarning'] = self.vdm_dict['Rx Signal Power [dBm]'][1][3] + trans_dom_th['rxsigpowerlowwarning'] = self.vdm_dict['Rx Signal Power [dBm]'][1][4] + except KeyError: + pass + return trans_dom_th + + def get_transceiver_status(self): + """ + Retrieves transceiver status of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_STATUS|ifname ; Error information for module on port + ; field = value + status = 1*255VCHAR ; code of the module status (plug in, plug out) + error = 1*255VCHAR ; module error (N/A or a string consisting of error descriptions joined by "|", like "error1 | error2" ) + module_state = 1*255VCHAR ; current module state (ModuleLowPwr, ModulePwrUp, ModuleReady, ModulePwrDn, Fault) + module_fault_cause = 1*255VCHAR ; reason of entering the module fault state + datapath_firmware_fault = BOOLEAN ; datapath (DSP) firmware fault + module_firmware_fault = BOOLEAN ; module firmware fault + module_state_changed = BOOLEAN ; module state changed + datapath_hostlane1 = 1*255VCHAR ; data path state indicator on host lane 1 + datapath_hostlane2 = 1*255VCHAR ; data path state indicator on host lane 2 + datapath_hostlane3 = 1*255VCHAR ; data path state indicator on host lane 3 + datapath_hostlane4 = 1*255VCHAR ; data path state indicator on host lane 4 + datapath_hostlane5 = 1*255VCHAR ; data path state indicator on host lane 5 + datapath_hostlane6 = 1*255VCHAR ; data path state indicator on host lane 6 + datapath_hostlane7 = 1*255VCHAR ; data path state indicator on host lane 7 + datapath_hostlane8 = 1*255VCHAR ; data path state indicator on host lane 8 + txoutput_status = BOOLEAN ; tx output status on media lane + rxoutput_status_hostlane1 = BOOLEAN ; rx output status on host lane 1 + rxoutput_status_hostlane2 = BOOLEAN ; rx output status on host lane 2 + rxoutput_status_hostlane3 = BOOLEAN ; rx output status on host lane 3 + rxoutput_status_hostlane4 = BOOLEAN ; rx output status on host lane 4 + rxoutput_status_hostlane5 = BOOLEAN ; rx output status on host lane 5 + rxoutput_status_hostlane6 = BOOLEAN ; rx output status on host lane 6 + rxoutput_status_hostlane7 = BOOLEAN ; rx output status on host lane 7 + rxoutput_status_hostlane8 = BOOLEAN ; rx output status on host lane 8 + txfault = BOOLEAN ; tx fault flag on media lane + txlos_hostlane1 = BOOLEAN ; tx loss of signal flag on host lane 1 + txlos_hostlane2 = BOOLEAN ; tx loss of signal flag on host lane 2 + txlos_hostlane3 = BOOLEAN ; tx loss of signal flag on host lane 3 + txlos_hostlane4 = BOOLEAN ; tx loss of signal flag on host lane 4 + txlos_hostlane5 = BOOLEAN ; tx loss of signal flag on host lane 5 + txlos_hostlane6 = BOOLEAN ; tx loss of signal flag on host lane 6 + txlos_hostlane7 = BOOLEAN ; tx loss of signal flag on host lane 7 + txlos_hostlane8 = BOOLEAN ; tx loss of signal flag on host lane 8 + txcdrlol_hostlane1 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 1 + txcdrlol_hostlane2 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 2 + txcdrlol_hostlane3 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 3 + txcdrlol_hostlane4 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 4 + txcdrlol_hostlane5 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 5 + txcdrlol_hostlane6 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 6 + txcdrlol_hostlane7 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 7 + txcdrlol_hostlane8 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 8 + rxlos = BOOLEAN ; rx loss of signal flag on media lane + rxcdrlol = BOOLEAN ; rx clock and data recovery loss of lock on media lane + config_state_hostlane1 = 1*255VCHAR ; configuration status for the data path of host line 1 + config_state_hostlane2 = 1*255VCHAR ; configuration status for the data path of host line 2 + config_state_hostlane3 = 1*255VCHAR ; configuration status for the data path of host line 3 + config_state_hostlane4 = 1*255VCHAR ; configuration status for the data path of host line 4 + config_state_hostlane5 = 1*255VCHAR ; configuration status for the data path of host line 5 + config_state_hostlane6 = 1*255VCHAR ; configuration status for the data path of host line 6 + config_state_hostlane7 = 1*255VCHAR ; configuration status for the data path of host line 7 + config_state_hostlane8 = 1*255VCHAR ; configuration status for the data path of host line 8 + dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 + dpinit_pending_hostlane2 = BOOLEAN ; data path configuration updated on host lane 2 + dpinit_pending_hostlane3 = BOOLEAN ; data path configuration updated on host lane 3 + dpinit_pending_hostlane4 = BOOLEAN ; data path configuration updated on host lane 4 + dpinit_pending_hostlane5 = BOOLEAN ; data path configuration updated on host lane 5 + dpinit_pending_hostlane6 = BOOLEAN ; data path configuration updated on host lane 6 + dpinit_pending_hostlane7 = BOOLEAN ; data path configuration updated on host lane 7 + dpinit_pending_hostlane8 = BOOLEAN ; data path configuration updated on host lane 8 + tuning_in_progress = BOOLEAN ; tuning in progress status + wavelength_unlock_status = BOOLEAN ; laser unlocked status + target_output_power_oor = BOOLEAN ; target output power out of range flag + fine_tuning_oor = BOOLEAN ; fine tuning out of range flag + tuning_not_accepted = BOOLEAN ; tuning not accepted flag + invalid_channel_num = BOOLEAN ; invalid channel number flag + tuning_complete = BOOLEAN ; tuning complete flag + temphighalarm_flag = BOOLEAN ; temperature high alarm flag + temphighwarning_flag = BOOLEAN ; temperature high warning flag + templowalarm_flag = BOOLEAN ; temperature low alarm flag + templowwarning_flag = BOOLEAN ; temperature low warning flag + vcchighalarm_flag = BOOLEAN ; vcc high alarm flag + vcchighwarning_flag = BOOLEAN ; vcc high warning flag + vcclowalarm_flag = BOOLEAN ; vcc low alarm flag + vcclowwarning_flag = BOOLEAN ; vcc low warning flag + txpowerhighalarm_flag = BOOLEAN ; tx power high alarm flag + txpowerlowalarm_flag = BOOLEAN ; tx power low alarm flag + txpowerhighwarning_flag = BOOLEAN ; tx power high warning flag + txpowerlowwarning_flag = BOOLEAN ; tx power low alarm flag + rxpowerhighalarm_flag = BOOLEAN ; rx power high alarm flag + rxpowerlowalarm_flag = BOOLEAN ; rx power low alarm flag + rxpowerhighwarning_flag = BOOLEAN ; rx power high warning flag + rxpowerlowwarning_flag = BOOLEAN ; rx power low warning flag + txbiashighalarm_flag = BOOLEAN ; tx bias high alarm flag + txbiaslowalarm_flag = BOOLEAN ; tx bias low alarm flag + txbiashighwarning_flag = BOOLEAN ; tx bias high warning flag + txbiaslowwarning_flag = BOOLEAN ; tx bias low warning flag + lasertemphighalarm_flag = BOOLEAN ; laser temperature high alarm flag + lasertemplowalarm_flag = BOOLEAN ; laser temperature low alarm flag + lasertemphighwarning_flag = BOOLEAN ; laser temperature high warning flag + lasertemplowwarning_flag = BOOLEAN ; laser temperature low warning flag + prefecberhighalarm_flag = BOOLEAN ; prefec ber high alarm flag + prefecberlowalarm_flag = BOOLEAN ; prefec ber low alarm flag + prefecberhighwarning_flag = BOOLEAN ; prefec ber high warning flag + prefecberlowwarning_flag = BOOLEAN ; prefec ber low warning flag + postfecberhighalarm_flag = BOOLEAN ; postfec ber high alarm flag + postfecberlowalarm_flag = BOOLEAN ; postfec ber low alarm flag + postfecberhighwarning_flag = BOOLEAN ; postfec ber high warning flag + postfecberlowwarning_flag = BOOLEAN ; postfec ber low warning flag + biasxihighalarm_flag = BOOLEAN ; bias xi high alarm flag + biasxilowalarm_flag = BOOLEAN ; bias xi low alarm flag + biasxihighwarning_flag = BOOLEAN ; bias xi high warning flag + biasxilowwarning_flag = BOOLEAN ; bias xi low warning flag + biasxqhighalarm_flag = BOOLEAN ; bias xq high alarm flag + biasxqlowalarm_flag = BOOLEAN ; bias xq low alarm flag + biasxqhighwarning_flag = BOOLEAN ; bias xq high warning flag + biasxqlowwarning_flag = BOOLEAN ; bias xq low warning flag + biasxphighalarm_flag = BOOLEAN ; bias xp high alarm flag + biasxplowalarm_flag = BOOLEAN ; bias xp low alarm flag + biasxphighwarning_flag = BOOLEAN ; bias xp high warning flag + biasxplowwarning_flag = BOOLEAN ; bias xp low warning flag + biasyihighalarm_flag = BOOLEAN ; bias yi high alarm flag + biasyilowalarm_flag = BOOLEAN ; bias yi low alarm flag + biasyihighwarning_flag = BOOLEAN ; bias yi high warning flag + biasyilowwarning_flag = BOOLEAN ; bias yi low warning flag + biasyqhighalarm_flag = BOOLEAN ; bias yq high alarm flag + biasyqlowalarm_flag = BOOLEAN ; bias yq low alarm flag + biasyqhighwarning_flag = BOOLEAN ; bias yq high warning flag + biasyqlowwarning_flag = BOOLEAN ; bias yq low warning flag + biasyphighalarm_flag = BOOLEAN ; bias yp high alarm flag + biasyplowalarm_flag = BOOLEAN ; bias yp low alarm flag + biasyphighwarning_flag = BOOLEAN ; bias yp high warning flag + biasyplowwarning_flag = BOOLEAN ; bias yp low warning flag + cdshorthighalarm_flag = BOOLEAN ; cd short high alarm flag + cdshortlowalarm_flag = BOOLEAN ; cd short low alarm flag + cdshorthighwarning_flag = BOOLEAN ; cd short high warning flag + cdshortlowwarning_flag = BOOLEAN ; cd short low warning flag + cdlonghighalarm_flag = BOOLEAN ; cd long high alarm flag + cdlonglowalarm_flag = BOOLEAN ; cd long low alarm flag + cdlonghighwarning_flag = BOOLEAN ; cd long high warning flag + cdlonglowwarning_flag = BOOLEAN ; cd long low warning flag + dgdhighalarm_flag = BOOLEAN ; dgd high alarm flag + dgdlowalarm_flag = BOOLEAN ; dgd low alarm flag + dgdhighwarning_flag = BOOLEAN ; dgd high warning flag + dgdlowwarning_flag = BOOLEAN ; dgd low warning flag + sopmdhighalarm_flag = BOOLEAN ; sopmd high alarm flag + sopmdlowalarm_flag = BOOLEAN ; sopmd low alarm flag + sopmdhighwarning_flag = BOOLEAN ; sopmd high warning flag + sopmdlowwarning_flag = BOOLEAN ; sopmd low warning flag + pdlhighalarm_flag = BOOLEAN ; pdl high alarm flag + pdllowalarm_flag = BOOLEAN ; pdl low alarm flag + pdlhighwarning_flag = BOOLEAN ; pdl high warning flag + pdllowwarning_flag = BOOLEAN ; pdl low warning flag + osnrhighalarm_flag = BOOLEAN ; osnr high alarm flag + osnrlowalarm_flag = BOOLEAN ; osnr low alarm flag + osnrhighwarning_flag = BOOLEAN ; osnr high warning flag + osnrlowwarning_flag = BOOLEAN ; osnr low warning flag + esnrhighalarm_flag = BOOLEAN ; esnr high alarm flag + esnrlowalarm_flag = BOOLEAN ; esnr low alarm flag + esnrhighwarning_flag = BOOLEAN ; esnr high warning flag + esnrlowwarning_flag = BOOLEAN ; esnr low warning flag + cfohighalarm_flag = BOOLEAN ; cfo high alarm flag + cfolowalarm_flag = BOOLEAN ; cfo low alarm flag + cfohighwarning_flag = BOOLEAN ; cfo high warning flag + cfolowwarning_flag = BOOLEAN ; cfo low warning flag + txcurrpowerhighalarm_flag = BOOLEAN ; txcurrpower high alarm flag + txcurrpowerlowalarm_flag = BOOLEAN ; txcurrpower low alarm flag + txcurrpowerhighwarning_flag = BOOLEAN ; txcurrpower high warning flag + txcurrpowerlowwarning_flag = BOOLEAN ; txcurrpower low warning flag + rxtotpowerhighalarm_flag = BOOLEAN ; rxtotpower high alarm flag + rxtotpowerlowalarm_flag = BOOLEAN ; rxtotpower low alarm flag + rxtotpowerhighwarning_flag = BOOLEAN ; rxtotpower high warning flag + rxtotpowerlowwarning_flag = BOOLEAN ; rxtotpower low warning flag + rxsigpowerhighalarm_flag = BOOLEAN ; rxsigpower high alarm flag + rxsigpowerlowalarm_flag = BOOLEAN ; rxsigpower low alarm flag + rxsigpowerhighwarning_flag = BOOLEAN ; rxsigpower high warning flag + rxsigpowerlowwarning_flag = BOOLEAN ; rxsigpower low warning flag + ================================================================================ + """ + trans_status = super(CCmisApi,self).get_transceiver_status() + trans_status['tuning_in_progress'] = self.get_tuning_in_progress() + trans_status['wavelength_unlock_status'] = self.get_wavelength_unlocked() + laser_tuning_summary = self.get_laser_tuning_summary() + trans_status['target_output_power_oor'] = 'TargetOutputPowerOOR' in laser_tuning_summary + trans_status['fine_tuning_oor'] = 'FineTuningOutOfRange' in laser_tuning_summary + trans_status['tuning_not_accepted'] = 'TuningNotAccepted' in laser_tuning_summary + trans_status['invalid_channel_num'] = 'InvalidChannel' in laser_tuning_summary + trans_status['tuning_complete'] = 'TuningComplete' in laser_tuning_summary + trans_status['biasxihighalarm_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][5] + trans_status['biasxilowalarm_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][6] + trans_status['biasxihighwarning_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][7] + trans_status['biasxilowwarning_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][8] + trans_status['biasxqhighalarm_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][5] + trans_status['biasxqlowalarm_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][6] + trans_status['biasxqhighwarning_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][7] + trans_status['biasxqlowwarning_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][8] + trans_status['biasxphighalarm_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][5] + trans_status['biasxplowalarm_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][6] + trans_status['biasxphighwarning_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][7] + trans_status['biasxplowwarning_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][8] + trans_status['biasyihighalarm_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][5] + trans_status['biasyilowalarm_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][6] + trans_status['biasyihighwarning_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][7] + trans_status['biasyilowwarning_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][8] + trans_status['biasyqhighalarm_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][5] + trans_status['biasyqlowalarm_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][6] + trans_status['biasyqhighwarning_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][7] + trans_status['biasyqlowwarning_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][8] + trans_status['biasyphighalarm_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][5] + trans_status['biasyplowalarm_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][6] + trans_status['biasyphighwarning_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][7] + trans_status['biasyplowwarning_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][8] + trans_status['cdshorthighalarm_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][5] + trans_status['cdshortlowalarm_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][6] + trans_status['cdshorthighwarning_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][7] + trans_status['cdshortlowwarning_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][8] + try: + trans_status['cdlonghighalarm_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][5] + trans_status['cdlonglowalarm_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][6] + trans_status['cdlonghighwarning_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][7] + trans_status['cdlonglowwarning_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][8] + except KeyError: + pass + trans_status['dgdhighalarm_flag'] = self.vdm_dict['DGD [ps]'][1][5] + trans_status['dgdlowalarm_flag'] = self.vdm_dict['DGD [ps]'][1][6] + trans_status['dgdhighwarning_flag'] = self.vdm_dict['DGD [ps]'][1][7] + trans_status['dgdlowwarning_flag'] = self.vdm_dict['DGD [ps]'][1][8] + try: + trans_status['sopmdhighalarm_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][5] + trans_status['sopmdlowalarm_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][6] + trans_status['sopmdhighwarning_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][7] + trans_status['sopmdlowwarning_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][8] + except KeyError: + pass + trans_status['pdlhighalarm_flag'] = self.vdm_dict['PDL [dB]'][1][5] + trans_status['pdllowalarm_flag'] = self.vdm_dict['PDL [dB]'][1][6] + trans_status['pdlhighwarning_flag'] = self.vdm_dict['PDL [dB]'][1][7] + trans_status['pdllowwarning_flag'] = self.vdm_dict['PDL [dB]'][1][8] + trans_status['osnrhighalarm_flag'] = self.vdm_dict['OSNR [dB]'][1][5] + trans_status['osnrlowalarm_flag'] = self.vdm_dict['OSNR [dB]'][1][6] + trans_status['osnrhighwarning_flag'] = self.vdm_dict['OSNR [dB]'][1][7] + trans_status['osnrlowwarning_flag'] = self.vdm_dict['OSNR [dB]'][1][8] + trans_status['esnrhighalarm_flag'] = self.vdm_dict['eSNR [dB]'][1][5] + trans_status['esnrlowalarm_flag'] = self.vdm_dict['eSNR [dB]'][1][6] + trans_status['esnrhighwarning_flag'] = self.vdm_dict['eSNR [dB]'][1][7] + trans_status['esnrlowwarning_flag'] = self.vdm_dict['eSNR [dB]'][1][8] + trans_status['cfohighalarm_flag'] = self.vdm_dict['CFO [MHz]'][1][5] + trans_status['cfolowalarm_flag'] = self.vdm_dict['CFO [MHz]'][1][6] + trans_status['cfohighwarning_flag'] = self.vdm_dict['CFO [MHz]'][1][7] + trans_status['cfolowwarning_flag'] = self.vdm_dict['CFO [MHz]'][1][8] + trans_status['txcurrpowerhighalarm_flag'] = self.vdm_dict['Tx Power [dBm]'][1][5] + trans_status['txcurrpowerlowalarm_flag'] = self.vdm_dict['Tx Power [dBm]'][1][6] + trans_status['txcurrpowerhighwarning_flag'] = self.vdm_dict['Tx Power [dBm]'][1][7] + trans_status['txcurrpowerlowwarning_flag'] = self.vdm_dict['Tx Power [dBm]'][1][8] + trans_status['rxtotpowerhighalarm_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][5] + trans_status['rxtotpowerlowalarm_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][6] + trans_status['rxtotpowerhighwarning_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][7] + trans_status['rxtotpowerlowwarning_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][8] + trans_status['rxsigpowerhighalarm_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][5] + trans_status['rxsigpowerlowalarm_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][6] + trans_status['rxsigpowerhighwarning_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][7] + trans_status['rxsigpowerlowwarning_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][8] + return trans_status + + def get_transceiver_pm(self): + """ + Retrieves PM for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_PM|ifname ; information of PM on port + ; field = value + prefec_ber_avg = FLOAT ; prefec ber avg + prefec_ber_min = FLOAT ; prefec ber min + prefec_ber_max = FLOAT ; prefec ber max + uncorr_frames_avg = FLOAT ; uncorrected frames ratio avg + uncorr_frames_min = FLOAT ; uncorrected frames ratio min + uncorr_frames_max = FLOAT ; uncorrected frames ratio max + cd_avg = FLOAT ; chromatic dispersion avg + cd_min = FLOAT ; chromatic dispersion min + cd_max = FLOAT ; chromatic dispersion max + dgd_avg = FLOAT ; differential group delay avg + dgd_min = FLOAT ; differential group delay min + dgd_max = FLOAT ; differential group delay max + sopmd_avg = FLOAT ; second order polarization mode dispersion avg + sopmd_min = FLOAT ; second order polarization mode dispersion min + sopmd_max = FLOAT ; second order polarization mode dispersion max + pdl_avg = FLOAT ; polarization dependent loss avg + pdl_min = FLOAT ; polarization dependent loss min + pdl_max = FLOAT ; polarization dependent loss max + osnr_avg = FLOAT ; optical signal to noise ratio avg + osnr_min = FLOAT ; optical signal to noise ratio min + osnr_max = FLOAT ; optical signal to noise ratio max + esnr_avg = FLOAT ; electrical signal to noise ratio avg + esnr_min = FLOAT ; electrical signal to noise ratio min + esnr_max = FLOAT ; electrical signal to noise ratio max + cfo_avg = FLOAT ; carrier frequency offset avg + cfo_min = FLOAT ; carrier frequency offset min + cfo_max = FLOAT ; carrier frequency offset max + soproc_avg = FLOAT ; state of polarization rate of change avg + soproc_min = FLOAT ; state of polarization rate of change min + soproc_max = FLOAT ; state of polarization rate of change max + tx_power_avg = FLOAT ; tx output power avg + tx_power_min = FLOAT ; tx output power min + tx_power_max = FLOAT ; tx output power max + rx_tot_power_avg = FLOAT ; rx total power avg + rx_tot_power_min = FLOAT ; rx total power min + rx_tot_power_max = FLOAT ; rx total power max + rx_sig_power_avg = FLOAT ; rx signal power avg + rx_sig_power_min = FLOAT ; rx signal power min + rx_sig_power_max = FLOAT ; rx signal power max + ======================================================================== + """ + trans_pm = dict() + PM_dict = self.get_pm_all() + trans_pm['prefec_ber_avg'] = PM_dict['preFEC_BER_avg'] + trans_pm['prefec_ber_min'] = PM_dict['preFEC_BER_min'] + trans_pm['prefec_ber_max'] = PM_dict['preFEC_BER_max'] + trans_pm['uncorr_frames_avg'] = PM_dict['preFEC_uncorr_frame_ratio_avg'] + trans_pm['uncorr_frames_min'] = PM_dict['preFEC_uncorr_frame_ratio_min'] + trans_pm['uncorr_frames_max'] = PM_dict['preFEC_uncorr_frame_ratio_max'] + trans_pm['cd_avg'] = PM_dict['rx_cd_avg'] + trans_pm['cd_min'] = PM_dict['rx_cd_min'] + trans_pm['cd_max'] = PM_dict['rx_cd_max'] + trans_pm['dgd_avg'] = PM_dict['rx_dgd_avg'] + trans_pm['dgd_min'] = PM_dict['rx_dgd_min'] + trans_pm['dgd_max'] = PM_dict['rx_dgd_max'] + trans_pm['sopmd_avg'] = PM_dict['rx_sopmd_avg'] + trans_pm['sopmd_min'] = PM_dict['rx_sopmd_min'] + trans_pm['sopmd_max'] = PM_dict['rx_sopmd_max'] + trans_pm['pdl_avg'] = PM_dict['rx_pdl_avg'] + trans_pm['pdl_min'] = PM_dict['rx_pdl_min'] + trans_pm['pdl_max'] = PM_dict['rx_pdl_max'] + trans_pm['osnr_avg'] = PM_dict['rx_osnr_avg'] + trans_pm['osnr_min'] = PM_dict['rx_osnr_min'] + trans_pm['osnr_max'] = PM_dict['rx_osnr_max'] + trans_pm['esnr_avg'] = PM_dict['rx_esnr_avg'] + trans_pm['esnr_min'] = PM_dict['rx_esnr_min'] + trans_pm['esnr_max'] = PM_dict['rx_esnr_max'] + trans_pm['cfo_avg'] = PM_dict['rx_cfo_avg'] + trans_pm['cfo_min'] = PM_dict['rx_cfo_min'] + trans_pm['cfo_max'] = PM_dict['rx_cfo_max'] + trans_pm['soproc_avg'] = PM_dict['rx_soproc_avg'] + trans_pm['soproc_min'] = PM_dict['rx_soproc_min'] + trans_pm['soproc_max'] = PM_dict['rx_soproc_max'] + trans_pm['tx_power_avg'] = PM_dict['tx_power_avg'] + trans_pm['tx_power_min'] = PM_dict['tx_power_min'] + trans_pm['tx_power_max'] = PM_dict['tx_power_max'] + trans_pm['rx_tot_power_avg'] = PM_dict['rx_power_avg'] + trans_pm['rx_tot_power_min'] = PM_dict['rx_power_min'] + trans_pm['rx_tot_power_max'] = PM_dict['rx_power_max'] + trans_pm['rx_sig_power_avg'] = PM_dict['rx_sigpwr_avg'] + trans_pm['rx_sig_power_min'] = PM_dict['rx_sigpwr_min'] + trans_pm['rx_sig_power_max'] = PM_dict['rx_sigpwr_max'] + return trans_pm diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index b1929f4d8e23..73f6d4def484 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -7,6 +7,16 @@ from ...fields import consts from ..xcvr_api import XcvrApi +import logging +from ...fields import consts +from ..xcvr_api import XcvrApi +from .cmisCDB import CmisCdbApi +from .cmisVDM import CmisVdmApi +import time + +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) + class CmisApi(XcvrApi): NUM_CHANNELS = 8 @@ -14,15 +24,87 @@ def __init__(self, xcvr_eeprom): super(CmisApi, self).__init__(xcvr_eeprom) def get_model(self): + ''' + This function returns the part number of the module + ''' return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD) + def get_vendor_rev(self): + ''' + This function returns the revision level for part number provided by vendor + ''' + return self.xcvr_eeprom.read(consts.VENDOR_REV_FIELD) + def get_serial(self): + ''' + This function returns the serial number of the module + ''' return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO_FIELD) + def get_module_type(self): + ''' + This function returns the SFF8024Identifier (module type / form-factor). Table 4-1 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.ID_FIELD) + + def get_connector_type(self): + ''' + This function returns module connector. Table 4-3 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.CONNECTOR_FIELD) + + def get_module_hardware_revision(self): + ''' + This function returns the module hardware revision + ''' + hw_major_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]] + return '.'.join(hw_rev) + + def get_cmis_rev(self): + ''' + This function returns the CMIS version the module complies to + ''' + cmis_major = self.xcvr_eeprom.read(consts.CMIS_MAJOR_REVISION) + cmis_minor = self.xcvr_eeprom.read(consts.CMIS_MINOR_REVISION) + cmis_rev = [str(num) for num in [cmis_major, cmis_minor]] + return '.'.join(cmis_rev) + + # Transceiver status + def get_module_state(self): + ''' + This function returns the module state + ''' + return self.xcvr_eeprom.read(consts.MODULE_STATE) + + def get_module_fault_cause(self): + ''' + This function returns the module fault cause + ''' + return self.xcvr_eeprom.read(consts.MODULE_FAULT_CAUSE) + + def get_module_active_firmware(self): + ''' + This function returns the active firmware version + ''' + active_fw_major = self.xcvr_eeprom.read(consts.ACTIVE_FW_MAJOR_REV) + active_fw_minor = self.xcvr_eeprom.read(consts.ACTIVE_FW_MINOR_REV) + active_fw = [str(num) for num in [active_fw_major, active_fw_minor]] + return '.'.join(active_fw) + + def get_module_inactive_firmware(self): + ''' + This function returns the inactive firmware version + ''' + inactive_fw_major = self.xcvr_eeprom.read(consts.INACTIVE_FW_MAJOR_REV) + inactive_fw_minor = self.xcvr_eeprom.read(consts.INACTIVE_FW_MINOR_REV) + inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]] + return '.'.join(inactive_fw) + def get_transceiver_info(self): admin_info = self.xcvr_eeprom.read(consts.ADMIN_INFO_FIELD) - media_type = self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD) - if admin_info is None or media_type is None: + if admin_info is None: return None ext_id = admin_info[consts.EXT_ID_FIELD] @@ -32,7 +114,7 @@ def get_transceiver_info(self): xcvr_info = { "type": admin_info[consts.ID_FIELD], "type_abbrv_name": admin_info[consts.ID_ABBRV_FIELD], - "hardware_rev": admin_info[consts.VENDOR_REV_FIELD], + "hardware_rev": '.'.join([str(admin_info[consts.HW_MAJOR_REV]),str(admin_info[consts.HW_MINOR_REV])]), "serial": admin_info[consts.VENDOR_SERIAL_NO_FIELD], "manufacturer": admin_info[consts.VENDOR_NAME_FIELD], "model": admin_info[consts.VENDOR_PART_NO_FIELD], @@ -40,15 +122,37 @@ def get_transceiver_info(self): "encoding": "N/A", # Not supported "ext_identifier": "%s (%sW Max)" % (power_class, max_power), "ext_rateselect_compliance": "N/A", # Not supported - "cable_type": "Length cable Assembly(m)", - "cable_length": float(admin_info[consts.LENGTH_ASSEMBLY_FIELD]), + "cable_type": "Length Cable Assembly(m)", + "cable_length": admin_info[consts.LENGTH_ASSEMBLY_FIELD], "nominal_bit_rate": 0, # Not supported - "specification_compliance": media_type, + "specification_compliance": admin_info[consts.MEDIA_TYPE_FIELD], "vendor_date": admin_info[consts.VENDOR_DATE_FIELD], "vendor_oui": admin_info[consts.VENDOR_OUI_FIELD], # TODO "application_advertisement": "N/A", } + xcvr_info['host_electrical_interface'] = self.get_host_electrical_interface() + xcvr_info['media_interface_code'] = self.get_module_media_interface() + xcvr_info['host_lane_count'] = self.get_host_lane_count() + xcvr_info['media_lane_count'] = self.get_media_lane_count() + xcvr_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() + xcvr_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() + apsel_dict = self.get_active_apsel_hostlane() + xcvr_info['active_apsel_hostlane1'] = apsel_dict['ActiveAppSelLane1'] + xcvr_info['active_apsel_hostlane2'] = apsel_dict['ActiveAppSelLane2'] + xcvr_info['active_apsel_hostlane3'] = apsel_dict['ActiveAppSelLane3'] + xcvr_info['active_apsel_hostlane4'] = apsel_dict['ActiveAppSelLane4'] + xcvr_info['active_apsel_hostlane5'] = apsel_dict['ActiveAppSelLane5'] + xcvr_info['active_apsel_hostlane6'] = apsel_dict['ActiveAppSelLane6'] + xcvr_info['active_apsel_hostlane7'] = apsel_dict['ActiveAppSelLane7'] + xcvr_info['active_apsel_hostlane8'] = apsel_dict['ActiveAppSelLane8'] + + xcvr_info['media_interface_technology'] = self.get_media_interface_technology() + xcvr_info['vendor_rev'] = self.get_vendor_rev() + xcvr_info['cmis_rev'] = self.get_cmis_rev() + xcvr_info['active_firmware'] = self.get_module_active_firmware() + xcvr_info['inactive_firmware'] = self.get_module_inactive_firmware() + xcvr_info['specification_compliance'] = self.get_module_media_type() return xcvr_info def get_transceiver_bulk_status(self): @@ -74,8 +178,8 @@ def get_transceiver_bulk_status(self): return None bulk_status = { - "rx_los": all(rx_los) if self.get_rx_los_support() else 'N/A', - "tx_fault": all(tx_fault) if self.get_tx_fault_support() else 'N/A', + "rx_los": all(rx_los.values()) if self.get_rx_los_support() else 'N/A', + "tx_fault": all(tx_fault.values()) if self.get_tx_fault_support() else 'N/A', "tx_disable": all(tx_disable), "tx_disabled_channel": tx_disabled_channel, "temperature": temp, @@ -83,10 +187,18 @@ def get_transceiver_bulk_status(self): } for i in range(1, self.NUM_CHANNELS + 1): - bulk_status["tx%dbias" % i] = tx_bias[i - 1] - bulk_status["rx%dpower" % i] = rx_power[i - 1] - bulk_status["tx%dpower" % i] = tx_power[i - 1] + bulk_status["tx%dbias" % i] = tx_bias['LaserBiasTx%dField' % i] + bulk_status["rx%dpower" % i] = rx_power['OpticalPowerRx%dField' %i] + bulk_status["tx%dpower" % i] = tx_power['OpticalPowerTx%dField' %i] + laser_temp_dict = self.get_laser_temperature() + bulk_status['laser_temperature'] = laser_temp_dict['monitor value'] + self.vdm_dict = self.get_vdm() + try: + bulk_status['prefec_ber'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][0] + bulk_status['postfec_ber'] = self.vdm_dict['Errored Frames Average Media Input'][1][0] + except KeyError: + pass return bulk_status def get_transceiver_threshold_info(self): @@ -112,7 +224,7 @@ def get_transceiver_threshold_info(self): if thresh is None: return None - return { + threshold_info_dict = { "temphighalarm": float("{:.3f}".format(thresh[consts.TEMP_HIGH_ALARM_FIELD])), "templowalarm": float("{:.3f}".format(thresh[consts.TEMP_LOW_ALARM_FIELD])), "temphighwarning": float("{:.3f}".format(thresh[consts.TEMP_HIGH_WARNING_FIELD])), @@ -121,7 +233,7 @@ def get_transceiver_threshold_info(self): "vcclowalarm": float("{:.3f}".format(thresh[consts.VOLTAGE_LOW_ALARM_FIELD])), "vcchighwarning": float("{:.3f}".format(thresh[consts.VOLTAGE_HIGH_WARNING_FIELD])), "vcclowwarning": float("{:.3f}".format(thresh[consts.VOLTAGE_LOW_WARNING_FIELD])), - "rxpowerhighalarm": float("{:.3f}".format(thresh[consts.RX_POWER_HIGH_ALARM_FIELD])), + "rxpowerhighalarm": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.RX_POWER_HIGH_ALARM_FIELD]))), "rxpowerlowalarm": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.RX_POWER_LOW_ALARM_FIELD]))), "rxpowerhighwarning": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.RX_POWER_HIGH_WARNING_FIELD]))), "rxpowerlowwarning": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.RX_POWER_LOW_WARNING_FIELD]))), @@ -134,16 +246,41 @@ def get_transceiver_threshold_info(self): "txbiashighwarning": float("{:.3f}".format(thresh[consts.TX_BIAS_HIGH_WARNING_FIELD])), "txbiaslowwarning": float("{:.3f}".format(thresh[consts.TX_BIAS_LOW_WARNING_FIELD])) } + laser_temp_dict = self.get_laser_temperature() + threshold_info_dict['lasertemphighalarm'] = laser_temp_dict['high alarm'] + threshold_info_dict['lasertemplowalarm'] = laser_temp_dict['low alarm'] + threshold_info_dict['lasertemphighwarning'] = laser_temp_dict['high warn'] + threshold_info_dict['lasertemplowwarning'] = laser_temp_dict['low warn'] + self.vdm_dict = self.get_vdm() + try: + threshold_info_dict['prefecberhighalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][1] + threshold_info_dict['prefecberlowalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][2] + threshold_info_dict['prefecberhighwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][3] + threshold_info_dict['prefecberlowwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][4] + threshold_info_dict['postfecberhighalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][1] + threshold_info_dict['postfecberlowalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][2] + threshold_info_dict['postfecberhighwarning'] = self.vdm_dict['Errored Frames Average Media Input'][1][3] + threshold_info_dict['postfecberlowwarning'] = self.vdm_dict['Errored Frames Average Media Input'][1][4] + except KeyError: + pass + return threshold_info_dict def get_module_temperature(self): + ''' + This function returns the module case temperature and its thresholds. Unit in deg C + ''' if not self.get_temperature_support(): return 'N/A' temp = self.xcvr_eeprom.read(consts.TEMPERATURE_FIELD) if temp is None: return None return float("{:.3f}".format(temp)) - + def get_voltage(self): + ''' + This function returns the monitored value of the 3.3-V supply voltage and its thresholds. + Unit in V + ''' if not self.get_voltage_support(): return 'N/A' voltage = self.xcvr_eeprom.read(consts.VOLTAGE_FIELD) @@ -153,7 +290,7 @@ def get_voltage(self): def is_flat_memory(self): return self.xcvr_eeprom.read(consts.FLAT_MEM_FIELD) - + def get_temperature_support(self): return not self.is_flat_memory() @@ -163,7 +300,29 @@ def get_voltage_support(self): def get_rx_los_support(self): return not self.is_flat_memory() + def get_tx_cdr_lol_support(self): + return not self.is_flat_memory() + + def get_tx_cdr_lol(self): + ''' + This function returns TX CDR LOL flag on TX host lane + ''' + tx_cdr_lol_support = self.get_tx_cdr_lol_support() + if tx_cdr_lol_support is None: + return None + if not tx_cdr_lol_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + tx_cdr_lol = self.xcvr_eeprom.read(consts.TX_CDR_LOL) + if tx_cdr_lol is None: + return None + for key, value in tx_cdr_lol.items(): + tx_cdr_lol[key] = bool(value) + return tx_cdr_lol + def get_rx_los(self): + ''' + This function returns RX LOS flag on RX media lane + ''' rx_los_support = self.get_rx_los_support() if rx_los_support is None: return None @@ -172,46 +331,164 @@ def get_rx_los(self): rx_los = self.xcvr_eeprom.read(consts.RX_LOS_FIELD) if rx_los is None: return None - return [bool(rx_los & (1 << i)) for i in range(self.NUM_CHANNELS)] + for key, value in rx_los.items(): + rx_los[key] = bool(value) + return rx_los + + def get_rx_cdr_lol_support(self): + return not self.is_flat_memory() + + def get_rx_cdr_lol(self): + ''' + This function returns RX CDR LOL flag on RX media lane + ''' + rx_cdr_lol_support = self.get_rx_cdr_lol_support() + if rx_cdr_lol_support is None: + return None + if not rx_cdr_lol_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + rx_cdr_lol = self.xcvr_eeprom.read(consts.RX_CDR_LOL) + if rx_cdr_lol is None: + return None + for key, value in rx_cdr_lol.items(): + rx_cdr_lol[key] = bool(value) + return rx_cdr_lol + + def get_tx_power_flag(self): + ''' + This function returns TX power out of range flag on TX media lane + ''' + tx_power_high_alarm_dict = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG) + tx_power_low_alarm_dict = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG) + tx_power_high_warn_dict = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN_FLAG) + tx_power_low_warn_dict = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN_FLAG) + if tx_power_high_alarm_dict is None or tx_power_low_alarm_dict is None or tx_power_high_warn_dict is None or tx_power_low_warn_dict is None: + return None + for key, value in tx_power_high_alarm_dict.items(): + tx_power_high_alarm_dict[key] = bool(value) + for key, value in tx_power_low_alarm_dict.items(): + tx_power_low_alarm_dict[key] = bool(value) + for key, value in tx_power_high_warn_dict.items(): + tx_power_high_warn_dict[key] = bool(value) + for key, value in tx_power_low_warn_dict.items(): + tx_power_low_warn_dict[key] = bool(value) + tx_power_flag_dict = {'tx_power_high_alarm': tx_power_high_alarm_dict, + 'tx_power_low_alarm': tx_power_low_alarm_dict, + 'tx_power_high_warn': tx_power_high_warn_dict, + 'tx_power_low_warn': tx_power_low_warn_dict,} + return tx_power_flag_dict + + def get_tx_bias_flag(self): + ''' + This function returns TX bias out of range flag on TX media lane + ''' + tx_bias_high_alarm_dict = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG) + tx_bias_low_alarm_dict = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG) + tx_bias_high_warn_dict = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_WARN_FLAG) + tx_bias_low_warn_dict = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_WARN_FLAG) + if tx_bias_high_alarm_dict is None or tx_bias_low_alarm_dict is None or tx_bias_high_warn_dict is None or tx_bias_low_warn_dict is None: + return None + for key, value in tx_bias_high_alarm_dict.items(): + tx_bias_high_alarm_dict[key] = bool(value) + for key, value in tx_bias_low_alarm_dict.items(): + tx_bias_low_alarm_dict[key] = bool(value) + for key, value in tx_bias_high_warn_dict.items(): + tx_bias_high_warn_dict[key] = bool(value) + for key, value in tx_bias_low_warn_dict.items(): + tx_bias_low_warn_dict[key] = bool(value) + tx_bias_flag_dict = {'tx_bias_high_alarm': tx_bias_high_alarm_dict, + 'tx_bias_low_alarm': tx_bias_low_alarm_dict, + 'tx_bias_high_warn': tx_bias_high_warn_dict, + 'tx_bias_low_warn': tx_bias_low_warn_dict,} + return tx_bias_flag_dict + + def get_rx_power_flag(self): + ''' + This function returns RX power out of range flag on RX media lane + ''' + rx_power_high_alarm_dict = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG) + rx_power_low_alarm_dict = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG) + rx_power_high_warn_dict = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN_FLAG) + rx_power_low_warn_dict = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN_FLAG) + if rx_power_high_alarm_dict is None or rx_power_low_alarm_dict is None or rx_power_high_warn_dict is None or rx_power_low_warn_dict is None: + return None + for key, value in rx_power_high_alarm_dict.items(): + rx_power_high_alarm_dict[key] = bool(value) + for key, value in rx_power_low_alarm_dict.items(): + rx_power_low_alarm_dict[key] = bool(value) + for key, value in rx_power_high_warn_dict.items(): + rx_power_high_warn_dict[key] = bool(value) + for key, value in rx_power_low_warn_dict.items(): + rx_power_low_warn_dict[key] = bool(value) + rx_power_flag_dict = {'rx_power_high_alarm': rx_power_high_alarm_dict, + 'rx_power_low_alarm': rx_power_low_alarm_dict, + 'rx_power_high_warn': rx_power_high_warn_dict, + 'rx_power_low_warn': rx_power_low_warn_dict,} + return rx_power_flag_dict + + def get_tx_output_status(self): + ''' + This function returns whether TX output signals are valid on TX media lane + ''' + tx_output_status_dict = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) + if tx_output_status_dict is None: + return None + for key, value in tx_output_status_dict.items(): + tx_output_status_dict[key] = bool(value) + return tx_output_status_dict + + def get_rx_output_status(self): + ''' + This function returns whether RX output signals are valid on RX host lane + ''' + rx_output_status_dict = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) + if rx_output_status_dict is None: + return None + for key, value in rx_output_status_dict.items(): + rx_output_status_dict[key] = bool(value) + return rx_output_status_dict def get_tx_bias_support(self): return not self.is_flat_memory() def get_tx_bias(self): + ''' + This function returns TX bias current on each media lane + ''' tx_bias_support = self.get_tx_bias_support() if tx_bias_support is None: return None if not tx_bias_support: return ["N/A" for _ in range(self.NUM_CHANNELS)] tx_bias = self.xcvr_eeprom.read(consts.TX_BIAS_FIELD) - if tx_bias is None: - return None - return [channel_bias for channel_bias in tx_bias.values()] - + return tx_bias + def get_tx_power(self): + ''' + This function returns TX output power in mW on each media lane + ''' tx_power_support = self.get_tx_power_support() if tx_power_support is None: return None if not tx_power_support: return ["N/A" for _ in range(self.NUM_CHANNELS)] tx_power = self.xcvr_eeprom.read(consts.TX_POWER_FIELD) - if tx_power is None: - return None - return [float("{:.3f}".format(channel_power)) for channel_power in tx_power.values()] + return tx_power def get_tx_power_support(self): return not self.is_flat_memory() def get_rx_power(self): + ''' + This function returns RX input power in mW on each media lane + ''' rx_power_support = self.get_rx_power_support() if rx_power_support is None: return None if not rx_power_support: return ["N/A" for _ in range(self.NUM_CHANNELS)] rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD) - if rx_power is None: - return None - return [float("{:.3f}".format(channel_power)) for channel_power in rx_power.values()] + return rx_power def get_rx_power_support(self): return not self.is_flat_memory() @@ -220,6 +497,9 @@ def get_tx_fault_support(self): return not self.is_flat_memory() and self.xcvr_eeprom.read(consts.TX_FAULT_SUPPORT_FIELD) def get_tx_fault(self): + ''' + This function returns TX fault flag on TX media lane + ''' tx_fault_support = self.get_tx_fault_support() if tx_fault_support is None: return None @@ -228,7 +508,28 @@ def get_tx_fault(self): tx_fault = self.xcvr_eeprom.read(consts.TX_FAULT_FIELD) if tx_fault is None: return None - return [bool(tx_fault & (1 << i)) for i in range(self.NUM_CHANNELS)] + for key, value in tx_fault.items(): + tx_fault[key] = bool(value) + return tx_fault + + def get_tx_los_support(self): + return not self.is_flat_memory() + + def get_tx_los(self): + ''' + This function returns TX LOS flag on TX host lane + ''' + tx_los_support = self.get_tx_los_support() + if tx_los_support is None: + return None + if not tx_los_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + tx_los = self.xcvr_eeprom.read(consts.TX_LOS_FIELD) + if tx_los is None: + return None + for key, value in tx_los.items(): + tx_los[key] = bool(value) + return tx_los def get_tx_disable_support(self): return not self.is_flat_memory() and self.xcvr_eeprom.read(consts.TX_DISABLE_SUPPORT_FIELD) @@ -272,6 +573,12 @@ def tx_disable_channel(self, channel, disable): return self.xcvr_eeprom.write(consts.TX_DISABLE_FIELD, channel_state) + def get_power_override(self): + return None + + def set_power_override(self, power_override, power_set): + return True + def get_transceiver_thresholds_support(self): return not self.is_flat_memory() @@ -283,3 +590,1078 @@ def get_lpmode_support(self): def get_power_override_support(self): return False + + def get_module_media_type(self): + ''' + This function returns module media type: MMF, SMF, Passive Copper Cable, Active Cable Assembly or Base-T. + ''' + return self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD) + + def get_host_electrical_interface(self): + ''' + This function returns module host electrical interface. Table 4-5 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) + + def get_module_media_interface(self): + ''' + This function returns module media electrical interface. Table 4-6 ~ 4-10 in SFF-8024 Rev4.6 + ''' + media_type = self.get_module_media_type() + if media_type == 'Multimode Fiber (MMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) + elif media_type == 'Single Mode Fiber (SMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) + elif media_type == 'Passive Copper Cable': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) + elif media_type == 'Active Cable Assembly': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) + elif media_type == 'BASE-T': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) + else: + return 'Unknown media interface' + + def is_coherent_module(self): + ''' + Returns True if the module follow C-CMIS spec, False otherwise + ''' + mintf = self.get_module_media_interface() + return False if 'ZR' not in mintf else True + + def get_host_lane_count(self): + ''' + This function returns number of host lanes + ''' + return self.xcvr_eeprom.read(consts.HOST_LANE_COUNT) + + + def get_media_lane_count(self): + ''' + This function returns number of media lanes + ''' + return self.xcvr_eeprom.read(consts.MEDIA_LANE_COUNT) + + def get_media_interface_technology(self): + ''' + This function returns the media lane technology + ''' + return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) + + def get_host_lane_assignment_option(self): + ''' + This function returns the host lane that the application begins on + ''' + return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) + + def get_media_lane_assignment_option(self): + ''' + This function returns the media lane that the application is allowed to begin on + ''' + return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) + + def get_active_apsel_hostlane(self): + ''' + This function returns the application select code that each host lane has + ''' + return self.xcvr_eeprom.read(consts.ACTIVE_APSEL_CODE) + + def get_tx_config_power(self): + ''' + This function returns the configured TX output power. Unit in dBm + ''' + return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) + + def get_media_output_loopback(self): + ''' + This function returns the media output loopback status + ''' + result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) + if result is None: + return None + return result == 1 + + def get_media_input_loopback(self): + ''' + This function returns the media input loopback status + ''' + result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) + if result is None: + return None + return result == 1 + + def get_host_output_loopback(self): + ''' + This function returns the host output loopback status + ''' + result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) + if result is None: + return None + loopback_status = [] + for bitpos in range(self.NUM_CHANNELS): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_host_input_loopback(self): + ''' + This function returns the host input loopback status + ''' + result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) + if result is None: + return None + loopback_status = [] + for bitpos in range(self.NUM_CHANNELS): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_aux_mon_type(self): + ''' + This function returns the aux monitor types + ''' + result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) + if result is None: + return None + aux1_mon_type = result & 0x1 + aux2_mon_type = (result >> 1) & 0x1 + aux3_mon_type = (result >> 2) & 0x1 + return aux1_mon_type, aux2_mon_type, aux3_mon_type + + def get_laser_temperature(self): + ''' + This function returns the laser temperature monitor value + ''' + try: + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + except TypeError: + return None + LASER_TEMP_SCALE = 256.0 + if aux2_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEMP_SCALE + elif aux2_mon_type == 1 and aux3_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX3_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX3_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX3_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX3_LOW_WARN)/LASER_TEMP_SCALE + else: + return None + laser_temp_dict = {'monitor value': laser_temp, + 'high alarm': laser_temp_high_alarm, + 'low alarm': laser_temp_low_alarm, + 'high warn': laser_temp_high_warn, + 'low warn': laser_temp_low_warn} + return laser_temp_dict + + def get_laser_TEC_current(self): + ''' + This function returns the laser TEC current monitor value + ''' + try: + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + except TypeError: + return None + LASER_TEC_CURRENT_SCALE = 32767.0 + if aux1_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX1_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX1_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX1_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX1_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX1_LOW_WARN)/LASER_TEC_CURRENT_SCALE + elif aux1_mon_type == 0 and aux2_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEC_CURRENT_SCALE + else: + return None + laser_tec_current_dict = {'monitor value': laser_tec_current, + 'high alarm': laser_tec_current_high_alarm, + 'low alarm': laser_tec_current_low_alarm, + 'high warn': laser_tec_current_high_warn, + 'low warn': laser_tec_current_low_warn} + return laser_tec_current_dict + + def get_config_datapath_hostlane_status(self): + ''' + This function returns configuration command execution + / result status for the datapath of each host lane + ''' + return self.xcvr_eeprom.read(consts.CONFIG_LANE_STATUS) + + def get_datapath_state(self): + ''' + This function returns the eight datapath states + ''' + return self.xcvr_eeprom.read(consts.DATA_PATH_STATE) + + def get_dpinit_pending(self): + ''' + This function returns datapath init pending status. + 0 means datapath init not pending. + 1 means datapath init pending. DPInit not yet executed after successful ApplyDPInit. + Hence the active control set content may deviate from the actual hardware config + ''' + dpinit_pending_dict = self.xcvr_eeprom.read(consts.DPINIT_PENDING) + if dpinit_pending_dict is None: + return None + for key, value in dpinit_pending_dict.items(): + dpinit_pending_dict[key] = bool(value) + return dpinit_pending_dict + + def get_supported_power_config(self): + ''' + This function returns the supported TX power range + ''' + min_prog_tx_output_power = self.xcvr_eeprom.read(consts.MIN_PROG_OUTPUT_POWER) + max_prog_tx_output_power = self.xcvr_eeprom.read(consts.MAX_PROG_OUTPUT_POWER) + return min_prog_tx_output_power, max_prog_tx_output_power + + def reset_module(self, reset = False): + ''' + This function resets the module + Return True if the provision succeeds, False if it fails + Return True if no action. + ''' + if reset: + reset_control = reset << 3 + return self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, reset_control) + else: + return True + + def set_low_power(self, AssertLowPower): + ''' + This function sets the module to low power state. + AssertLowPower being 0 means "set to high power" + AssertLowPower being 1 means "set to low power" + Return True if the provision succeeds, False if it fails + ''' + low_power_control = AssertLowPower << 6 + return self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) + + def get_loopback_capability(self): + ''' + This function returns the module loopback capability as advertised + ''' + allowed_loopback_result = self.xcvr_eeprom.read(consts.LOOPBACK_CAPABILITY) + if allowed_loopback_result is None: + return None + loopback_capability = dict() + loopback_capability['simultaneous_host_media_loopback_supported'] = bool((allowed_loopback_result >> 6) & 0x1) + loopback_capability['per_lane_media_loopback_supported'] = bool((allowed_loopback_result >> 5) & 0x1) + loopback_capability['per_lane_host_loopback_supported'] = bool((allowed_loopback_result >> 4) & 0x1) + loopback_capability['host_side_input_loopback_supported'] = bool((allowed_loopback_result >> 3) & 0x1) + loopback_capability['host_side_output_loopback_supported'] = bool((allowed_loopback_result >> 2) & 0x1) + loopback_capability['media_side_input_loopback_supported'] = bool((allowed_loopback_result >> 1) & 0x1) + loopback_capability['media_side_output_loopback_supported'] = bool((allowed_loopback_result >> 0) & 0x1) + return loopback_capability + + def set_loopback_mode(self, loopback_mode): + ''' + This function sets the module loopback mode. + Loopback mode has to be one of the five: + 1. "none" (default) + 2. "host-side-input" + 3. "host-side-output" + 4. "media-side-input" + 5. "media-side-output" + The function will look at 13h:128 to check advertized loopback capabilities. + Return True if the provision succeeds, False if it fails + ''' + loopback_capability = self.get_loopback_capability() + if loopback_capability is None: + return None + if loopback_mode == 'none': + status_host_input = self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0) + status_host_output = self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0) + status_media_input = self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0) + status_media_output = self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0) + return all([status_host_input, status_host_output, status_media_input, status_media_output]) + elif loopback_mode == 'host-side-input': + assert loopback_capability['host_side_input_loopback_supported'] + return self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0xff) + elif loopback_mode == 'host-side-output': + assert loopback_capability['host_side_output_loopback_supported'] + return self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) + elif loopback_mode == 'media-side-input': + assert loopback_capability['media_side_input_loopback_supported'] + return self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0xff) + elif loopback_mode == 'media-side-output': + assert loopback_capability['media_side_output_loopback_supported'] + return self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0xff) + else: + return 'N/A' + + + def get_cdb_api(self): + self.cdb = CmisCdbApi(self.xcvr_eeprom) + return self.cdb + + def get_vdm_api(self): + self.vdm = CmisVdmApi(self.xcvr_eeprom) + return self.vdm + + def get_vdm(self): + ''' + This function returns all the VDM items, including real time monitor value, threholds and flags + ''' + try: + self.vdm + except AttributeError: + self.get_vdm_api() + vdm = self.vdm.get_vdm_allpage() + return vdm + + def get_module_firmware_fault_state_changed(self): + ''' + This function returns datapath firmware fault state, module firmware fault state + and whether module state changed + ''' + result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) + if result is None: + return None + datapath_firmware_fault = bool((result >> 2) & 0x1) + module_firmware_fault = bool((result >> 1) & 0x1) + module_state_changed = bool(result & 0x1) + return datapath_firmware_fault, module_firmware_fault, module_state_changed + + def get_module_level_flag(self): + ''' + This function returns teh module level flags, including + - 3.3 V voltage supply flags + - Case temperature flags + - Aux 1 flags + - Aux 2 flags + - Aux 3 flags + - Custom field flags + ''' + module_flag_byte1 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE1) + module_flag_byte2 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE2) + module_flag_byte3 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE3) + if module_flag_byte1 is None or module_flag_byte2 is None or module_flag_byte3 is None: + return None + voltage_high_alarm_flag = bool((module_flag_byte1 >> 4) & 0x1) + voltage_low_alarm_flag = bool((module_flag_byte1 >> 5) & 0x1) + voltage_high_warn_flag = bool((module_flag_byte1 >> 6) & 0x1) + voltage_low_warn_flag = bool((module_flag_byte1 >> 7) & 0x1) + voltage_flags = {'voltage_high_alarm_flag': voltage_high_alarm_flag, + 'voltage_low_alarm_flag': voltage_low_alarm_flag, + 'voltage_high_warn_flag': voltage_high_warn_flag, + 'voltage_low_warn_flag': voltage_low_warn_flag} + + case_temp_high_alarm_flag = bool((module_flag_byte1 >> 0) & 0x1) + case_temp_low_alarm_flag = bool((module_flag_byte1 >> 1) & 0x1) + case_temp_high_warn_flag = bool((module_flag_byte1 >> 2) & 0x1) + case_temp_low_warn_flag = bool((module_flag_byte1 >> 3) & 0x1) + case_temp_flags = {'case_temp_high_alarm_flag': case_temp_high_alarm_flag, + 'case_temp_low_alarm_flag': case_temp_low_alarm_flag, + 'case_temp_high_warn_flag': case_temp_high_warn_flag, + 'case_temp_low_warn_flag': case_temp_low_warn_flag} + + aux2_high_alarm_flag = bool((module_flag_byte2 >> 4) & 0x1) + aux2_low_alarm_flag = bool((module_flag_byte2 >> 5) & 0x1) + aux2_high_warn_flag = bool((module_flag_byte2 >> 6) & 0x1) + aux2_low_warn_flag = bool((module_flag_byte2 >> 7) & 0x1) + aux2_flags = {'aux2_high_alarm_flag': aux2_high_alarm_flag, + 'aux2_low_alarm_flag': aux2_low_alarm_flag, + 'aux2_high_warn_flag': aux2_high_warn_flag, + 'aux2_low_warn_flag': aux2_low_warn_flag} + + aux1_high_alarm_flag = bool((module_flag_byte2 >> 0) & 0x1) + aux1_low_alarm_flag = bool((module_flag_byte2 >> 1) & 0x1) + aux1_high_warn_flag = bool((module_flag_byte2 >> 2) & 0x1) + aux1_low_warn_flag = bool((module_flag_byte2 >> 3) & 0x1) + aux1_flags = {'aux1_high_alarm_flag': aux1_high_alarm_flag, + 'aux1_low_alarm_flag': aux1_low_alarm_flag, + 'aux1_high_warn_flag': aux1_high_warn_flag, + 'aux1_low_warn_flag': aux1_low_warn_flag} + + custom_mon_high_alarm_flag = bool((module_flag_byte3 >> 4) & 0x1) + custom_mon_low_alarm_flag = bool((module_flag_byte3 >> 5) & 0x1) + custom_mon_high_warn_flag = bool((module_flag_byte3 >> 6) & 0x1) + custom_mon_low_warn_flag = bool((module_flag_byte3 >> 7) & 0x1) + custom_mon_flags = {'custom_mon_high_alarm_flag': custom_mon_high_alarm_flag, + 'custom_mon_low_alarm_flag': custom_mon_low_alarm_flag, + 'custom_mon_high_warn_flag': custom_mon_high_warn_flag, + 'custom_mon_low_warn_flag': custom_mon_low_warn_flag} + + aux3_high_alarm_flag = bool((module_flag_byte3 >> 0) & 0x1) + aux3_low_alarm_flag = bool((module_flag_byte3 >> 1) & 0x1) + aux3_high_warn_flag = bool((module_flag_byte3 >> 2) & 0x1) + aux3_low_warn_flag = bool((module_flag_byte3 >> 3) & 0x1) + aux3_flags = {'aux3_high_alarm_flag': aux3_high_alarm_flag, + 'aux3_low_alarm_flag': aux3_low_alarm_flag, + 'aux3_high_warn_flag': aux3_high_warn_flag, + 'aux3_low_warn_flag': aux3_low_warn_flag} + + module_flag = {'voltage_flags': voltage_flags, + 'case_temp_flags': case_temp_flags, + 'aux1_flags': aux1_flags, + 'aux2_flags': aux2_flags, + 'aux3_flags': aux3_flags, + 'custom_mon_flags': custom_mon_flags} + return module_flag + + def get_module_fw_upgrade_feature(self, verbose = False): + """ + This function obtains CDB features supported by the module from CDB command 0041h, + such as start header size, maximum block size, whether extended payload messaging + (page 0xA0 - 0xAF) or only local payload is supported. These features are important because + the following upgrade with depend on these parameters. + """ + try: + self.cdb + except AttributeError: + self.get_cdb_api() + txt = '' + # get fw upgrade features (CMD 0041h) + starttime = time.time() + autopaging = self.xcvr_eeprom.read(consts.AUTO_PAGING_SUPPORT) + autopaging_flag = bool(autopaging) + writelength_raw = self.xcvr_eeprom.read(consts.CDB_SEQ_WRITE_LENGTH_EXT) + if writelength_raw is None: + return None + writelength = (writelength_raw + 1) * 8 + txt += 'Auto page support: %s\n' %autopaging_flag + txt += 'Max write length: %d\n' %writelength + rpllen, rpl_chkcode, rpl = self.cdb.get_fw_management_features() + if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: + startLPLsize = rpl[2] + txt += 'Start payload size %d\n' % startLPLsize + maxblocksize = (rpl[4] + 1) * 8 + txt += 'Max block size %d\n' % maxblocksize + lplEplSupport = {0x00 : 'No write to LPL/EPL supported', + 0x01 : 'Write to LPL supported', + 0x10 : 'Write to EPL supported', + 0x11 : 'Write to LPL/EPL supported'} + txt += '{}\n'.format(lplEplSupport[rpl[5]]) + if rpl[5] == 1: + lplonly_flag = True + else: + lplonly_flag = False + txt += 'Abort CMD102h supported %s\n' %bool(rpl[1] & 0x01) + if verbose: + txt += 'Copy CMD108h supported %s\n' %bool((rpl[1] >> 1) & 0x01) + txt += 'Skipping erased blocks supported %s\n' %bool((rpl[1] >> 2) & 0x01) + txt += 'Full image readback supported %s\n' %bool((rpl[1] >> 7) & 0x01) + txt += 'Default erase byte {:#x}\n'.format(rpl[3]) + txt += 'Read to LPL/EPL {:#x}\n'.format(rpl[6]) + + else: + txt += 'Reply payload check code error\n' + return {'status': False, 'info': txt, 'result': None} + elapsedtime = time.time()-starttime + txt += 'Get module FW upgrade features time: %.2f s\n' %elapsedtime + logger.info(txt) + return {'status': True, 'info': txt, 'result': (startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength)} + + def get_module_fw_info(self): + """ + This function returns firmware Image A and B version, running version, committed version + and whether both firmware images are valid. + Operational Status: 1 = running, 0 = not running + Administrative Status: 1=committed, 0=uncommitted + Validity Status: 1 = invalid, 0 = valid + """ + try: + self.cdb + except AttributeError: + self.get_cdb_api() + txt = '' + # get fw info (CMD 0100h) + starttime = time.time() + txt += 'Get module FW info\n' + rpllen, rpl_chkcode, rpl = self.cdb.get_fw_info() + # password issue + if self.cdb.cdb_chkcode(rpl) != rpl_chkcode: + string = 'Get module FW info: Need to enter password\n' + logger.info(string) + # Reset password for module using CMIS 4.0 + self.cdb.module_enter_password(0) + rpllen, rpl_chkcode, rpl = self.cdb.get_fw_info() + + if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: + # Regiter 9Fh:136 + fwStatus = rpl[0] + ImageARunning = (fwStatus & 0x01) # bit 0 - image A is running + ImageACommitted = ((fwStatus >> 1) & 0x01) # bit 1 - image A is committed + ImageAValid = ((fwStatus >> 2) & 0x01) # bit 2 - image A is valid + ImageBRunning = ((fwStatus >> 4) & 0x01) # bit 4 - image B is running + ImageBCommitted = ((fwStatus >> 5) & 0x01) # bit 5 - image B is committed + ImageBValid = ((fwStatus >> 6) & 0x01) # bit 6 - image B is valid + + if ImageAValid == 0: + # Registers 9Fh:138,139; 140,141 + ImageA = '%d.%d.%d' %(rpl[2], rpl[3], ((rpl[4]<< 8) | rpl[5])) + else: + ImageA = "N/A" + txt += 'Image A Version: %s\n' %ImageA + + if ImageBValid == 0: + # Registers 9Fh:174,175; 176.177 + ImageB = '%d.%d.%d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41])) + else: + ImageB = "N/A" + txt += 'Image B Version: %s\n' %ImageB + + if ImageARunning == 1: + RunningImage = 'A' + elif ImageBRunning == 1: + RunningImage = 'B' + else: + RunningImage = 'N/A' + if ImageACommitted == 1: + CommittedImage = 'A' + elif ImageBCommitted == 1: + CommittedImage = 'B' + else: + CommittedImage = 'N/A' + txt += 'Running Image: %s; Committed Image: %s\n' %(RunningImage, CommittedImage) + else: + txt += 'Reply payload check code error\n' + return {'status': False, 'info': txt, 'result': None} + elapsedtime = time.time()-starttime + txt += 'Get module FW info time: %.2f s\n' %elapsedtime + logger.info(txt) + return {'status': True, 'info': txt, 'result': (ImageA, ImageARunning, ImageACommitted, ImageAValid, ImageB, ImageBRunning, ImageBCommitted, ImageBValid)} + + def module_fw_run(self, mode = 0x01): + """ + This command is used to start and run a selected image. + This command transfers control from the currently + running firmware to a selected firmware that is started. It + can be used to switch between firmware versions, or to + perform a restart of the currently running firmware. + mode: + 00h = Traffic affecting Reset to Inactive Image. + 01h = Attempt Hitless Reset to Inactive Image + 02h = Traffic affecting Reset to Running Image. + 03h = Attempt Hitless Reset to Running Image + + This function returns True if firmware run successfully completes. + Otherwise it will return False. + """ + try: + self.cdb + except AttributeError: + self.get_cdb_api() + # run module FW (CMD 0109h) + txt = '' + starttime = time.time() + fw_run_status = self.cdb.run_fw_image(mode) + if fw_run_status == 1: + txt += 'Module FW run: Success\n' + # password issue + elif fw_run_status == 70: + string = 'Module FW run: Need to enter password\n' + logger.info(string) + self.cdb.module_enter_password() + fw_run_status = self.cdb.run_fw_image(mode) + txt += 'FW_run_status %d\n' %fw_run_status + else: + # self.cdb.abort_fw_download() + txt += 'Module FW run: Fail\n' + txt += 'FW_run_status %d\n' %fw_run_status + return False, txt + elapsedtime = time.time()-starttime + txt += 'Module FW run time: %.2f s\n' %elapsedtime + logger.info(txt) + return True, txt + + def module_fw_commit(self): + """ + The host uses this command to commit the running image + so that the module will boot from it on future boots. + + This function returns True if firmware commit successfully completes. + Otherwise it will return False. + """ + try: + self.cdb + except AttributeError: + self.get_cdb_api() + txt = '' + # commit module FW (CMD 010Ah) + starttime = time.time() + fw_commit_status= self.cdb.commit_fw_image() + if fw_commit_status == 1: + txt += 'Module FW commit: Success\n' + # password issue + elif fw_commit_status == 70: + string = 'Module FW commit: Need to enter password\n' + logger.info(string) + self.cdb.module_enter_password() + fw_commit_status = self.cdb.commit_fw_image() + txt += 'FW_commit_status %d\n' %fw_commit_status + else: + # self.cdb.abort_fw_download() + txt += 'Module FW commit: Fail\n' + txt += 'FW_commit_status %d\n' %fw_commit_status + return False, txt + elapsedtime = time.time()-starttime + txt += 'Module FW commit time: %.2f s\n' %elapsedtime + logger.info(txt) + return True, txt + + def module_fw_download(self, startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath): + """ + This function performs the download of a firmware image to module eeprom + It starts CDB download by writing the header of start header size + from the designated firmware file to the local payload page 0x9F, with CDB command 0101h. + + Then it repeatedly reads from the given firmware file and write to the payload + space advertised from the first step. We use CDB command 0103h to write to the local payload; + we use CDB command 0104h to write to the extended paylaod. This step repeats until it reaches + end of the firmware file, or the CDB status failed. + + The last step is to complete the firmware upgrade with CDB command 0107h. + + Note that if the download process fails anywhere in the middle, we need to run CDB command 0102h + to abort the upgrade before we restart another upgrade process. + + This function returns True if download successfully completes. Otherwise it will return False where it fails. + """ + try: + self.cdb + except AttributeError: + self.get_cdb_api() + txt = '' + # start fw download (CMD 0101h) + starttime = time.time() + try: + f = open(imagepath, 'rb') + except FileNotFoundError: + txt += 'Image path %s is incorrect.\n' % imagepath + logger.info(txt) + return False, txt + + f.seek(0, 2) + imagesize = f.tell() + f.seek(0, 0) + startdata = f.read(startLPLsize) + logger.info('\nStart FW downloading') + logger.info("startLPLsize is %d" %startLPLsize) + fw_start_status = self.cdb.start_fw_download(startLPLsize, bytearray(startdata), imagesize) + if fw_start_status == 1: + string = 'Start module FW download: Success\n' + logger.info(string) + # password error + elif fw_start_status == 70: + string = 'Start module FW download: Need to enter password\n' + logger.info(string) + self.cdb.module_enter_password() + self.cdb.start_fw_download(startLPLsize, bytearray(startdata), imagesize) + else: + string = 'Start module FW download: Fail\n' + txt += string + self.cdb.abort_fw_download() + txt += 'FW_start_status %d\n' %fw_start_status + logger.info(txt) + return False, txt + elapsedtime = time.time()-starttime + logger.info('Start module FW download time: %.2f s' %elapsedtime) + + # start periodically writing (CMD 0103h or 0104h) + # assert maxblocksize == 2048 or lplonly_flag + if lplonly_flag: + BLOCK_SIZE = 116 + else: + BLOCK_SIZE = maxblocksize + address = 0 + remaining = imagesize - startLPLsize + logger.info("\nTotal size: {} start bytes: {} remaining: {}".format(imagesize, startLPLsize, remaining)) + while remaining > 0: + if remaining < BLOCK_SIZE: + count = remaining + else: + count = BLOCK_SIZE + data = f.read(count) + progress = (imagesize - remaining) * 100.0 / imagesize + if lplonly_flag: + fw_download_status = self.cdb.block_write_lpl(address, data) + else: + fw_download_status = self.cdb.block_write_epl(address, data, autopaging_flag, writelength) + if fw_download_status != 1: + self.cdb.abort_fw_download() + txt += 'CDB download failed. CDB Status: %d\n' %fw_download_status + txt += 'FW_download_status %d\n' %fw_download_status + logger.info(txt) + return False, txt + elapsedtime = time.time()-starttime + logger.info('Address: {:#08x}; Count: {}; Progress: {:.2f}%; Time: {:.2f}s'.format(address, count, progress, elapsedtime)) + address += count + remaining -= count + elapsedtime = time.time()-starttime + logger.info('Total module FW download time: %.2f s' %elapsedtime) + + time.sleep(2) + # complete FW download (CMD 0107h) + fw_complete_status = self.cdb.validate_fw_image() + if fw_complete_status == 1: + logger.info('Module FW download complete: Success') + else: + txt += 'Module FW download complete: Fail\n' + txt += 'FW_complete_status %d\n' %fw_complete_status + logger.info(txt) + return False, txt + elapsedtime = time.time()-elapsedtime-starttime + logger.info('Complete module FW download time: %.2f s\n' %elapsedtime) + return True, txt + + def module_fw_upgrade(self, imagepath): + """ + This function performs firmware upgrade. + 1. show FW version in the beginning + 2. check module advertised FW download capability + 3. configure download + 4. show download progress + 5. configure run downloaded firmware + 6. configure commit downloaded firmware + 7. show FW version in the end + + imagepath specifies where firmware image file is located. + target_firmware is a string that specifies the firmware version to upgrade to + + This function returns True if download successfully completes. + Otherwise it will return False. + """ + result = self.get_module_fw_info() + try: + _, _, _, _, _, _, _, _ = result['result'] + except (ValueError, TypeError): + return result['status'], result['info'] + result = self.get_module_fw_upgrade_feature() + try: + startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = result['result'] + except (ValueError, TypeError): + return result['status'], result['info'] + download_status, txt = self.module_fw_download(startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath) + if not download_status: + return False, txt + switch_status, switch_txt = self.module_fw_switch() + status = download_status and switch_status + txt += switch_txt + return status, txt + + def module_fw_switch(self): + """ + This function switch the active/inactive module firmware in the current module memory + This function returns True if firmware switch successfully completes. + Otherwise it will return False. + If not both images are valid, it will stop firmware switch and return False + """ + txt = '' + result = self.get_module_fw_info() + try: + (ImageA_init, ImageARunning_init, ImageACommitted_init, ImageAValid_init, + ImageB_init, ImageBRunning_init, ImageBCommitted_init, ImageBValid_init) = result['result'] + except (ValueError, TypeError): + return result['status'], result['info'] + if ImageAValid_init == 0 and ImageBValid_init == 0: + self.module_fw_run(mode = 0x01) + time.sleep(60) + self.module_fw_commit() + (ImageA, ImageARunning, ImageACommitted, ImageAValid, + ImageB, ImageBRunning, ImageBCommitted, ImageBValid) = self.get_module_fw_info()['result'] + # detect if image switch happened + txt += 'Before switch Image A: %s; Run: %d Commit: %d, Valid: %d\n' %( + ImageA_init, ImageARunning_init, ImageACommitted_init, ImageAValid_init + ) + txt += 'Befpre switch Image B: %s; Run: %d Commit: %d, Valid: %d\n' %( + ImageB_init, ImageBRunning_init, ImageBCommitted_init, ImageBValid_init + ) + txt += 'Image A: %s; Run: %d Commit: %d, Valid: %d\n' %(ImageA, ImageARunning, ImageACommitted, ImageAValid) + txt += 'Image B: %s; Run: %d Commit: %d, Valid: %d\n' %(ImageB, ImageBRunning, ImageBCommitted, ImageBValid) + if (ImageARunning_init == 1 and ImageARunning == 1) or (ImageBRunning_init == 1 and ImageBRunning == 1): + txt += 'Switch did not happen.\n' + logger.info(txt) + return False, txt + else: + logger.info(txt) + return True, txt + else: + txt += 'Not both images are valid.' + logger.info(txt) + return False, txt + + def get_transceiver_status(self): + """ + Retrieves transceiver status of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_STATUS|ifname ; Error information for module on port + ; field = value + status = 1*255VCHAR ; code of the module status (plug in, plug out) + error = 1*255VCHAR ; module error (N/A or a string consisting of error descriptions joined by "|", like "error1 | error2" ) + module_state = 1*255VCHAR ; current module state (ModuleLowPwr, ModulePwrUp, ModuleReady, ModulePwrDn, Fault) + module_fault_cause = 1*255VCHAR ; reason of entering the module fault state + datapath_firmware_fault = BOOLEAN ; datapath (DSP) firmware fault + module_firmware_fault = BOOLEAN ; module firmware fault + module_state_changed = BOOLEAN ; module state changed + datapath_hostlane1 = 1*255VCHAR ; data path state indicator on host lane 1 + datapath_hostlane2 = 1*255VCHAR ; data path state indicator on host lane 2 + datapath_hostlane3 = 1*255VCHAR ; data path state indicator on host lane 3 + datapath_hostlane4 = 1*255VCHAR ; data path state indicator on host lane 4 + datapath_hostlane5 = 1*255VCHAR ; data path state indicator on host lane 5 + datapath_hostlane6 = 1*255VCHAR ; data path state indicator on host lane 6 + datapath_hostlane7 = 1*255VCHAR ; data path state indicator on host lane 7 + datapath_hostlane8 = 1*255VCHAR ; data path state indicator on host lane 8 + txoutput_status = BOOLEAN ; tx output status on media lane + rxoutput_status_hostlane1 = BOOLEAN ; rx output status on host lane 1 + rxoutput_status_hostlane2 = BOOLEAN ; rx output status on host lane 2 + rxoutput_status_hostlane3 = BOOLEAN ; rx output status on host lane 3 + rxoutput_status_hostlane4 = BOOLEAN ; rx output status on host lane 4 + rxoutput_status_hostlane5 = BOOLEAN ; rx output status on host lane 5 + rxoutput_status_hostlane6 = BOOLEAN ; rx output status on host lane 6 + rxoutput_status_hostlane7 = BOOLEAN ; rx output status on host lane 7 + rxoutput_status_hostlane8 = BOOLEAN ; rx output status on host lane 8 + txfault = BOOLEAN ; tx fault flag on media lane + txlos_hostlane1 = BOOLEAN ; tx loss of signal flag on host lane 1 + txlos_hostlane2 = BOOLEAN ; tx loss of signal flag on host lane 2 + txlos_hostlane3 = BOOLEAN ; tx loss of signal flag on host lane 3 + txlos_hostlane4 = BOOLEAN ; tx loss of signal flag on host lane 4 + txlos_hostlane5 = BOOLEAN ; tx loss of signal flag on host lane 5 + txlos_hostlane6 = BOOLEAN ; tx loss of signal flag on host lane 6 + txlos_hostlane7 = BOOLEAN ; tx loss of signal flag on host lane 7 + txlos_hostlane8 = BOOLEAN ; tx loss of signal flag on host lane 8 + txcdrlol_hostlane1 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 1 + txcdrlol_hostlane2 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 2 + txcdrlol_hostlane3 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 3 + txcdrlol_hostlane4 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 4 + txcdrlol_hostlane5 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 5 + txcdrlol_hostlane6 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 6 + txcdrlol_hostlane7 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 7 + txcdrlol_hostlane8 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 8 + rxlos = BOOLEAN ; rx loss of signal flag on media lane + rxcdrlol = BOOLEAN ; rx clock and data recovery loss of lock on media lane + config_state_hostlane1 = 1*255VCHAR ; configuration status for the data path of host line 1 + config_state_hostlane2 = 1*255VCHAR ; configuration status for the data path of host line 2 + config_state_hostlane3 = 1*255VCHAR ; configuration status for the data path of host line 3 + config_state_hostlane4 = 1*255VCHAR ; configuration status for the data path of host line 4 + config_state_hostlane5 = 1*255VCHAR ; configuration status for the data path of host line 5 + config_state_hostlane6 = 1*255VCHAR ; configuration status for the data path of host line 6 + config_state_hostlane7 = 1*255VCHAR ; configuration status for the data path of host line 7 + config_state_hostlane8 = 1*255VCHAR ; configuration status for the data path of host line 8 + dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 + dpinit_pending_hostlane2 = BOOLEAN ; data path configuration updated on host lane 2 + dpinit_pending_hostlane3 = BOOLEAN ; data path configuration updated on host lane 3 + dpinit_pending_hostlane4 = BOOLEAN ; data path configuration updated on host lane 4 + dpinit_pending_hostlane5 = BOOLEAN ; data path configuration updated on host lane 5 + dpinit_pending_hostlane6 = BOOLEAN ; data path configuration updated on host lane 6 + dpinit_pending_hostlane7 = BOOLEAN ; data path configuration updated on host lane 7 + dpinit_pending_hostlane8 = BOOLEAN ; data path configuration updated on host lane 8 + temphighalarm_flag = BOOLEAN ; temperature high alarm flag + temphighwarning_flag = BOOLEAN ; temperature high warning flag + templowalarm_flag = BOOLEAN ; temperature low alarm flag + templowwarning_flag = BOOLEAN ; temperature low warning flag + vcchighalarm_flag = BOOLEAN ; vcc high alarm flag + vcchighwarning_flag = BOOLEAN ; vcc high warning flag + vcclowalarm_flag = BOOLEAN ; vcc low alarm flag + vcclowwarning_flag = BOOLEAN ; vcc low warning flag + txpowerhighalarm_flag = BOOLEAN ; tx power high alarm flag + txpowerlowalarm_flag = BOOLEAN ; tx power low alarm flag + txpowerhighwarning_flag = BOOLEAN ; tx power high warning flag + txpowerlowwarning_flag = BOOLEAN ; tx power low alarm flag + rxpowerhighalarm_flag = BOOLEAN ; rx power high alarm flag + rxpowerlowalarm_flag = BOOLEAN ; rx power low alarm flag + rxpowerhighwarning_flag = BOOLEAN ; rx power high warning flag + rxpowerlowwarning_flag = BOOLEAN ; rx power low warning flag + txbiashighalarm_flag = BOOLEAN ; tx bias high alarm flag + txbiaslowalarm_flag = BOOLEAN ; tx bias low alarm flag + txbiashighwarning_flag = BOOLEAN ; tx bias high warning flag + txbiaslowwarning_flag = BOOLEAN ; tx bias low warning flag + lasertemphighalarm_flag = BOOLEAN ; laser temperature high alarm flag + lasertemplowalarm_flag = BOOLEAN ; laser temperature low alarm flag + lasertemphighwarning_flag = BOOLEAN ; laser temperature high warning flag + lasertemplowwarning_flag = BOOLEAN ; laser temperature low warning flag + prefecberhighalarm_flag = BOOLEAN ; prefec ber high alarm flag + prefecberlowalarm_flag = BOOLEAN ; prefec ber low alarm flag + prefecberhighwarning_flag = BOOLEAN ; prefec ber high warning flag + prefecberlowwarning_flag = BOOLEAN ; prefec ber low warning flag + postfecberhighalarm_flag = BOOLEAN ; postfec ber high alarm flag + postfecberlowalarm_flag = BOOLEAN ; postfec ber low alarm flag + postfecberhighwarning_flag = BOOLEAN ; postfec ber high warning flag + postfecberlowwarning_flag = BOOLEAN ; postfec ber low warning flag + ================================================================================ + """ + trans_status = dict() + trans_status['module_state'] = self.get_module_state() + trans_status['module_fault_cause'] = self.get_module_fault_cause() + try: + dp_fw_fault, module_fw_fault, module_state_changed = self.get_module_firmware_fault_state_changed() + trans_status['datapath_firmware_fault'] = dp_fw_fault + trans_status['module_firmware_fault'] = module_fw_fault + trans_status['module_state_changed'] = module_state_changed + except TypeError: + pass + dp_state_dict = self.get_datapath_state() + trans_status['DP1State'] = dp_state_dict['DP1State'] + trans_status['DP2State'] = dp_state_dict['DP2State'] + trans_status['DP3State'] = dp_state_dict['DP3State'] + trans_status['DP4State'] = dp_state_dict['DP4State'] + trans_status['DP5State'] = dp_state_dict['DP5State'] + trans_status['DP6State'] = dp_state_dict['DP6State'] + trans_status['DP7State'] = dp_state_dict['DP7State'] + trans_status['DP8State'] = dp_state_dict['DP8State'] + tx_output_status_dict = self.get_tx_output_status() + trans_status['txoutput_status'] = tx_output_status_dict['TxOutputStatus1'] + rx_output_status_dict = self.get_rx_output_status() + trans_status['rxoutput_status_hostlane1'] = rx_output_status_dict['RxOutputStatus1'] + trans_status['rxoutput_status_hostlane2'] = rx_output_status_dict['RxOutputStatus2'] + trans_status['rxoutput_status_hostlane3'] = rx_output_status_dict['RxOutputStatus3'] + trans_status['rxoutput_status_hostlane4'] = rx_output_status_dict['RxOutputStatus4'] + trans_status['rxoutput_status_hostlane5'] = rx_output_status_dict['RxOutputStatus5'] + trans_status['rxoutput_status_hostlane6'] = rx_output_status_dict['RxOutputStatus6'] + trans_status['rxoutput_status_hostlane7'] = rx_output_status_dict['RxOutputStatus7'] + trans_status['rxoutput_status_hostlane8'] = rx_output_status_dict['RxOutputStatus8'] + tx_fault_dict = self.get_tx_fault() + trans_status['txfault'] = tx_fault_dict['TxFault1'] + tx_los_dict = self.get_tx_los() + trans_status['txlos_hostlane1'] = tx_los_dict['TxLOS1'] + trans_status['txlos_hostlane2'] = tx_los_dict['TxLOS2'] + trans_status['txlos_hostlane3'] = tx_los_dict['TxLOS3'] + trans_status['txlos_hostlane4'] = tx_los_dict['TxLOS4'] + trans_status['txlos_hostlane5'] = tx_los_dict['TxLOS5'] + trans_status['txlos_hostlane6'] = tx_los_dict['TxLOS6'] + trans_status['txlos_hostlane7'] = tx_los_dict['TxLOS7'] + trans_status['txlos_hostlane8'] = tx_los_dict['TxLOS8'] + tx_lol_dict = self.get_tx_cdr_lol() + trans_status['txcdrlol_hostlane1'] = tx_lol_dict['TxCDRLOL1'] + trans_status['txcdrlol_hostlane2'] = tx_lol_dict['TxCDRLOL2'] + trans_status['txcdrlol_hostlane3'] = tx_lol_dict['TxCDRLOL3'] + trans_status['txcdrlol_hostlane4'] = tx_lol_dict['TxCDRLOL4'] + trans_status['txcdrlol_hostlane5'] = tx_lol_dict['TxCDRLOL5'] + trans_status['txcdrlol_hostlane6'] = tx_lol_dict['TxCDRLOL6'] + trans_status['txcdrlol_hostlane7'] = tx_lol_dict['TxCDRLOL7'] + trans_status['txcdrlol_hostlane8'] = tx_lol_dict['TxCDRLOL8'] + rx_los_dict = self.get_rx_los() + trans_status['rxlos'] = rx_los_dict['RxLOS1'] + rx_lol_dict = self.get_rx_cdr_lol() + trans_status['rxcdrlol'] = rx_lol_dict['RxCDRLOL1'] + config_status_dict = self.get_config_datapath_hostlane_status() + trans_status['config_state_hostlane1'] = config_status_dict['ConfigStatusLane1'] + trans_status['config_state_hostlane2'] = config_status_dict['ConfigStatusLane2'] + trans_status['config_state_hostlane3'] = config_status_dict['ConfigStatusLane3'] + trans_status['config_state_hostlane4'] = config_status_dict['ConfigStatusLane4'] + trans_status['config_state_hostlane5'] = config_status_dict['ConfigStatusLane5'] + trans_status['config_state_hostlane6'] = config_status_dict['ConfigStatusLane6'] + trans_status['config_state_hostlane7'] = config_status_dict['ConfigStatusLane7'] + trans_status['config_state_hostlane8'] = config_status_dict['ConfigStatusLane8'] + dpinit_pending_dict = self.get_dpinit_pending() + trans_status['dpinit_pending_hostlane1'] = dpinit_pending_dict['DPInitPending1'] + trans_status['dpinit_pending_hostlane2'] = dpinit_pending_dict['DPInitPending2'] + trans_status['dpinit_pending_hostlane3'] = dpinit_pending_dict['DPInitPending3'] + trans_status['dpinit_pending_hostlane4'] = dpinit_pending_dict['DPInitPending4'] + trans_status['dpinit_pending_hostlane5'] = dpinit_pending_dict['DPInitPending5'] + trans_status['dpinit_pending_hostlane6'] = dpinit_pending_dict['DPInitPending6'] + trans_status['dpinit_pending_hostlane7'] = dpinit_pending_dict['DPInitPending7'] + trans_status['dpinit_pending_hostlane8'] = dpinit_pending_dict['DPInitPending8'] + module_flag = self.get_module_level_flag() + trans_status['temphighalarm_flag'] = module_flag['case_temp_flags']['case_temp_high_alarm_flag'] + trans_status['templowalarm_flag'] = module_flag['case_temp_flags']['case_temp_low_alarm_flag'] + trans_status['temphighwarning_flag'] = module_flag['case_temp_flags']['case_temp_high_warn_flag'] + trans_status['templowwarning_flag'] = module_flag['case_temp_flags']['case_temp_low_warn_flag'] + trans_status['vcchighalarm_flag'] = module_flag['voltage_flags']['voltage_high_alarm_flag'] + trans_status['vcclowalarm_flag'] = module_flag['voltage_flags']['voltage_low_alarm_flag'] + trans_status['vcchighwarning_flag'] = module_flag['voltage_flags']['voltage_high_warn_flag'] + trans_status['vcclowwarning_flag'] = module_flag['voltage_flags']['voltage_low_warn_flag'] + try: + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + if aux2_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux2_flags']['aux2_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux2_flags']['aux2_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux2_flags']['aux2_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux2_flags']['aux2_low_warn_flag'] + elif aux2_mon_type == 1 and aux3_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux3_flags']['aux3_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux3_flags']['aux3_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux3_flags']['aux3_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux3_flags']['aux3_low_warn_flag'] + except TypeError: + pass + tx_power_flag_dict = self.get_tx_power_flag() + trans_status['txpowerhighalarm_flag'] = tx_power_flag_dict['tx_power_high_alarm']['TxPowerHighAlarmFlag1'] + trans_status['txpowerlowalarm_flag'] = tx_power_flag_dict['tx_power_low_alarm']['TxPowerLowAlarmFlag1'] + trans_status['txpowerhighwarning_flag'] = tx_power_flag_dict['tx_power_high_warn']['TxPowerHighWarnFlag1'] + trans_status['txpowerlowwarning_flag'] = tx_power_flag_dict['tx_power_low_warn']['TxPowerLowWarnFlag1'] + rx_power_flag_dict = self.get_rx_power_flag() + trans_status['rxpowerhighalarm_flag'] = rx_power_flag_dict['rx_power_high_alarm']['RxPowerHighAlarmFlag1'] + trans_status['rxpowerlowalarm_flag'] = rx_power_flag_dict['rx_power_low_alarm']['RxPowerLowAlarmFlag1'] + trans_status['rxpowerhighwarning_flag'] = rx_power_flag_dict['rx_power_high_warn']['RxPowerHighWarnFlag1'] + trans_status['rxpowerlowwarning_flag'] = rx_power_flag_dict['rx_power_low_warn']['RxPowerLowWarnFlag1'] + tx_bias_flag_dict = self.get_tx_bias_flag() + trans_status['txbiashighalarm_flag'] = tx_bias_flag_dict['tx_bias_high_alarm']['TxBiasHighAlarmFlag1'] + trans_status['txbiaslowalarm_flag'] = tx_bias_flag_dict['tx_bias_low_alarm']['TxBiasLowAlarmFlag1'] + trans_status['txbiashighwarning_flag'] = tx_bias_flag_dict['tx_bias_high_warn']['TxBiasHighWarnFlag1'] + trans_status['txbiaslowwarning_flag'] = tx_bias_flag_dict['tx_bias_low_warn']['TxBiasLowWarnFlag1'] + self.vdm_dict = self.get_vdm() + try: + trans_status['prefecberhighalarm_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][5] + trans_status['prefecberlowalarm_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][6] + trans_status['prefecberhighwarning_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][7] + trans_status['prefecberlowwarning_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][8] + trans_status['postfecberhighalarm_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][5] + trans_status['postfecberlowalarm_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][6] + trans_status['postfecberhighwarning_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][7] + trans_status['postfecberlowwarning_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][8] + except KeyError: + pass + return trans_status + + def get_transceiver_loopback(self): + """ + Retrieves loopback mode for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_PM|ifname ; information of loopback on port + ; field = value + media_output_loopback = BOOLEAN ; media side output loopback enable + media_input_loopback = BOOLEAN ; media side input loopback enable + host_output_loopback_lane1 = BOOLEAN ; host side output loopback enable lane1 + host_output_loopback_lane2 = BOOLEAN ; host side output loopback enable lane2 + host_output_loopback_lane3 = BOOLEAN ; host side output loopback enable lane3 + host_output_loopback_lane4 = BOOLEAN ; host side output loopback enable lane4 + host_output_loopback_lane5 = BOOLEAN ; host side output loopback enable lane5 + host_output_loopback_lane6 = BOOLEAN ; host side output loopback enable lane6 + host_output_loopback_lane7 = BOOLEAN ; host side output loopback enable lane7 + host_output_loopback_lane8 = BOOLEAN ; host side output loopback enable lane8 + host_input_loopback_lane1 = BOOLEAN ; host side input loopback enable lane1 + host_input_loopback_lane2 = BOOLEAN ; host side input loopback enable lane2 + host_input_loopback_lane3 = BOOLEAN ; host side input loopback enable lane3 + host_input_loopback_lane4 = BOOLEAN ; host side input loopback enable lane4 + host_input_loopback_lane5 = BOOLEAN ; host side input loopback enable lane5 + host_input_loopback_lane6 = BOOLEAN ; host side input loopback enable lane6 + host_input_loopback_lane7 = BOOLEAN ; host side input loopback enable lane7 + host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 + ======================================================================== + """ + trans_loopback = dict() + trans_loopback['media_output_loopback'] = self.get_media_output_loopback() + trans_loopback['media_input_loopback'] = self.get_media_input_loopback() + host_output_loopback_status = self.get_host_output_loopback() + trans_loopback['host_output_loopback_lane1'] = host_output_loopback_status[0] + trans_loopback['host_output_loopback_lane2'] = host_output_loopback_status[1] + trans_loopback['host_output_loopback_lane3'] = host_output_loopback_status[2] + trans_loopback['host_output_loopback_lane4'] = host_output_loopback_status[3] + trans_loopback['host_output_loopback_lane5'] = host_output_loopback_status[4] + trans_loopback['host_output_loopback_lane6'] = host_output_loopback_status[5] + trans_loopback['host_output_loopback_lane7'] = host_output_loopback_status[6] + trans_loopback['host_output_loopback_lane8'] = host_output_loopback_status[7] + host_input_loopback_status = self.get_host_input_loopback() + trans_loopback['host_input_loopback_lane1'] = host_input_loopback_status[0] + trans_loopback['host_input_loopback_lane2'] = host_input_loopback_status[1] + trans_loopback['host_input_loopback_lane3'] = host_input_loopback_status[2] + trans_loopback['host_input_loopback_lane4'] = host_input_loopback_status[3] + trans_loopback['host_input_loopback_lane5'] = host_input_loopback_status[4] + trans_loopback['host_input_loopback_lane6'] = host_input_loopback_status[5] + trans_loopback['host_input_loopback_lane7'] = host_input_loopback_status[6] + trans_loopback['host_input_loopback_lane8'] = host_input_loopback_status[7] + return trans_loopback + # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py new file mode 100644 index 000000000000..215bf8ef0450 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -0,0 +1,480 @@ +""" + cmisCDB.py + + Implementation of APIs related to CDB commands +""" +import logging +from ...fields import consts +from ..xcvr_api import XcvrApi +import struct +import time + +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) + +LPLPAGE = 0x9f +CDB_RPL_OFFSET = 136 +CDB_WRITE_MSG_START = 130 +PAGE_LENGTH = 128 +INIT_OFFSET = 128 +CMDLEN = 2 +MAX_WAIT = 100 + + +class CmisCdbApi(XcvrApi): + def __init__(self, xcvr_eeprom): + super(CmisCdbApi, self).__init__(xcvr_eeprom) + self.cdb_instance_supported = self.xcvr_eeprom.read(consts.CDB_SUPPORT) + self.failed_status_dict = self.xcvr_eeprom.mem_map.codes.CDB_FAIL_STATUS + assert self.cdb_instance_supported != 0 + + def cdb1_chkflags(self): + ''' + This function detects if there is datapath or module firmware fault. + If there is no firmware fault, it checks if CDB command completes. + It retruns True if the CDB command is incomplete and returns False if complete + + Bit 7: L-Cdb2CommandComplete Latched Flag to indicate completion of the CDB command + for CDB block 2. Support is advertised in field 01h:163.7-6 + + Bit 6: L-Cdb1CommandComplete Latched Flag to indicate completion of the CDB command + for CDB block 1. Support is advertised in field 01h:163.7-6 + + Bit 5-3: - Reserved + + Bit 2: L-DataPathFirmwareFault Latched Flag to indicate that subordinated firmware in an + auxiliary device for processing transmitted or received + signals (e.g. a DSP) has failed. + + Bit 1: L-ModuleFirmwareFault Latched Flag to indicate that self-supervision of the main + module firmware has detected a failure in the main module + firmware itself. There are several possible causes of the + error such as program memory becoming corrupted and + incomplete firmware loading. + + Bit 0: L-ModuleStateChanged Latched Flag to indicate a Module State Change + ''' + status = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) + datapath_firmware_fault = bool((status >> 2) & 0x1) + module_firmware_fault = bool((status >> 1) & 0x1) + cdb1_command_complete = bool((status >> 6) & 0x1) + assert not datapath_firmware_fault + assert not module_firmware_fault + if cdb1_command_complete: + return False + else: + return True + + def cdb_chkcode(self, cmd): + ''' + This function calculates and returns the checksum of a CDB command + ''' + checksum = 0 + for byte in cmd: + checksum += byte + return 0xff - (checksum & 0xff) + + def cdb1_chkstatus(self): + ''' + This function checks the CDB status. + The format of returned values is busy flag, failed flag and cause + + CDB command status + Bit 7: CdbIsBusy + Bit 6: CdbHasFailed + Bit 5-0: CdBCommandResult + Coarse Status CdbIsBusy CdbHasFailed + IN PROGRESS 1 X (dont care) + SUCCESS 0 0 + FAILED 0 1 + + IN PROGRESS + 00h=Reserved + 01h=Command is captured but not processed + 02h=Command checking is in progress + 03h=Previous CMD was ABORTED by CMD Abort + 04h-1Fh=Reserved + 20h-2Fh=Reserved + 30h-3Fh=Custom + + SUCCESS + 00h=Reserved + 01h=Command completed successfully + 02h=Reserved + 03h=Previous CMD was ABORTED by CMD Abort + 04h-1Fh=Reserved + 20h-2Fh=Reserved + 30h-3Fh=Custom + + FAILED + 00h=Reserved + 01h=CMDCode unknown + 02h=Parameter range error or parameter not supported + 03h=Previous CMD was not ABORTED by CMD Abort + 04h=Command checking time out + 05h=CdbCheckCode Error + 06h=Password related error (command specific meaning) + 07h=Command not compatible with operating status + 08h-0Fh=Reserved for STS command checking error + 10h-1Fh=Reserved + 20h-2Fh=For individual STS command or task error + 30h-3Fh=Custom + ''' + status = self.xcvr_eeprom.read(consts.CDB1_STATUS) + is_busy = bool((status >> 7) & 0x1) + cnt = 0 + while is_busy and cnt < MAX_WAIT: + time.sleep(0.1) + status = self.xcvr_eeprom.read(consts.CDB1_STATUS) + is_busy = bool((status >> 7) & 0x1) + cnt += 1 + return status + + def write_cdb(self, cmd): + ''' + This function writes a CDB command to page 0x9f + ''' + self.xcvr_eeprom.write_raw(LPLPAGE*PAGE_LENGTH+CDB_WRITE_MSG_START, len(cmd)-CMDLEN, cmd[CMDLEN:]) + self.xcvr_eeprom.write_raw(LPLPAGE*PAGE_LENGTH+INIT_OFFSET, CMDLEN, cmd[:CMDLEN]) + + def read_cdb(self): + ''' + This function reads the reply of a CDB command from page 0x9f. + It returns the reply message of a CDB command. + rpllen is the length (number of bytes) of rpl + rpl_chkcode is the check code of rpl and can be calculated by cdb_chkcode() + rpl is the reply message. + ''' + rpllen = self.xcvr_eeprom.read(consts.CDB_RPL_LENGTH) + rpl_chkcode = self.xcvr_eeprom.read(consts.CDB_RPL_CHKCODE) + rpl = self.xcvr_eeprom.read_raw(LPLPAGE*PAGE_LENGTH+CDB_RPL_OFFSET, rpllen) + return rpllen, rpl_chkcode, rpl + + # Query status + def query_cdb_status(self): + ''' + This QUERY Status command may be used to retrieve the password acceptance + status and to perform a test of the CDB interface. + It returns the reply message of this CDB command 0000h. + ''' + cmd = bytearray(b'\x00\x00\x00\x00\x02\x00\x00\x00\x00\x10') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Query CDB status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Query CDB status: Fail- ' + status_txt + else: + txt = 'Query CDB status: Success' + logger.info(txt) + return self.read_cdb() + + # Enter password + def module_enter_password(self, psw = 0x00001011): + ''' + The Enter Password command allows the host to enter a host password + The default host password is 00001011h. CDB command 0001h puts the + password in Page 9Fh, Byte 136-139. + It returns the status of CDB command 0001h + ''' + psw = struct.pack('>L', psw) + cmd = bytearray(b'\x00\x01\x00\x00\x04\x00\x00\x00') + psw + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Enter password status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Enter password status: Fail- ' + status_txt + else: + txt = 'Enter password status: Success' + logger.info(txt) + return status + + def get_module_feature(self): + ''' + This command is used to query which CDB commands are supported. + It returns the reply message of this CDB command 0040h. + ''' + cmd = bytearray(b'\x00\x40\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Get module feature status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Get module feature status: Fail- ' + status_txt + else: + txt = 'Get module feature status: Success' + logger.info(txt) + return self.read_cdb() + + # Firmware Update Features Supported + def get_fw_management_features(self): + ''' + This command is used to query supported firmware update features + It returns the reply message of this CDB command 0041h. + ''' + cmd = bytearray(b'\x00\x41\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Get firmware management feature status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Get firmware management feature status: Fail- ' + status_txt + else: + txt = 'Get firmware management feature status: Success' + logger.info(txt) + return self.read_cdb() + + # Get FW info + def get_fw_info(self): + ''' + This command returns the firmware versions and firmware default running + images that reside in the module + It returns the reply message of this CDB command 0100h. + ''' + # self.module_enter_password(0x00000000) + cmd = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Get firmware info status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Get firmware info status: Fail- ' + status_txt + else: + txt = 'Get firmware info status: Success' + logger.info(txt) + return self.read_cdb() + + # Start FW download + def start_fw_download(self, startLPLsize, header, imagesize): + ''' + This command starts the firmware download + It returns the status of CDB command 0101h + ''' + # pwd_status = self.module_enter_password() + # logger.info('Module password enter status is %d' %pwd_status) + logger.info("Image size is {}".format(imagesize)) + cmd = bytearray(b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + cmd[132-INIT_OFFSET] = startLPLsize + 8 + cmd[136-INIT_OFFSET] = (imagesize >> 24) & 0xff + cmd[137-INIT_OFFSET] = (imagesize >> 16) & 0xff + cmd[138-INIT_OFFSET] = (imagesize >> 8) & 0xff + cmd[139-INIT_OFFSET] = (imagesize >> 0) & 0xff + cmd += header + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Start firmware download status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Start firmware download status: Fail- ' + status_txt + else: + txt = 'Start firmware download status: Success' + logger.info(txt) + return status + + # Abort FW download + def abort_fw_download(self): + ''' + This command aborts the firmware download + It returns the status of CDB command 0102h + ''' + # pwd_status = self.module_enter_password() + # logger.info('Module password enter status is %d' %pwd_status) + cmd = bytearray(b'\x01\x02\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Abort firmware download status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Abort firmware download status: Fail- ' + status_txt + else: + txt = 'Abort firmware download status: Success' + logger.info(txt) + return status + + # Download FW with LPL + def block_write_lpl(self, addr, data): + ''' + This command writes one block of the firmware image into the LPL + It returns the status of CDB command 0103h + ''' + # lpl_len includes 136-139, four bytes, data is 116-byte long. + lpl_len = len(data) + 4 + cmd = bytearray(b'\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + cmd[132-INIT_OFFSET] = lpl_len & 0xff + cmd[136-INIT_OFFSET] = (addr >> 24) & 0xff + cmd[137-INIT_OFFSET] = (addr >> 16) & 0xff + cmd[138-INIT_OFFSET] = (addr >> 8) & 0xff + cmd[139-INIT_OFFSET] = (addr >> 0) & 0xff + # pad data to 116 bytes just in case, make sure to fill all 0x9f page + paddedPayload = data.ljust(116, b'\x00') + cmd += paddedPayload + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + time.sleep(0.2) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'LPL firmware download status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'LPL firmware download status: Fail- ' + status_txt + else: + txt = 'LPL firmware download status: Success' + logger.info(txt) + return status + + # Download FW with EPL + def block_write_epl(self, addr, data, autopaging_flag, writelength): + ''' + This command writes one block of the firmware image into the EPL + It returns the status of CDB command 0104h + ''' + epl_len = len(data) + subtime = time.time() + if not autopaging_flag: + pages = epl_len // PAGE_LENGTH + if (epl_len % PAGE_LENGTH) != 0: + pages += 1 + # write to page 0xA0 - 0xAF (max of 16 pages) + for pageoffset in range(pages): + next_page = 0xa0 + pageoffset + if PAGE_LENGTH*(pageoffset + 1) <= epl_len: + datachunk = data[PAGE_LENGTH*pageoffset : PAGE_LENGTH*(pageoffset + 1)] + self.xcvr_eeprom.write_raw(next_page*PAGE_LENGTH+INIT_OFFSET, PAGE_LENGTH, datachunk) + else: + datachunk = data[INIT_OFFSET*pageoffset : ] + self.xcvr_eeprom.write_raw(next_page*PAGE_LENGTH+INIT_OFFSET, len(datachunk), datachunk) + else: + sections = epl_len // writelength + if (epl_len % writelength) != 0: + sections += 1 + # write to page 0xA0 - 0xAF (max of 16 pages), with length of writelength per piece + for offset in range(0, epl_len, writelength): + if offset + writelength <= epl_len: + datachunk = data[offset : offset + writelength] + self.xcvr_eeprom.write_raw(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, writelength, datachunk) + else: + datachunk = data[offset : ] + self.xcvr_eeprom.write_raw(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, len(datachunk), datachunk) + subtimeint = time.time()-subtime + logger.info('%dB write time: %.2fs' %(epl_len, subtimeint)) + cmd = bytearray(b'\x01\x04\x08\x00\x04\x00\x00\x00') + addr_byte = struct.pack('>L',addr) + cmd += addr_byte + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + time.sleep(0.2) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'EPL firmware download status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'EPL firmware download status: Fail- ' + status_txt + else: + txt = 'EPL firmware download status: Success' + logger.info(txt) + return status + + # FW download complete + def validate_fw_image(self): + ''' + When this command is issued, the module shall validate the complete + image and then return success or failure + It returns the status of CDB command 0107h + ''' + cmd = bytearray(b'\x01\x07\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Firmware download complete status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Firmware download complete status: Fail- ' + status_txt + else: + txt = 'Firmware download complete status: Success' + logger.info(txt) + return status + + # Run FW image + # mode: + # 00h = Traffic affecting Reset to Inactive Image. + # 01h = Attempt Hitless Reset to Inactive Image + # 02h = Traffic affecting Reset to Running Image. + # 03h = Attempt Hitless Reset to Running Image + def run_fw_image(self, mode = 0x01): + ''' + The host uses this command to run a selected image from module internal firmware banks + It returns the status of CDB command 0109h + ''' + cmd = bytearray(b'\x01\x09\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00') + cmd[137-INIT_OFFSET] = mode + cmd[138-INIT_OFFSET] = 2 # Delay to Reset 512 ms + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Run firmware status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Run firmware status: Fail- ' + status_txt + else: + txt = 'Run firmware status: Success' + logger.info(txt) + return status + + # Commit FW image + def commit_fw_image(self): + ''' + A Commit is the process where the running image is set to be the image to be used on exit from module + reset. In other words, a committed image is the image that will run and is expected to be a 'good' firmware + version to run upon any resets (including watch dog). + + This command is used to switch the committed image after the firmware update process, when the new + firmware is running and when the host has determined that the new firmware is working properly. The module + shall only execute a Commit Image command on the image that it is currently running. If a non-running image + is allowed to be committed, it is possible that a bad version may be committed and attempted to run after the + next module reset. + + It returns the status of CDB command 010Ah + ''' + cmd = bytearray(b'\x01\x0A\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + self.write_cdb(cmd) + status = self.cdb1_chkstatus() + if (status != 0x1): + if status > 127: + txt = 'Commit firmware status: Busy' + else: + status_txt = self.failed_status_dict[status & 0x3f] + txt = 'Commit firmware status: Fail- ' + status_txt + else: + txt = 'Commit firmware status: Success' + logger.info(txt) + return status diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py new file mode 100644 index 000000000000..4d22a8d51c70 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py @@ -0,0 +1,180 @@ +""" + cmisCDB.py + + Implementation of APIs related to VDMs +""" + +from ...fields import consts +from ..xcvr_api import XcvrApi +import struct +import time + +PAGE_SIZE = 128 +PAGE_OFFSET = 128 +THRSH_SPACING = 8 +VDM_SIZE = 2 +VDM_FLAG_PAGE = 0x2c +VDM_FREEZE = 128 +VDM_UNFREEZE = 0 + +class CmisVdmApi(XcvrApi): + def __init__(self, xcvr_eeprom): + super(CmisVdmApi, self).__init__(xcvr_eeprom) + + def get_F16(self, value): + ''' + This function converts raw data to "F16" format defined in cmis. + ''' + scale_exponent = (value >> 11) & 0x1f + mantissa = value & 0x7ff + result = mantissa*10**(scale_exponent-24) + return result + + def get_vdm_page(self, page, VDM_flag_page): + ''' + This function returns VDM items from a specific VDM page. + Output format is a dictionary. Key is observable type; value is a dictionary. + In the inside dictionary, key is lane; value is a list + [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag + ] + ''' + if page not in [0x20, 0x21, 0x22, 0x23]: + raise ValueError('Page not in VDM Descriptor range!') + vdm_descriptor = self.xcvr_eeprom.read_raw(page * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) + + # Odd Adress VDM observable type ID, real-time monitored value in Page + 4 + vdm_typeID = vdm_descriptor[1::2] + # Even Address + # Bit 7-4: Threshold set ID in Page + 8, in group of 8 bytes, 16 sets/page + # Bit 3-0: n. Monitored lane n+1 + vdm_lane = [(elem & 0xf) for elem in vdm_descriptor[0::2]] + VDM_thresholdID = [(elem>>4) for elem in vdm_descriptor[0::2]] + vdm_valuePage = page + 4 + vdm_thrshPage = page + 8 + vdm_Page_data = {} + VDM_TYPE_DICT = self.xcvr_eeprom.mem_map.codes.VDM_TYPE + for index, typeID in enumerate(vdm_typeID): + if typeID not in VDM_TYPE_DICT: + continue + else: + vdm_info_dict = VDM_TYPE_DICT[typeID] + thrshID = VDM_thresholdID[index] + vdm_type = vdm_info_dict[0] + vdm_format = vdm_info_dict[1] + scale = vdm_info_dict[2] + + vdm_value_offset = vdm_valuePage * PAGE_SIZE + PAGE_OFFSET + VDM_SIZE * index + vdm_high_alarm_offset = vdm_thrshPage * PAGE_SIZE + PAGE_OFFSET + THRSH_SPACING * thrshID + vdm_low_alarm_offset = vdm_high_alarm_offset + 2 + vdm_high_warn_offset = vdm_high_alarm_offset + 4 + vdm_low_warn_offset = vdm_high_alarm_offset + 6 + + vdm_value_raw = self.xcvr_eeprom.read_raw(vdm_value_offset, VDM_SIZE, True) + vdm_thrsh_high_alarm_raw = self.xcvr_eeprom.read_raw(vdm_high_alarm_offset, VDM_SIZE, True) + vdm_thrsh_low_alarm_raw = self.xcvr_eeprom.read_raw(vdm_low_alarm_offset, VDM_SIZE, True) + vdm_thrsh_high_warn_raw = self.xcvr_eeprom.read_raw(vdm_high_warn_offset, VDM_SIZE, True) + vdm_thrsh_low_warn_raw = self.xcvr_eeprom.read_raw(vdm_low_warn_offset, VDM_SIZE, True) + if vdm_format == 'S16': + vdm_value = struct.unpack('>h',vdm_value_raw)[0] * scale + vdm_thrsh_high_alarm = struct.unpack('>h', vdm_thrsh_high_alarm_raw)[0] * scale + vdm_thrsh_low_alarm = struct.unpack('>h', vdm_thrsh_low_alarm_raw)[0] * scale + vdm_thrsh_high_warn = struct.unpack('>h', vdm_thrsh_high_warn_raw)[0] * scale + vdm_thrsh_low_warn = struct.unpack('>h', vdm_thrsh_low_warn_raw)[0] * scale + elif vdm_format == 'U16': + vdm_value = struct.unpack('>H',vdm_value_raw)[0] * scale + vdm_thrsh_high_alarm = struct.unpack('>H', vdm_thrsh_high_alarm_raw)[0] * scale + vdm_thrsh_low_alarm = struct.unpack('>H', vdm_thrsh_low_alarm_raw)[0] * scale + vdm_thrsh_high_warn = struct.unpack('>H', vdm_thrsh_high_warn_raw)[0] * scale + vdm_thrsh_low_warn = struct.unpack('>H', vdm_thrsh_low_warn_raw)[0] * scale + elif vdm_format == 'F16': + vdm_value_int = struct.unpack('>H',vdm_value_raw)[0] + vdm_value = self.get_F16(vdm_value_int) + vdm_thrsh_high_alarm_int = struct.unpack('>H', vdm_thrsh_high_alarm_raw)[0] + vdm_thrsh_low_alarm_int = struct.unpack('>H', vdm_thrsh_low_alarm_raw)[0] + vdm_thrsh_high_warn_int = struct.unpack('>H', vdm_thrsh_high_warn_raw)[0] + vdm_thrsh_low_warn_int = struct.unpack('>H', vdm_thrsh_low_warn_raw)[0] + vdm_thrsh_high_alarm = self.get_F16(vdm_thrsh_high_alarm_int) + vdm_thrsh_low_alarm = self.get_F16(vdm_thrsh_low_alarm_int) + vdm_thrsh_high_warn = self.get_F16(vdm_thrsh_high_warn_int) + vdm_thrsh_low_warn = self.get_F16(vdm_thrsh_low_warn_int) + else: + continue + + vdm_flag_offset = 32 * (page - 0x20) + index//2 + bit_offset = 4*(index%2) + vdm_high_alarm_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset)) & 0x1) + vdm_low_alarm_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+1)) & 0x1) + vdm_high_warn_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+2)) & 0x1) + vdm_low_warn_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+3)) & 0x1) + + if vdm_type not in vdm_Page_data: + vdm_Page_data[vdm_type] = { + vdm_lane[index]+1: [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag] + } + + else: + vdm_Page_data[vdm_info_dict[0]][vdm_lane[index]+1] = [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag] + return vdm_Page_data + + def get_vdm_allpage(self): + ''' + This function returns VDM items from all advertised VDM pages. + Output format is a dictionary. Key is observable type; value is a dictionary. + In the inside dictionary, key is lane; value is a list + [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag + ] + ''' + vdm_page_supported_raw = self.xcvr_eeprom.read(consts.VDM_SUPPORTED_PAGE) + if vdm_page_supported_raw is None: + return None + VDM_START_PAGE = 0x20 + vdm = dict() + # When raised by the host, causes the module to freeze and hold all + # reported statistics reporting registers (minimum, maximum and + # average values)in Pages 24h-27h. + # When ceased by the host, releases the freeze request, allowing the + # reported minimum, maximum and average values to update again. + self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_FREEZE) + time.sleep(1) + self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_UNFREEZE) + vdm_flag_page = self.xcvr_eeprom.read_raw(VDM_FLAG_PAGE * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) + for page in range(VDM_START_PAGE, VDM_START_PAGE + vdm_page_supported_raw + 1): + vdm_current_page = self.get_vdm_page(page, vdm_flag_page) + vdm.update(vdm_current_page) + return vdm diff --git a/sonic_platform_base/sonic_xcvr/codes/public/cmis.py b/sonic_platform_base/sonic_xcvr/codes/public/cmis.py index 985fa7a7c207..9bbcb0be6500 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/cmis.py @@ -20,3 +20,122 @@ class CmisCodes(Sff8024): 4: "active_cable_media_interface", 5: "base_t_media_interface", } + + MEDIA_INTERFACE_TECH = { + 0: '850 nm VCSEL', + 1: '1310 nm VCSEL', + 2: '1550 nm VCSEL', + 3: '1310 nm FP', + 4: '1310 nm DFB', + 5: '1550 nm DFB', + 6: '1310 nm EML', + 7: '1550 nm EML', + 8: 'Others', + 9: '1490 nm DFB', + 10: 'Copper cable unequalized', + 11: 'Copper cable passive equalized', + 12: 'Copper cable, near and far end limiting active equalizers', + 13: 'Copper cable, far end limiting active equalizers', + 14: 'Copper cable, near end limiting active equalizers', + 15: 'Copper cable, linear active equalizers', + 16: 'C-band tunable laser', + 17: 'L-band tunable laser', + } + + MODULE_STATE = { + 1: 'ModuleLowPwr', + 2: 'ModulePwrUp', + 3: 'ModuleReady', + 4: 'ModulePwrDn', + 5: 'ModuleFault', + } + + MODULE_FAULT_CAUSE = { + 0: 'No Fault detected', + 1: 'TEC runawawy', + 2: 'Data memory corrupted', + 3: 'Program memory corrupted', + } + + DATAPATH_STATE = { + 1: 'DataPathDeactivated', + 2: 'DataPathInit', + 3: 'DataPathDeinit', + 4: 'DataPathActivated', + 5: 'DataPathTxTurnOn', + 6: 'DataPathTxTurnOff', + 7: 'DataPathInitialized', + } + + CONFIG_STATUS = { + 0: 'ConfigUndefined', + 1: 'ConfigSuccess', + 2: 'ConfigRejected', + 3: 'ConfigRejectedInvalidAppSel', + 4: 'ConfigRejectedInvalidDataPath', + 5: 'ConfigRejectedInvalidSI', + 6: 'ConfigRejectedLaneInUse', + 7: 'ConfigRejectedPartialDataPath', + 12: 'ConfigInProgress', + } + + VDM_TYPE = { + # VDM_ID: [VDM_NAME, DATA_TYPE, SCALE] + 1: ['Laser Age [%]', 'U16', 1], + 2: ['TEC Current [%]', 'S16', 100.0/32767], + 3: ['Laser Frequency Error [MHz]', 'S16', 10], + 4: ['Laser Temperature [C]', 'S16', 1.0/256], + 5: ['eSNR Media Input [dB]', 'U16', 1.0/256], + 6: ['eSNR Host Input [dB]', 'U16', 1.0/256], + 7: ['PAM4 Level Transition Parameter Media Input [dB]', 'U16', 1.0/256], + 8: ['PAM4 Level Transition Parameter Host Input [dB]', 'U16', 1.0/256], + 9: ['Pre-FEC BER Minimum Media Input', 'F16', 1], + 10: ['Pre-FEC BER Minimum Host Input', 'F16', 1], + 11: ['Pre-FEC BER Maximum Media Input', 'F16', 1], + 12: ['Pre-FEC BER Maximum Host Input', 'F16', 1], + 13: ['Pre-FEC BER Average Media Input', 'F16', 1], + 14: ['Pre-FEC BER Average Host Input', 'F16', 1], + 15: ['Pre-FEC BER Current Value Media Input', 'F16', 1], + 16: ['Pre-FEC BER Current Value Host Input', 'F16', 1], + 17: ['Errored Frames Minimum Media Input', 'F16', 1], + 18: ['Errored Frames Minimum Host Input', 'F16', 1], + 19: ['Errored Frames Maximum Media Input', 'F16', 1], + 20: ['Errored Frames Maximum Host Input', 'F16', 1], + 21: ['Errored Frames Average Media Input', 'F16', 1], + 22: ['Errored Frames Average Host Input', 'F16', 1], + 23: ['Errored Frames Current Value Media Input', 'F16', 1], + 24: ['Errored Frames Current Value Host Input', 'F16', 1], + 128: ['Modulator Bias X/I [%]', 'U16', 100.0/65535], + 129: ['Modulator Bias X/Q [%]', 'U16', 100.0/65535], + 130: ['Modulator Bias Y/I [%]', 'U16', 100.0/65535], + 131: ['Modulator Bias Y/Q [%]', 'U16', 100.0/65535], + 132: ['Modulator Bias X_Phase [%]', 'U16', 100.0/65535], + 133: ['Modulator Bias Y_Phase [%]', 'U16', 100.0/65535], + 134: ['CD high granularity, short link [ps/nm]', 'S16', 1], + 135: ['CD low granularity, long link [ps/nm]', 'S16', 20], + 136: ['DGD [ps]', 'U16', 0.01], + 137: ['SOPMD [ps^2]', 'U16', 0.01], + 138: ['PDL [dB]', 'U16', 0.1], + 139: ['OSNR [dB]', 'U16', 0.1], + 140: ['eSNR [dB]', 'U16', 0.1], + 141: ['CFO [MHz]', 'S16', 1], + 142: ['EVM_modem [%]', 'U16', 100.0/65535], + 143: ['Tx Power [dBm]', 'S16', 0.01], + 144: ['Rx Total Power [dBm]', 'S16', 0.01], + 145: ['Rx Signal Power [dBm]', 'S16', 0.01], + 146: ['SOP ROC [krad/s]', 'U16', 1], + 147: ['MER [dB]', 'U16', 0.1] + } + + CDB_FAIL_STATUS = { + 0: 'reserved', + 1: 'CMDID unknown', + 2: 'Parameter range error or parameter not supported', + 3: 'Previous CMD was not properly ABORTED', + 4: 'Command checking time out', + 5: 'CdbChkCode Error', + 6: 'Password related error', + 7: 'Command not compatible with operating status' + } + + # TODO: Add other codes diff --git a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py index f9e7b00aebe0..6afd538b044c 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py @@ -72,7 +72,7 @@ class Sff8024(XcvrCodes): 27: 'DSFP', 28: 'Link-x4', 29: 'Link-x8', - 30: 'QSFP+', + 30: 'QSFP+' } CONNECTORS = { @@ -98,7 +98,7 @@ class Sff8024(XcvrCodes): 37: 'CS optical connector', 38: 'SN optical connector', 39: 'MPO 2x12', - 40: 'MPO 1x16', + 40: 'MPO 1x16' } ENCODINGS = { @@ -108,7 +108,7 @@ class Sff8024(XcvrCodes): 3: "NRZ", # 4-6 differ between 8472 and 8436/8636 7: "256B/257B (transcoded FEC-enabled data)", - 8: "PAM4", + 8: "PAM4" } EXT_SPEC_COMPLIANCE = { @@ -174,4 +174,197 @@ class Sff8024(XcvrCodes): 129: 'Capable of 128GFC' } + + MODULE_MEDIA_TYPE = { + 0: 'Undefined', + 1: 'Multimode Fiber (MMF)', + 2: 'Single Mode Fiber (SMF)', + 3: 'Passive Copper Cable', + 4: 'Active Cable Assembly', + 5: 'BASE-T' + } + + HOST_ELECTRICAL_INTERFACE = { + 0: 'Undefined', + 1: '1000BASE -CX(Clause 39)', + 2: 'XAUI(Clause 47)', + 3: 'XFI (SFF INF-8071i)', + 4: 'SFI (SFF-8431)', + 5: '25GAUI C2M (Annex 109B)', + 6: 'XLAUI C2M (Annex 83B)', + 7: 'XLPPI (Annex 86A)', + 8: 'LAUI-2 C2M (Annex 135C)', + 9: '50GAUI-2 C2M (Annex 135E)', + 10: '50GAUI-1 C2M (Annex 135G)', + 11: 'CAUI-4 C2M (Annex 83E)', + 12: '100GAUI-4 C2M (Annex 135E)', + 13: '100GAUI-2 C2M (Annex 135G)', + 14: '200GAUI-8 C2M (Annex 120C)', + 15: '200GAUI-4 C2M (Annex 120E)', + 16: '400GAUI-16 C2M (Annex 120C)', + 17: '400GAUI-8 C2M (Annex 120E)', + 19: '10GBASE-CX4 (Clause 54)', + 20: '25GBASE-CR CA-L (Clause 110)', + 21: '25GBASE-CR CA-S (Clause 110)', + 22: '25GBASE-CR CA-N (Clause 110)', + 23: '40GBASE-CR4 (Clause 85)', + 24: '50GBASE-CR (Clause 126)', + 25: '100GBASE-CR10 (Clause 85)', + 26: '100GBASE-CR4 (Clause 92)', + 27: '100GBASE-CR2 (Clause 136)', + 28: '200GBASE-CR4 (Clause 136)', + 29: '400G CR8', + 30: '1000BASE-T (Clause 40)', + 31: '2.5GBASE-T (Clause 126)', + 32: '5GBASE-T (Clause 126)', + 33: '10GBASE-T (Clause 55)', + 34: '25GBASE-T (Clause 113)', + 35: '40GBASE-T (Clause 113)', + 36: '50GBASE-T (Placeholder)', + 37: '8GFC (FC-PI-4)', + 38: '10GFC (10GFC)', + 39: '16GFC (FC-PI-5)', + 40: '32GFC (FC-PI-6)', + 41: '64GFC (FC-PI-7)', + 42: '128GFC (FC-PI-6P)', + 43: '256GFC (FC-PI-7P)', + 44: 'IB SDR (Arch.Spec.Vol.2)', + 45: 'IB DDR (Arch.Spec.Vol.2)', + 46: 'IB QDR (Arch.Spec.Vol.2)', + 47: 'IB FDR (Arch.Spec.Vol.2)', + 48: 'IB EDR (Arch.Spec.Vol.2)', + 49: 'IB HDR (Arch.Spec.Vol.2)', + 50: 'IB NDR', + 51: 'E.96 (CPRI Specification V7.0)', + 52: 'E.99 (CPRI Specification V7.0)', + 53: 'E.119 (CPRI Specification V7.0)', + 54: 'E.238 (CPRI Specification V7.0)', + 55: 'OTL3.4 (ITU-T G.709/Y.1331 G.Sup58)', + 56: 'OTL4.10 (ITU-T G.709/Y.1331 G.Sup58)', + 57: 'OTL4.4 (ITU-T G.709/Y.1331 G.Sup58)', + 58: 'OTLC.4 (ITU-T G.709.1/Y.1331 G.Sup58)', + 59: 'FOIC1.4 (ITU-T G.709.1/Y.1331 G.Sup58)', + 60: 'FOIC1.2 (ITU-T G.709.1/Y.1331 G.Sup58)', + 61: 'FOIC2.8 (ITU-T G.709.1/Y.1331 G.Sup58)', + 62: 'FOIC2.4 (ITU-T G.709.1/Y.1331 G.Sup58)', + 63: 'FOIC4.16 (ITU-T G.709.1 G.Sup58)', + 64: 'FOIC4.8 (ITU-T G.709.1 G.Sup58)' + } + + NM_850_MEDIA_INTERFACE = { + 0: 'Undefined', + 1: '10GBASE-SW (Clause 52)', + 2: '10GBASE-SR (Clause 52)', + 3: '25GBASE-SR (Clause 112)', + 4: '40GBASE-SR4 (Clause 86)', + 5: '40GE SWDM4 MSA Spec', + 6: '40GE BiDi', + 7: '50GBASE-SR (Clause 138)', + 8: '100GBASE-SR10 (Clause 86)', + 9: '100GBASE-SR4 (Clause 95)', + 10: '100GE SWDM4 MSA Spec', + 11: '100GE BiDi', + 12: '100GBASE-SR2 (Clause 138)', + 13: '100G-SR (Placeholder)', + 14: '200GBASE-SR4 (Clause 138)', + 15: '400GBASE-SR16 (Clause 123)', + 16: '400GBASE-SR8 (Clause 138)', + 17: '400G-SR4 (Placeholder)', + 18: '800G-SR8 (Placeholder)', + 26: '400GBASE-SR4.2 (Clause 150) (400GE BiDi)', + 19: '8GFC-MM (FC-PI-4)', + 20: '10GFC-MM (10GFC)', + 21: '16GFC-MM (FC-PI-5)', + 22: '32GFC-MM (FC-PI-6)', + 23: '64GFC-MM (FC-PI 7)', + 24: '128GFC-MM4 (FC-PI-6P)', + 25: '256GFC-MM4 (FC-PI-7P)' + } + + SM_MEDIA_INTERFACE = { + 0: 'Undefined', + 1: '10GBASE-LW (Cl 52)', + 2: '10GBASE-EW (Cl 52)', + 3: '10G-ZW', + 4: '10GBASE-LR (Cl 52)', + 5: '10GBASE-ER (Cl 52)', + 6: '10G-ZR', + 7: '25GBASE-LR (Cl 114)', + 8: '25GBASE-ER (Cl 114)', + 9: '40GBASE-LR4 (Cl 87)', + 10: '40GBASE-FR (Cl 89)', + 11: '50GBASE-FR (Cl 139)', + 12: '50GBASE-LR (Cl 139)', + 13: '100GBASE-LR4 (Cl 88)', + 14: '100GBASE-ER4 (Cl 88)', + 15: '100G PSM4 MSA Spec', + 16: '100G CWDM4 MSA Spec', + 17: '100G 4WDM-10 MSA Spec', + 18: '100G 4WDM-20 MSA Spec', + 19: '100G 4WDM-40 MSA Spec', + 20: '100GBASE-DR (Cl 140)', + 21: '100G-FR/100GBASE-FR1 (Cl 140)', + 22: '100G-LR/100GBASE-LR1 (Cl 140)', + 23: '200GBASE-DR4 (Cl 121)', + 24: '200GBASE-FR4 (Cl 122)', + 25: '200GBASE-LR4 (Cl 122)', + 26: '400GBASE-FR8 (Cl 122)', + 27: '400GBASE-LR8 (Cl 122)', + 28: '400GBASE-DR4 (Cl 124)', + 29: '400G-FR4/400GBASE-FR4 (Cl 151)', + 30: '400G-LR4-10', + 31: '8GFC-SM (FC-PI-4)', + 32: '10GFC-SM (10GFC)', + 33: '16GFC-SM (FC-PI-5)', + 34: '32GFC-SM (FC-PI-6)', + 35: '64GFC-SM (FC-PI-7)', + 36: '128GFC-PSM4 (FC-PI-6P)', + 37: '256GFC-PSM4 (FC-PI-7P)', + 38: '128GFC-CWDM4 (FC-PI-6P)', + 39: '256GFC-CWDM4 (FC-PI-7P)', + 44: '4I1-9D1F (G.959.1)', + 45: '4L1-9C1F (G.959.1)', + 46: '4L1-9D1F (G.959.1)', + 47: 'C4S1-9D1F (G.695)', + 48: 'C4S1-4D1F (G.695)', + 49: '4I1-4D1F (G.959.1)', + 50: '8R1-4D1F (G.959.1)', + 51: '8I1-4D1F (G.959.1)', + 56: '10G-SR', + 57: '10G-LR', + 58: '25G-SR', + 59: '25G-LR', + 60: '10G-LR-BiDi', + 61: '25G-LR-BiDi', + 62: '400ZR, DWDM, amplified', + 63: '400ZR, Single Wavelength, Unamplified', + 70: 'ZR400-OFEC-16QAM', + 71: 'ZR300-OFEC-8QAM', + 72: 'ZR200-OFEC-QPSK', + 73: 'ZR100-OFEC-QPSK' + } + + PASSIVE_COPPER_MEDIA_INTERFACE = { + '00': 'Undefined', + '01': 'Copper cable', + '02': 'Passive Loopback module' + } + + ACTIVE_CABLE_MEDIA_INTERFACE = { + '00': 'Undefined', + '01': 'Active Cable assembly with BER < 10^-12', + '02': 'Active Cable assembly with BER < 5x10^-5', + '03': 'Active Cable assembly with BER < 2.6x10^-4', + '04': 'Active Cable assembly with BER < 10^-6', + 'bf': 'Active Loopback module' + } + + BASE_T_MEDIA_INTERFACE = { + '00': 'Undefined', + '01': '1000BASE-T (Clause 40)', + '02': '2.5GBASE-T (Clause 126)', + '03': '5GBASE-T (Clause 126)', + '04': '10GBASE-T (Clause 55)' + } + # TODO: Add other codes diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index 35c4767c8852..87823867afa9 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -108,6 +108,124 @@ # CMIS ADMIN_INFO_FIELD = "AdminInfo" +MEDIA_TYPE_FIELD = "ModuleMediaType" +HOST_ELECTRICAL_INTERFACE = "HostElectricalInterfaceID" +MODULE_MEDIA_INTERFACE_850NM = "ModuleMediaInterface850nm" +MODULE_MEDIA_INTERFACE_SM = "ModuleMediaInterfaceSM" +MODULE_MEDIA_INTERFACE_PASSIVE_COPPER = "ModuleMediaInterfacePassiveCopper" +MODULE_MEDIA_INTERFACE_ACTIVE_CABLE = "ModuleMediaInterfaceActiveCable" +MODULE_MEDIA_INTERFACE_BASE_T = "ModuleMediaInterfaceBaseT" +HOST_LANE_COUNT = "HostLaneCount" +MEDIA_LANE_COUNT = "MediaLaneCount" +HOST_LANE_ASSIGNMENT_OPTION = "HostLaneAssignmentOptions" +MEDIA_LANE_ASSIGNMENT_OPTION = "MediaLaneAssignmentOptions" +ACTIVE_APSEL_CODE = "ActiveAppSelCode" +ACTIVE_APSEL_HOSTLANE = "ActiveAppSelLane" +MEDIA_INTERFACE_TECH = "MediaInterfaceTechnology" +HW_MAJOR_REV = "ModuleHardwareMajorRevision" +HW_MINOR_REV = "ModuleHardwareMinorRevision" +CMIS_MAJOR_REVISION = "CmisMajorRevision" +CMIS_MINOR_REVISION = "CmisMinorRevision" +ACTIVE_FW_MAJOR_REV = "ModuleActiveFirmwareMajorRevision" +ACTIVE_FW_MINOR_REV = "ModuleActiveFirmwareMinorRevision" +INACTIVE_FW_MAJOR_REV = "ModuleInactiveFirmwareMajorRevision" +INACTIVE_FW_MINOR_REV = "ModuleInactiveFirmwareMinorRevision" + +# DOM +TRANS_DOM_FIELD = "TransceiverDom" +CASE_TEMP = "ModuleTemp" +VOLTAGE = "Supply3V3" +GRID_SPACING = "Tx1SelectedGridSpacing" +LASER_CONFIG_CHANNEL = "Tx1ChannelNumber" +LASER_CURRENT_FREQ = "Tx1CurrentLaserFrequency" +TX_CONFIG_POWER = "Tx1TargetOutputPower" +AUX_MON_TYPE = "AuxMonitorType" +AUX1_MON = "Aux1MonValue" +AUX2_MON = "Aux2MonValue" +AUX3_MON = "Aux3MonValue" +CUSTOM_MON = "CustomMonValue" + +# Loopback +TRANS_LOOPBACK_FIELD = "TransceiverLoopback" +LOOPBACK_CAPABILITY = "LoopbackCapability" +MEDIA_OUTPUT_LOOPBACK = "MediaSideOutputLoopbackEnable" +MEDIA_INPUT_LOOPBACK = "MediaSideInputLoopbackEnable" +HOST_OUTPUT_LOOPBACK = "HostSideOutputLoopbackEnable" +HOST_INPUT_LOOPBACK = "HostSideLoopbackEnable" + +# Threshold +TRANS_THRESHOLD_FIELD = "TransceiverThreshold" +CASE_TEMP_HIGH_ALARM = "TempeartureHighAlarmThreshold" +CASE_TEMP_LOW_ALARM = "TempeartureLowAlarmThreshold" +CASE_TEMP_HIGH_WARN = "TempeartureHighWarningThreshold" +CASE_TEMP_LOW_WARN = "TempeartureLowWarningThreshold" +VOLTAGE_HIGH_ALARM = "Supply3V3HighAlarmThreshold" +VOLTAGE_LOW_ALARM = "Supply3V3LowAlarmThreshold" +VOLTAGE_HIGH_WARN = "Supply3V3HighWarningThreshold" +VOLTAGE_LOW_WARN = "Supply3V3LowWarningThreshold" +AUX1_HIGH_ALARM = "Aux1MonitorHighAlarmThreshold" +AUX1_LOW_ALARM = "Aux1MonitorLowAlarmThreshold" +AUX1_HIGH_WARN = "Aux1MonitorHighWarningThreshold" +AUX1_LOW_WARN = "Aux1MonitorLowWarningThreshold" +AUX2_HIGH_ALARM = "Aux2MonitorHighAlarmThreshold" +AUX2_LOW_ALARM = "Aux2MonitorLowAlarmThreshold" +AUX2_HIGH_WARN = "Aux2MonitorHighWarningThreshold" +AUX2_LOW_WARN = "Aux2MonitorLowWarningThreshold" +AUX3_HIGH_ALARM = "Aux3MonitorHighAlarmThreshold" +AUX3_LOW_ALARM = "Aux3MonitorLowAlarmThreshold" +AUX3_HIGH_WARN = "Aux3MonitorHighWarningThreshold" +AUX3_LOW_WARN = "Aux3MonitorLowWarningThreshold" +TX_POWER_HIGH_ALARM = "TxOpticalPowerHighAlarmThreshold" +TX_POWER_LOW_ALARM = "TxOpticalPowerLowAlarmThreshold" +TX_POWER_HIGH_WARN = "TxOpticalPowerHighWarningThreshold" +TX_POWER_LOW_WARN = "TxOpticalPowerLowWarningThreshold" +TX_BIAS_CURR_HIGH_ALARM = "TxBiasCurrentHighAlarmThreshold" +TX_BIAS_CURR_LOW_ALARM = "TxBiasCurrentLowAlarmThreshold" +TX_BIAS_CURR_HIGH_WARN = "TxBiasCurrentHighWarningThreshold" +TX_BIAS_CURR_LOW_WARN = "TxBiasCurrentLowWarningThreshold" +RX_POWER_HIGH_ALARM = "RxOpticalPowerHighAlarmThreshold" +RX_POWER_LOW_ALARM = "RxOpticalPowerLowAlarmThreshold" +RX_POWER_HIGH_WARN = "RxOpticalPowerHighWarningThreshold" +RX_POWER_LOW_WARN = "RxOpticalPowerLowWarningThreshold" + +# Status +TRANS_MODULE_STATUS_FIELD = "TransceiverModuleStatus" +TRANS_LANE_STATUS_FIELD = "TransceiverLaneStatus" +MODULE_STATE = "ModuleState" +MODULE_FIRMWARE_FAULT_INFO = "FirmwareFault" +MODULE_FLAG_BYTE1 = "ModuleFlagByte1" +MODULE_FLAG_BYTE2 = "ModuleFlagByte2" +MODULE_FLAG_BYTE3 = "ModuleFlagByte3" +CDB1_STATUS = "Cdb1Status" +MODULE_FAULT_CAUSE = "ModuleFaultCause" +DATA_PATH_STATE= "DataPathState" +TX_OUTPUT_STATUS = "TxOutputStatus" +RX_OUTPUT_STATUS = "RxOutputStatus" +TX_LOS_FIELD = "TxLOS" +TX_CDR_LOL = "TxCDRLOL" +TX_POWER_HIGH_ALARM_FLAG = "TxPowerHighAlarmFlag" +TX_POWER_LOW_ALARM_FLAG = "TxPowerLowAlarmFlag" +TX_POWER_HIGH_WARN_FLAG = "TxPowerHighWarnFlag" +TX_POWER_LOW_WARN_FLAG = "TxPowerLowWarnFlag" +TX_BIAS_HIGH_ALARM_FLAG = "TxBiasHighAlarmFlag" +TX_BIAS_LOW_ALARM_FLAG = "TxBiasLowAlarmFlag" +TX_BIAS_HIGH_WARN_FLAG = "TxBiasHighWarnFlag" +TX_BIAS_LOW_WARN_FLAG = "TxBiasLowWarnFlag" +RX_POWER_HIGH_ALARM_FLAG = "RxPowerHighAlarmFlag" +RX_POWER_LOW_ALARM_FLAG = "RxPowerLowAlarmFlag" +RX_POWER_HIGH_WARN_FLAG = "RxPowerHighWarnFlag" +RX_POWER_LOW_WARN_FLAG = "RxPowerLowWarnFlag" + +RX_CDR_LOL = "RxCDRLOL" +CONFIG_LANE_STATUS = "ConfigStatusLane" +DPINIT_PENDING = "DPInitPending" +TUNING_IN_PROGRESS = "TxTuningInProgress" +WAVELENGTH_UNLOCKED = "TxWavelengthUnlocked" +LASER_TUNING_DETAIL = "TxTuningDetail" + +# CONFIG +TRANS_CONFIG_FIELD = "TransceriverConfig" +MODULE_LEVEL_CONTROL = "ModuleControl" CTRLS_ADVT_FIELD = "Supported Controls Advertisement" FLAGS_ADVT_FIELD = "Supported Flags Advertisement" @@ -116,7 +234,6 @@ LANE_DATAPATH_STATUS_FIELD = "Lane Status and Data Path Status" LEN_MULT_FIELD = "LengthMultiplier" MAX_POWER_FIELD = "MaxPower" -MEDIA_TYPE_FIELD = "Media Type" MGMT_CHAR_FIELD = "Management Characteristics" MGMT_CHAR_MISC_FIELD = "Management Characteristics (Misc)" @@ -124,14 +241,82 @@ # C-CMIS -## Media Lane FEC Performance Monitoring -RX_BITS_PM_FIELD = "rxBitsPm" -RX_BITS_SUB_INT_PM_FIELD = "rxBitsSubIntPm" -MEDIA_LANE_FEC_PM_FIELD = "Media Lane FEC Performance Monitoring" -MEDIA_LANE_LINK_PM_FIELD = "Media Lane Link Performance Monitoring" +# Module configuration support fields +MODULE_CONFIG_SUPPORT_FIELD = "ModuleConfigSupport" +SUPPORT_GRID = "GridSupported" +LOW_CHANNEL = "LowChannel75GHz" +HIGH_CHANNEL = "HighChannel75GHz" +MIN_PROG_OUTPUT_POWER = "MinProgOutputPower" +MAX_PROG_OUTPUT_POWER = "MaxProgOutputPower" +## Media Lane FEC Performance Monitoring ## Media Lane Link Performance Monitoring -RX_AVG_CD_PM_FIELD = "rxAvgCdPm" -RX_MIN_CD_PM_FIELD = "rxMinCdPm" -RX_MAX_CD_PM_FIELD = "rxMaxCdPm" -RX_AVG_DGD_PM_FIELD = "rxAvgDgdPm" +# PM +TRANS_PM_FIELD = "TransceiverPm" +VDM_SUPPORTED_PAGE = "VdmSupportedPage" +VDM_CONTROL = "VdmControl" +MEDIA_LANE_FEC_PM = "Media Lane FEC Performance Monitoring" +MEDIA_LANE_LINK_PM = "Media Lane Link Performance Monitoring" +RX_BITS_PM = "rxBitsPm" +RX_BITS_SUB_INTERVAL_PM = "rxBitsSubIntPm" +RX_CORR_BITS_PM = "rxCorrBitsPm" +RX_MIN_CORR_BITS_SUB_INTERVAL_PM = "rxMinCorrBitsSubIntPm" +RX_MAX_CORR_BITS_SUB_INTERVAL_PM = "rxMaxCorrBitsSubIntPm" +RX_FRAMES_PM = "rxFramesPm" +RX_FRAMES_SUB_INTERVAL_PM = "rxFramsSubIntPm" +RX_FRAMES_UNCORR_ERR_PM = "rxFramesUncorrErrPm" +RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM = "rxMinFramesUncorrErrSubintPm" +RX_MAX_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM = "rxMaxFramesUncorrErrSubintPm" + +RX_AVG_CD_PM = "rxAvgCdPm" +RX_MIN_CD_PM = "rxMinCdPm" +RX_MAX_CD_PM = "rxMaxCdPm" +RX_AVG_DGD_PM = "rxAvgDgdPm" +RX_MIN_DGD_PM = "rxMinDgdPm" +RX_MAX_DGD_PM = "rxMaxDgdPm" +RX_AVG_SOPMD_PM = "rxAvgSopmdPm" +RX_MIN_SOPMD_PM = "rxMinSopmdPm" +RX_MAX_SOPMD_PM = "rxMaxSopmdPm" +RX_AVG_PDL_PM = "rxAvgPdlPm" +RX_MIN_PDL_PM = "rxMinPdlPm" +RX_MAX_PDL_PM = "rxMaxPdlPm" +RX_AVG_OSNR_PM = "rxAvgOsnrPm" +RX_MIN_OSNR_PM = "rxMinOsnrPm" +RX_MAX_OSNR_PM = "rxMaxOsnrPm" +RX_AVG_ESNR_PM = "rxAvgEsnrPm" +RX_MIN_ESNR_PM = "rxMinEsnrPm" +RX_MAX_ESNR_PM = "rxMaxEsnrPm" +RX_AVG_CFO_PM = "rxAvgCfoPm" +RX_MAX_CFO_PM = "rxMinCfoPm" +RX_MIN_CFO_PM = "rxMaxCfoPm" +RX_AVG_EVM_PM = "rxAvgEvmPm" +RX_MIN_EVM_PM = "rxMinEvmPm" +RX_MAX_EVM_PM = "rxMaxEvmPm" +TX_AVG_POWER_PM = "txAvgPowerPm" +TX_MIN_POWER_PM = "txMinPowerPm" +TX_MAX_POWER_PM = "txMaxPowerPm" +RX_AVG_POWER_PM = "rxAvgPowerPm" +RX_MIN_POWER_PM = "rxMinPowerPm" +RX_MAX_POWER_PM = "rxMaxPowerPm" +RX_AVG_SIG_POWER_PM = "rxAvgSigPowerPm" +RX_MIN_SIG_POWER_PM = "rxMinSigPowerPm" +RX_MAX_SIG_POWER_PM = "rxMaxSigPowerPm" +RX_AVG_SOPROC_PM = "rxAvgSigSoprocPm" +RX_MIN_SOPROC_PM = "rxMinSigSoprocPm" +RX_MAX_SOPROC_PM = "rxMaxSigSoprocPm" +RX_AVG_MER_PM = "rxAvgMerPm" +RX_MIN_MER_PM = "rxMinMerPm" +RX_MAX_MER_PM = "rxMaxMerPm" + +# CDB +TRANS_CDB_FIELD = "TransceiverCdb" +CDB_SUPPORT = "CdbSupport" +AUTO_PAGING_SUPPORT = "AutoPagingSupport" +CDB_SEQ_WRITE_LENGTH_EXT = "CdbReadWriteLengthExtension" +CDB_RPL_LENGTH = "CdbReplyLength" +CDB_RPL_CHKCODE = "CdbReplyCheckCode" +CDB_LPL = "CdbLocalPayload" +CDB_CMD = "CdbCommand" +CDB_WRITE_MSG = "CdbWriteMessage" + + diff --git a/sonic_platform_base/sonic_xcvr/fields/public/cmis.py b/sonic_platform_base/sonic_xcvr/fields/public/cmis.py index 582f2175b3aa..88806b1d5418 100644 --- a/sonic_platform_base/sonic_xcvr/fields/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/fields/public/cmis.py @@ -9,6 +9,5 @@ def __init__(self, name, offset, *fields, **kwargs): def decode(self, raw_data, **decoded_deps): base_len = super(CableLenField, self).decode(raw_data, **decoded_deps) len_mult = decoded_deps.get(consts.LEN_MULT_FIELD) - mult = 10 ** (len_mult - 1) return base_len * mult diff --git a/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py b/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py index f794d0e66746..e7d37622d88e 100644 --- a/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py +++ b/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py @@ -154,12 +154,12 @@ def decode(self, raw_data, **decoded_deps): decoded >>= self.start_bitpos if self.scale is not None: return decoded / self.scale - return decoded + return decoded def encode(self, val, raw_state=None): assert not self.ro if self.scale is not None: - return bytearray(struct.pack(self.format, val * self.scale)) + return bytearray(struct.pack(self.format, int(val * self.scale))) return bytearray(struct.pack(self.format, val)) class StringRegField(RegField): @@ -232,8 +232,18 @@ def decode(self, raw_data, **decoded_deps): start = self.offset for field in self.fields: offset = field.get_offset() - result[field.name] = field.decode(raw_data[offset - start: offset + field.get_size() - start], + if not field.get_deps(): + result[field.name] = field.decode(raw_data[offset - start: offset + field.get_size() - start], **decoded_deps) + + # Now decode any fields that have dependant fields in the same RegGroupField scope + for field in self.fields: + offset = field.get_offset() + deps = field.get_deps() + if deps: + decoded_deps = {dep: result[dep] for dep in deps} + result[field.name] = field.decode(raw_data[offset - start: offset + field.get_size() - start], + **decoded_deps) return result class DateField(StringRegField): diff --git a/sonic_platform_base/sonic_xcvr/mem_maps/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/mem_maps/public/c_cmis.py new file mode 100644 index 000000000000..14966784b0ab --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/c_cmis.py @@ -0,0 +1,84 @@ +""" + c_cmis.py + + Implementation of XcvrMemMap for C-CMIS Rev 1.1 +""" + +from ...fields.xcvr_field import ( + NumberRegField, + RegGroupField +) +from ...fields import consts +from .cmis import CmisMemMap + +class CCmisMemMap(CmisMemMap): + def __init__(self, codes): + super(CCmisMemMap, self).__init__(codes) + + self.MODULE_CONFIG_SUPPORT = RegGroupField(consts.MODULE_CONFIG_SUPPORT_FIELD, + NumberRegField(consts.SUPPORT_GRID, self.getaddr(0x4, 128)), + NumberRegField(consts.LOW_CHANNEL, self.getaddr(0x4, 158), format=">h", size=2), + NumberRegField(consts.HIGH_CHANNEL, self.getaddr(0x4, 160), format=">h", size=2), + NumberRegField(consts.MIN_PROG_OUTPUT_POWER, self.getaddr(0x4, 198), format=">h", size=2, scale = 100.0), + NumberRegField(consts.MAX_PROG_OUTPUT_POWER, self.getaddr(0x4, 200), format=">h", size=2, scale = 100.0) + ) + + self.MEDIA_LANE_FEC_PM = RegGroupField(consts.MEDIA_LANE_FEC_PM, + NumberRegField(consts.RX_BITS_PM, self.getaddr(0x34, 128), format=">Q", size=8), + NumberRegField(consts.RX_BITS_SUB_INTERVAL_PM, self.getaddr(0x34, 136), format=">Q", size=8), + NumberRegField(consts.RX_CORR_BITS_PM, self.getaddr(0x34, 144), format=">Q", size=8), + NumberRegField(consts.RX_MIN_CORR_BITS_SUB_INTERVAL_PM, self.getaddr(0x34, 152), format=">Q", size=8), + NumberRegField(consts.RX_MAX_CORR_BITS_SUB_INTERVAL_PM, self.getaddr(0x34, 160), format=">Q", size=8), + NumberRegField(consts.RX_FRAMES_PM, self.getaddr(0x34, 168), format=">I", size=4), + NumberRegField(consts.RX_FRAMES_SUB_INTERVAL_PM, self.getaddr(0x34, 172), format=">I", size=4), + NumberRegField(consts.RX_FRAMES_UNCORR_ERR_PM, self.getaddr(0x34, 176), format=">I", size=4), + NumberRegField(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM, self.getaddr(0x34, 180), format=">I", size=4), + NumberRegField(consts.RX_MAX_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM, self.getaddr(0x34, 184), format=">I", size=4), + ) + + # MEDIA_LANE_LINK_PM block corresponds to all the coherent PMs in C-CMIS spec reported in Page 35h. + self.MEDIA_LANE_LINK_PM = RegGroupField(consts.MEDIA_LANE_LINK_PM, + NumberRegField(consts.RX_AVG_CD_PM, self.getaddr(0x35, 128), format=">i", size=4), + NumberRegField(consts.RX_MIN_CD_PM, self.getaddr(0x35, 132), format=">i", size=4), + NumberRegField(consts.RX_MAX_CD_PM, self.getaddr(0x35, 136), format=">i", size=4), + NumberRegField(consts.RX_AVG_DGD_PM, self.getaddr(0x35, 140), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_DGD_PM, self.getaddr(0x35, 142), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_DGD_PM, self.getaddr(0x35, 144), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_SOPMD_PM, self.getaddr(0x35, 146), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_SOPMD_PM, self.getaddr(0x35, 148), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_SOPMD_PM, self.getaddr(0x35, 150), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_PDL_PM, self.getaddr(0x35, 152), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_PDL_PM, self.getaddr(0x35, 154), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_PDL_PM, self.getaddr(0x35, 156), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_AVG_OSNR_PM, self.getaddr(0x35, 158), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_OSNR_PM, self.getaddr(0x35, 160), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_OSNR_PM, self.getaddr(0x35, 162), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_AVG_ESNR_PM, self.getaddr(0x35, 164), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_ESNR_PM, self.getaddr(0x35, 166), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_ESNR_PM, self.getaddr(0x35, 168), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_AVG_CFO_PM, self.getaddr(0x35, 170), format=">h", size=2), + NumberRegField(consts.RX_MIN_CFO_PM, self.getaddr(0x35, 172), format=">h", size=2), + NumberRegField(consts.RX_MAX_CFO_PM, self.getaddr(0x35, 174), format=">h", size=2), + NumberRegField(consts.RX_AVG_EVM_PM, self.getaddr(0x35, 176), format=">H", size=2, scale=655.35), + NumberRegField(consts.RX_MIN_EVM_PM, self.getaddr(0x35, 178), format=">H", size=2, scale=655.35), + NumberRegField(consts.RX_MAX_EVM_PM, self.getaddr(0x35, 180), format=">H", size=2, scale=655.35), + NumberRegField(consts.TX_AVG_POWER_PM, self.getaddr(0x35,182), format=">h", size=2, scale=100.0), + NumberRegField(consts.TX_MIN_POWER_PM, self.getaddr(0x35,184), format=">h", size=2, scale=100.0), + NumberRegField(consts.TX_MAX_POWER_PM, self.getaddr(0x35,186), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_POWER_PM, self.getaddr(0x35,188), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_POWER_PM, self.getaddr(0x35,190), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_POWER_PM, self.getaddr(0x35,192), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_POWER_PM, self.getaddr(0x35,188), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_POWER_PM, self.getaddr(0x35,190), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_POWER_PM, self.getaddr(0x35,192), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_SIG_POWER_PM, self.getaddr(0x35,194), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_SIG_POWER_PM, self.getaddr(0x35,196), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_SIG_POWER_PM, self.getaddr(0x35,198), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_SOPROC_PM, self.getaddr(0x35,200), format=">H", size=2), + NumberRegField(consts.RX_MIN_SOPROC_PM, self.getaddr(0x35,202), format=">H", size=2), + NumberRegField(consts.RX_MAX_SOPROC_PM, self.getaddr(0x35,204), format=">H", size=2), + NumberRegField(consts.RX_AVG_MER_PM, self.getaddr(0x35,206), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_MER_PM, self.getaddr(0x35,208), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_MER_PM, self.getaddr(0x35,210), format=">H", size=2, scale=10.0), + # TODO: add others PMs... + ) diff --git a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py index 9e9e27bc06bc..c792c2bad074 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -22,111 +22,329 @@ def __init__(self, codes): super(CmisMemMap, self).__init__(codes) self.MGMT_CHARACTERISTICS = RegGroupField(consts.MGMT_CHAR_FIELD, - NumberRegField(consts.MGMT_CHAR_MISC_FIELD, self.get_addr(0x0, 2), + NumberRegField(consts.MGMT_CHAR_MISC_FIELD, self.getaddr(0x0, 2), RegBitField(consts.FLAT_MEM_FIELD, 7) ) ) - self.MEDIA_TYPE = CodeRegField(consts.MEDIA_TYPE_FIELD, self.get_addr(0x0, 85), self.codes.MEDIA_TYPES) - self.ADMIN_INFO = RegGroupField(consts.ADMIN_INFO_FIELD, - CodeRegField(consts.ID_FIELD, self.get_addr(0x0, 128), self.codes.XCVR_IDENTIFIERS), - CodeRegField(consts.ID_ABBRV_FIELD, self.get_addr(0x0, 128), self.codes.XCVR_IDENTIFIER_ABBRV), - StringRegField(consts.VENDOR_NAME_FIELD, self.get_addr(0x0, 129), size=16), - HexRegField(consts.VENDOR_OUI_FIELD, self.get_addr(0x0, 145), size=3), - StringRegField(consts.VENDOR_PART_NO_FIELD, self.get_addr(0x0, 148), size=16), - StringRegField(consts.VENDOR_REV_FIELD, self.get_addr(0x0, 164), size=2), - StringRegField(consts.VENDOR_SERIAL_NO_FIELD, self.get_addr(0x0, 166), size=16), - DateField(consts.VENDOR_DATE_FIELD, self.get_addr(0x0, 182), size=8), + CodeRegField(consts.ID_FIELD, self.getaddr(0x0, 128), self.codes.XCVR_IDENTIFIERS), + CodeRegField(consts.ID_ABBRV_FIELD, self.getaddr(0x0, 128), self.codes.XCVR_IDENTIFIER_ABBRV), + StringRegField(consts.VENDOR_NAME_FIELD, self.getaddr(0x0, 129), size=16), + HexRegField(consts.VENDOR_OUI_FIELD, self.getaddr(0x0, 145), size=3), + StringRegField(consts.VENDOR_PART_NO_FIELD, self.getaddr(0x0, 148), size=16), + StringRegField(consts.VENDOR_REV_FIELD, self.getaddr(0x0, 164), size=2), + StringRegField(consts.VENDOR_SERIAL_NO_FIELD, self.getaddr(0x0, 166), size=16), + DateField(consts.VENDOR_DATE_FIELD, self.getaddr(0x0, 182), size=8), RegGroupField(consts.EXT_ID_FIELD, - CodeRegField(consts.POWER_CLASS_FIELD, self.get_addr(0x0, 200), self.codes.POWER_CLASSES, + CodeRegField(consts.POWER_CLASS_FIELD, self.getaddr(0x0, 200), self.codes.POWER_CLASSES, *(RegBitField("%s_%d" % (consts.POWER_CLASS_FIELD, bit), bit) for bit in range(5, 8)) ), - NumberRegField(consts.MAX_POWER_FIELD, self.get_addr(0x0, 201), scale=4), + NumberRegField(consts.MAX_POWER_FIELD, self.getaddr(0x0, 201), scale=4.0), ), - NumberRegField(consts.LEN_MULT_FIELD, self.get_addr(0x0, 202), + NumberRegField(consts.LEN_MULT_FIELD, self.getaddr(0x0, 202), *(RegBitField("%s_%d" % (consts.LEN_MULT_FIELD, bit), bit) for bit in range (6, 8)) ), - CableLenField(consts.LENGTH_ASSEMBLY_FIELD, self.get_addr(0x0, 202), + CableLenField(consts.LENGTH_ASSEMBLY_FIELD, self.getaddr(0x0, 202), *(RegBitField("%s_%d" % (consts.LENGTH_ASSEMBLY_FIELD, bit), bit) for bit in range(0, 6)) ), - CodeRegField(consts.CONNECTOR_FIELD, self.get_addr(0x0, 203), self.codes.CONNECTORS), - deps=[consts.LEN_MULT_FIELD] + + CodeRegField(consts.CONNECTOR_FIELD, self.getaddr(0x0, 203), self.codes.CONNECTORS), + CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, self.getaddr(0x0, 86), self.codes.HOST_ELECTRICAL_INTERFACE), + CodeRegField(consts.MEDIA_TYPE_FIELD, self.getaddr(0x0, 85), self.codes.MODULE_MEDIA_TYPE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, self.getaddr(0x0, 87), self.codes.NM_850_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, self.getaddr(0x0, 87), self.codes.SM_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, self.getaddr(0x0, 87), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, self.getaddr(0x0, 87), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, self.getaddr(0x0, 87), self.codes.BASE_T_MEDIA_INTERFACE), + NumberRegField(consts.MEDIA_LANE_COUNT, self.getaddr(0x0, 88), + *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) + ), + NumberRegField(consts.HOST_LANE_COUNT, self.getaddr(0x0, 88), + *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) + ), + NumberRegField(consts.HOST_LANE_ASSIGNMENT_OPTION, self.getaddr(0x0, 89), format="B", size=1), + NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, self.getaddr(0x1, 176), format="B", size=1), + CodeRegField(consts.MEDIA_INTERFACE_TECH, self.getaddr(0x0, 212), self.codes.MEDIA_INTERFACE_TECH), + NumberRegField(consts.HW_MAJOR_REV, self.getaddr(0x1, 130), size=1), + NumberRegField(consts.HW_MINOR_REV, self.getaddr(0x1, 131), size=1), + NumberRegField(consts.CMIS_MAJOR_REVISION, self.getaddr(0x0, 1), + *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) + ), + NumberRegField(consts.CMIS_MINOR_REVISION, self.getaddr(0x0, 1), + *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) + ), + NumberRegField(consts.ACTIVE_FW_MAJOR_REV, self.getaddr(0x0, 39), format="B", size=1), + NumberRegField(consts.ACTIVE_FW_MINOR_REV, self.getaddr(0x0, 40), format="B", size=1), + NumberRegField(consts.INACTIVE_FW_MAJOR_REV, self.getaddr(0x1, 128), format="B", size=1), + NumberRegField(consts.INACTIVE_FW_MINOR_REV, self.getaddr(0x1, 129), format="B", size=1), + + RegGroupField(consts.ACTIVE_APSEL_CODE, + *(NumberRegField("%s%d" % (consts.ACTIVE_APSEL_HOSTLANE, lane) , self.getaddr(0x11, offset), + *(RegBitField("Bit%d" % bit, bit) for bit in range(4, 7))) + for lane, offset in zip(range(1, 9), range(206, 214))) + ) ) self.MODULE_LEVEL_MONITORS = RegGroupField(consts.MODULE_MONITORS_FIELD, - NumberRegField(consts.TEMPERATURE_FIELD, self.get_addr(0x0, 14), size=2, format=">h", scale=256), - NumberRegField(consts.VOLTAGE_FIELD, self.get_addr(0x0, 16), size=2, format=">H", scale=10000), + NumberRegField(consts.TEMPERATURE_FIELD, self.getaddr(0x0, 14), size=2, format=">h", scale=256.0), + NumberRegField(consts.VOLTAGE_FIELD, self.getaddr(0x0, 16), size=2, format=">H", scale=10000.0), + NumberRegField(consts.GRID_SPACING, self.getaddr(0x12, 128), + *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)), ro = False + ), + NumberRegField(consts.LASER_CONFIG_CHANNEL, self.getaddr(0x12, 136), format=">h", size=2, ro=False), + NumberRegField(consts.LASER_CURRENT_FREQ, self.getaddr(0x12, 168), format=">L", size=4, scale = 1000.0), + NumberRegField(consts.TX_CONFIG_POWER, self.getaddr(0x12, 200), format=">h", size=2, scale=100.0, ro=False), + NumberRegField(consts.AUX_MON_TYPE, self.getaddr(0x1, 145), size=1), + NumberRegField(consts.AUX1_MON, self.getaddr(0x0, 18), format=">h", size=2), + NumberRegField(consts.AUX2_MON, self.getaddr(0x0, 20), format=">h", size=2), + NumberRegField(consts.AUX3_MON, self.getaddr(0x0, 22), format=">h", size=2), + NumberRegField(consts.CUSTOM_MON, self.getaddr(0x0, 24), format=">H", size=2), ) self.MODULE_CHAR_ADVT = RegGroupField(consts.MODULE_CHAR_ADVT_FIELD, - NumberRegField(consts.CTRLS_ADVT_FIELD, self.get_addr(0x1, 155), + NumberRegField(consts.CTRLS_ADVT_FIELD, self.getaddr(0x1, 155), RegBitField(consts.TX_DISABLE_SUPPORT_FIELD, 1), size=2, format="