Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
923 changes: 923 additions & 0 deletions sonic_platform_base/sonic_xcvr/api/public/c_cmis.py

Large diffs are not rendered by default.

1,436 changes: 1,409 additions & 27 deletions sonic_platform_base/sonic_xcvr/api/public/cmis.py

Large diffs are not rendered by default.

480 changes: 480 additions & 0 deletions sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py

Large diffs are not rendered by default.

180 changes: 180 additions & 0 deletions sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py
Original file line number Diff line number Diff line change
@@ -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
119 changes: 119 additions & 0 deletions sonic_platform_base/sonic_xcvr/codes/public/cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading