Skip to content

Commit

Permalink
400zr initial support (sonic-net#228)
Browse files Browse the repository at this point in the history
Co-authored-by: Prince George <prgeor@microsoft.com>
  • Loading branch information
qinchuanares and prgeor committed Nov 12, 2021
1 parent ef55364 commit c8eceec
Show file tree
Hide file tree
Showing 18 changed files with 6,384 additions and 133 deletions.
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

0 comments on commit c8eceec

Please sign in to comment.