Skip to content

Commit

Permalink
[sfp-refactoring] Initial support for CMIS application initialization (
Browse files Browse the repository at this point in the history
  • Loading branch information
ds952811 authored Dec 7, 2021
1 parent 10ae99a commit 94919de
Show file tree
Hide file tree
Showing 6 changed files with 601 additions and 7 deletions.
204 changes: 201 additions & 3 deletions sonic_platform_base/sonic_xcvr/api/public/cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from ..xcvr_api import XcvrApi

import logging
from ...codes.public.cmis import CmisCodes
from ...codes.public.sff8024 import Sff8024
from ...fields import consts
from ..xcvr_api import XcvrApi
from .cmisCDB import CmisCdbApi
Expand Down Expand Up @@ -50,6 +52,12 @@ def get_module_type(self):
'''
return self.xcvr_eeprom.read(consts.ID_FIELD)

def get_module_type_abbreviation(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_ABBRV_FIELD)

def get_connector_type(self):
'''
This function returns module connector. Table 4-3 in SFF-8024 Rev4.6
Expand Down Expand Up @@ -134,10 +142,10 @@ def get_transceiver_info(self):
"nominal_bit_rate": 0, # Not supported
"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",
"vendor_oui": admin_info[consts.VENDOR_OUI_FIELD]
}
appl_advt = self.get_application_advertisement()
xcvr_info['application_advertisement'] = str(appl_advt) if len(appl_advt) > 0 else '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()
Expand Down Expand Up @@ -876,6 +884,24 @@ def reset_module(self, reset = False):
else:
return True

def reset(self):
"""
Reset SFP and return all user module settings to their default state.
Returns:
A boolean, True if successful, False if not
"""
if self.reset_module(True):
# minimum waiting time for the TWI to be functional again
time.sleep(2)
# buffer time
for retries in range(5):
state = self.get_module_state()
if state in ['ModuleReady', 'ModuleLowPwr']:
return True
time.sleep(1)
return False

def get_lpmode(self):
'''
Retrieves Low power module status
Expand Down Expand Up @@ -1745,4 +1771,176 @@ def get_transceiver_loopback(self):
for lane in range(1, self.NUM_CHANNELS+1):
trans_loopback['host_input_loopback_lane%d' % lane] = 'N/A'
return trans_loopback

def set_datapath_init(self, channel):
"""
Put the CMIS datapath into the initialized state
Args:
channel:
Integer, a bitmask of the lanes on the host side
e.g. 0x5 for lane 0 and lane 2.
Returns:
Boolean, true if success otherwise false
"""
cmis_major = self.xcvr_eeprom.read(consts.CMIS_MAJOR_REVISION)
data = self.xcvr_eeprom.read(consts.DATAPATH_DEINIT_FIELD)
for lane in range(self.NUM_CHANNELS):
if ((1 << lane) & channel) == 0:
continue
if cmis_major >= 4: # CMIS v4 onwards
data &= ~(1 << lane)
else: # CMIS v3
data |= (1 << lane)
self.xcvr_eeprom.write(consts.DATAPATH_DEINIT_FIELD, data)

def set_datapath_deinit(self, channel):
"""
Put the CMIS datapath into the de-initialized state
Args:
channel:
Integer, a bitmask of the lanes on the host side
e.g. 0x5 for lane 0 and lane 2.
Returns:
Boolean, true if success otherwise false
"""
cmis_major = self.xcvr_eeprom.read(consts.CMIS_MAJOR_REVISION)
data = self.xcvr_eeprom.read(consts.DATAPATH_DEINIT_FIELD)
for lane in range(self.NUM_CHANNELS):
if ((1 << lane) & channel) == 0:
continue
if cmis_major >= 4: # CMIS v4 onwards
data |= (1 << lane)
else: # CMIS v3
data &= ~(1 << lane)
self.xcvr_eeprom.write(consts.DATAPATH_DEINIT_FIELD, data)

def get_application_advertisement(self):
"""
Get the application advertisement of the CMIS transceiver
Returns:
Dictionary, the application advertisement
"""
map = {
Sff8024.MODULE_MEDIA_TYPE[1]: consts.MODULE_MEDIA_INTERFACE_850NM,
Sff8024.MODULE_MEDIA_TYPE[2]: consts.MODULE_MEDIA_INTERFACE_SM,
Sff8024.MODULE_MEDIA_TYPE[3]: consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER,
Sff8024.MODULE_MEDIA_TYPE[4]: consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE,
Sff8024.MODULE_MEDIA_TYPE[5]: consts.MODULE_MEDIA_INTERFACE_BASE_T
}

ret = {}
dic = self.xcvr_eeprom.read(consts.APPLS_ADVT_FIELD)
for app in range(1, 16):
buf = {}

key = "{}_{}".format(consts.HOST_ELECTRICAL_INTERFACE, app)
val = dic.get(key)
if val in [None, 'Unknown', 'Undefined']:
break
buf['host_electrical_interface_id'] = val

prefix = map.get(self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD))
if prefix is None:
break
key = "{}_{}".format(prefix, app)
val = dic.get(key)
if val in [None, 'Unknown', 'Undefined']:
break
buf['module_media_interface_id'] = val

key = "{}_{}".format(consts.MEDIA_LANE_COUNT, app)
val = dic.get(key)
if val is None:
break
buf['media_lane_count'] = val

key = "{}_{}".format(consts.HOST_LANE_COUNT, app)
val = dic.get(key)
if val is None:
break
buf['host_lane_count'] = val

key = "{}_{}".format(consts.HOST_LANE_ASSIGNMENT_OPTION, app)
val = dic.get(key)
if val is None:
break
buf['host_lane_assignment_options'] = val

ret[app] = buf
return ret

def get_application(self, lane):
"""
Get the CMIS selected application code of a host lane
Args:
lane:
Integer, the zero-based lane id on the host side
Returns:
Integer, the transceiver-specific application code
"""
appl = 0
if lane in range(self.NUM_CHANNELS) and not self.is_flat_memory():
name = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1)
appl = self.xcvr_eeprom.read(name) >> 4

return (appl & 0xf)

def set_application(self, channel, appl_code):
"""
Update the selected application code to the specified lanes on the host side
Args:
channel:
Integer, a bitmask of the lanes on the host side
e.g. 0x5 for lane 0 and lane 2.
appl_code:
Integer, the desired application code
Returns:
Boolean, true if success otherwise false
"""
# Update the application selection
lane_first = -1
for lane in range(self.NUM_CHANNELS):
if ((1 << lane) & channel) == 0:
continue
if lane_first < 0:
lane_first = lane
addr = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1)
data = (appl_code << 4) | (lane_first << 1)
self.xcvr_eeprom.write(addr, data)

# Apply DataPathInit
return self.xcvr_eeprom.write("%s_%d" % (consts.STAGED_CTRL_APPLY_DPINIT_FIELD, 0), channel)

def get_error_description(self):
dp_state = self.get_datapath_state()
conf_state = self.get_config_datapath_hostlane_status()
for lane in range(self.NUM_CHANNELS):
name = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1)
appl = self.xcvr_eeprom.read(name)
if (appl is None) or ((appl >> 4) == 0):
continue

name = "DP{}State".format(lane + 1)
if dp_state[name] != CmisCodes.DATAPATH_STATE[4]:
return dp_state[name]

name = "ConfigStatusLane{}".format(lane + 1)
if conf_state[name] != CmisCodes.CONFIG_STATUS[1]:
return conf_state[name]

state = self.get_module_state()
if state != CmisCodes.MODULE_STATE[3]:
return state

return None

# TODO: other XcvrApi methods
2 changes: 1 addition & 1 deletion sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ 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
#assert self.cdb_instance_supported != 0

def cdb1_chkflags(self):
'''
Expand Down
7 changes: 7 additions & 0 deletions sonic_platform_base/sonic_xcvr/fields/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@
TRANS_CONFIG_FIELD = "TransceiverConfig"
MODULE_LEVEL_CONTROL = "ModuleControl"

APPLS_ADVT_FIELD = "Applications Advertisement"
CTRLS_ADVT_FIELD = "Supported Controls Advertisement"
FLAGS_ADVT_FIELD = "Supported Flags Advertisement"
PAGE_SUPPORT_ADVT_FIELD = "Supported Pages Advertisement"
Expand All @@ -278,13 +279,19 @@
LANE_MON_ADVT_FIELD = "Supported Lane Monitor Advertisement"
LANE_DATAPATH_CTRL_FIELD = "Lane Control and Data Path Control"
LANE_DATAPATH_STATUS_FIELD = "Lane Status and Data Path Status"
DATAPATH_DEINIT_FIELD = "Data Path Deinit"
LEN_MULT_FIELD = "LengthMultiplier"
MAX_POWER_FIELD = "MaxPower"
MGMT_CHAR_FIELD = "Management Characteristics"
MGMT_CHAR_MISC_FIELD = "Management Characteristics (Misc)"

MODULE_CHAR_ADVT_FIELD = "Module Characteristics Advertising"

STAGED_CTRL_FIELD = "Staged Control Set"
STAGED_CTRL_APPLY_DPINIT_FIELD = "Staged Control Set Apply DataPathInit"
STAGED_CTRL_APPLY_IMMEDIATE_FIELD = "Staged Control Set Apply Immediate"
STAGED_CTRL_APSEL_FIELD = "Staged Control Set ApSel"

# C-CMIS

# Module configuration support fields
Expand Down
Loading

0 comments on commit 94919de

Please sign in to comment.