[devices]: DellEMC: Platform 2.0 Api(sfp,eeprom,chassis )for z9264f (#4007)

- Sfp,Eeprom,Chassis(transceiver change event) support added for z9264f Platform 2.0 API
- Added Interrupt handler to SFP change event in dell_z9264f_fpga_ocores.c
- Fixed few indentation and offset issues in sfputil.py for z9264f
This commit is contained in:
rkdevi27 2020-01-23 23:02:34 +05:30 committed by lguohan
parent c6fee49e76
commit c2677a5614
12 changed files with 1596 additions and 62 deletions

View File

@ -10,6 +10,7 @@
#############################################################################
try:
import os.path
from sonic_eeprom import eeprom_tlvinfo
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
@ -18,5 +19,13 @@ except ImportError, e:
class board(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0050/eeprom"
self.eeprom_path = None
for b in (0,1):
f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b)
if os.path.exists(f):
self.eeprom_path = f
break
if self.eeprom_path is None:
return
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -44,6 +44,8 @@ SFP_VOLT_OFFSET = 98
SFP_VOLT_WIDTH = 2
SFP_MODULE_THRESHOLD_OFFSET = 0
SFP_MODULE_THRESHOLD_WIDTH = 56
SFP_CHANNL_MON_OFFSET = 100
SFP_CHANNL_MON_WIDTH = 6
XCVR_DOM_CAPABILITY_OFFSET = 92
XCVR_DOM_CAPABILITY_WIDTH = 1
@ -226,8 +228,8 @@ class SfpUtil(SfpUtilBase):
if (reg_value == ""):
return False
# Mask off 4th bit for presence
mask = (1 << 6)
# Mask off 4th bit for reset
mask = (1 << 4)
# ResetL is active low
reg_value = reg_value & ~mask
@ -347,7 +349,7 @@ class SfpUtil(SfpUtilBase):
]
transceiver_dom_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A')
if port_num in self.qsfp_ports:
if port_num in self.qsfp_ports:
offset = 0
offset_xcvr = 128
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
@ -379,7 +381,7 @@ class SfpUtil(SfpUtilBase):
return transceiver_dom_info_dict
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
else:
return transceiver_dom_info_dict
@ -411,10 +413,22 @@ class SfpUtil(SfpUtilBase):
else:
return transceiver_dom_info_dict
transceiver_dom_info_dict['tx1power'] = 'N/A'
transceiver_dom_info_dict['tx1power'] = 'N/A'
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
else:
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0)
else:
return None
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value']
transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value']
transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value']
transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value']
try:
sysfsfile_eeprom.close()
except IOError:
@ -433,64 +447,66 @@ class SfpUtil(SfpUtilBase):
transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value']
else:
offset = 256
file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
return None
offset = 256
file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
return None
try:
sysfsfile_eeprom = io.open(file_path,"rb",0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfpd_obj = sff8472Dom(None,1)
if sfpd_obj is None:
return None
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET),
SFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
else:
return transceiver_dom_info_dict
try:
sysfsfile_eeprom = io.open(file_path,"rb",0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET),
SFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
else:
return transceiver_dom_info_dict
sfpd_obj = sff8472Dom(None,1)
if sfpd_obj is None:
return None
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET),
SFP_TEMPE_WIDTH)
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_MODULE_THRESHOLD_OFFSET),
SFP_MODULE_THRESHOLD_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
else:
return transceiver_dom_info_dict
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
else:
return transceiver_dom_info_dict
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET),
SFP_VOLT_WIDTH)
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value']
transceiver_dom_info_dict['rx2power'] = 'N/A'
transceiver_dom_info_dict['rx3power'] = 'N/A'
transceiver_dom_info_dict['rx4power'] = 'N/A'
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value']
transceiver_dom_info_dict['tx2bias'] = 'N/A'
transceiver_dom_info_dict['tx3bias'] = 'N/A'
transceiver_dom_info_dict['tx4bias'] = 'N/A'
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value']
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
else:
return transceiver_dom_info_dict
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET),
SFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
else:
return transceiver_dom_info_dict
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value']
transceiver_dom_info_dict['rx2power'] = 'N/A'
transceiver_dom_info_dict['rx3power'] = 'N/A'
transceiver_dom_info_dict['rx4power'] = 'N/A'
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value']
transceiver_dom_info_dict['tx2bias'] = 'N/A'
transceiver_dom_info_dict['tx3bias'] = 'N/A'
transceiver_dom_info_dict['tx4bias'] = 'N/A'
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value']
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
return transceiver_dom_info_dict
return transceiver_dom_info_dict
def get_transceiver_dom_threshold_info_dict(self, port_num):
transceiver_dom_threshold_info_dict = {}
dom_info_dict_keys = ['temphighalarm', 'temphighwarning',

View File

@ -6,6 +6,7 @@ z9264f/scripts/pcisysfs.py usr/bin
z9264f/scripts/qsfp_irq_enable.py usr/bin
z9264f/cfg/z9264f-modules.conf etc/modules-load.d
z9264f/systemd/platform-modules-z9264f.service etc/systemd/system
z9264f/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dellemc_z9264f_c3538-r0
common/platform_reboot usr/share/sonic/device/x86_64-dellemc_z9264f_c3538-r0
common/fw-updater usr/local/bin
common/onie_mode_set usr/local/bin

View File

@ -29,6 +29,10 @@ override_dh_auto_build:
cd $(MOD_SRC_DIR)/$${mod}; \
python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
cd $(MOD_SRC_DIR); \
elif [ $$mod = "z9264f" ]; then \
cd $(MOD_SRC_DIR)/$${mod}; \
python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
cd $(MOD_SRC_DIR); \
fi; \
echo "making man page alias $$mod -> $$mod APIs";\
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
@ -67,6 +71,10 @@ override_dh_clean:
rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \
rm -rf $(MOD_SRC_DIR)/$${mod}/build; \
rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \
elif [ $$mod = "z9264f" ]; then \
rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \
rm -rf $(MOD_SRC_DIR)/$${mod}/build; \
rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \
fi; \
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \
done)

View File

@ -231,6 +231,7 @@ enum {
#define IRQ_LTCH_STS 0x20
#define PRSNT_LTCH_STS 0x10
#define MODABS_STS 0x01
#define PORT_CTRL_OFFSET 0x4000
#define PORT_STS_OFFSET 0x4004
@ -296,6 +297,7 @@ enum {
#define FPGA_MSI_VECTOR_ID_4 4
#define FPGA_MSI_VECTOR_ID_5 5
#define FPGA_MSI_VECTOR_ID_6 6
#define FPGA_MSI_VECTOR_ID_8 8
#define FPGA_MSI_VECTOR_ID_9 9
#define FPGA_MSI_VECTOR_ID_10 10
@ -523,7 +525,7 @@ static ssize_t get_mod_msi(struct device *dev, struct device_attribute *devattr,
int ind = 0, port_status=0, port_irq_status=0;
struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(dev);
PRINT("%s:xcvr_intr_count:%u\n", __FUNCTION__, fpgapci->xcvr_intr_count);
for(ind=0;ind<64;ind++)
for(ind=0;ind<66;ind++)
{
port_status = ioread32(fpga_ctl_addr + PORT_STS_OFFSET + (ind*16));
port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
@ -585,6 +587,28 @@ static irqreturn_t fpgaport_33_64_isr(int irq, void *dev)
return IRQ_HANDLED;
}
static irqreturn_t fpgaport_65_66_isr(int irq, void *dev)
{
struct pci_dev *pdev = dev;
struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&pdev->dev);
int ind = 0, port_status=0, port_irq_status=0;
for(ind=64;ind<66;ind++)
{
port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
if(port_irq_status| (MODABS_STS))
{
PRINT("%s:port:%d, port_status:%#x, port_irq_status:%#x\n", __FUNCTION__, ind, port_status, port_irq_status);
//write on clear
iowrite32( MODABS_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
}
}
fpgapci->xcvr_intr_count++;
PRINT("%s: xcvr_intr_count:%u\n", __FUNCTION__, fpgapci->xcvr_intr_count);
sysfs_notify(&pdev->dev.kobj, NULL, "port_msi");
return IRQ_HANDLED;
}
static void fpgai2c_process(struct fpgalogic_i2c *i2c)
{
struct i2c_msg *msg = i2c->msg;
@ -1122,6 +1146,12 @@ static int register_intr_handler(struct pci_dev *dev, int irq_num_id)
PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
fpgapci->irq_assigned++;
break;
case FPGA_MSI_VECTOR_ID_6:
err = request_irq(dev->irq + irq_num_id, fpgaport_65_66_isr, IRQF_EARLY_RESUME,
FPGA_PCI_NAME, dev);
PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
fpgapci->irq_assigned++;
break;
case FPGA_MSI_VECTOR_ID_8:
err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
FPGA_PCI_NAME, &fpgalogic_i2c[0]);
@ -1180,6 +1210,12 @@ static int register_intr_handler(struct pci_dev *dev, int irq_num_id)
PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
fpgapci->irq_assigned++;
break;
case FPGA_MSI_VECTOR_ID_6:
err = request_irq(dev->irq + irq_num_id, fpgaport_65_66_isr, IRQF_EARLY_RESUME,
FPGA_PCI_NAME, dev);
PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
fpgapci->irq_assigned++;
break;
case FPGA_MSI_VECTOR_ID_8:
err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
FPGA_PCI_NAME, &fpgalogic_i2c[0]);

View File

@ -27,6 +27,7 @@ def pci_set_value(resource, val, offset):
close(fd)
return val
#Enabled interrupt for qsfp and sfp
for port_num in range(PORT_START, PORT_END+1):
port_offset = 0x400c + ((port_num) * 16)
pci_set_value(BASE_RES_PATH, 0x30, port_offset)
pci_set_value(BASE_RES_PATH, 0x31, port_offset)

View File

@ -17,9 +17,9 @@ init_devnum() {
# Attach/Detach syseeprom on CPU board
sys_eeprom() {
case $1 in
"new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-0/$1
"new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1
;;
"delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-0/$1
"delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1
;;
*) echo "z9264f_platform: sys_eeprom : invalid command !"
;;
@ -125,6 +125,20 @@ init_switch_port_led() {
fi
}
install_python_api_package() {
device="/usr/share/sonic/device"
platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform)
rv=$(pip install $device/$platform/sonic_platform-1.0-py2-none-any.whl)
}
remove_python_api_package() {
rv=$(pip show sonic-platform > /dev/null 2>/dev/null)
if [ $? -eq 0 ]; then
rv=$(pip uninstall -y sonic-platform > /dev/null 2>/dev/null)
fi
}
init_devnum
if [ "$1" == "init" ]; then
@ -140,6 +154,7 @@ if [ "$1" == "init" ]; then
switch_board_sfp "new_device"
switch_board_modsel
init_switch_port_led
install_python_api_package
python /usr/bin/qsfp_irq_enable.py
elif [ "$1" == "deinit" ]; then
@ -149,6 +164,7 @@ elif [ "$1" == "deinit" ]; then
switch_board_sfp "delete_device"
modprobe -r i2c-mux-pca954x
modprobe -r i2c-dev
remove_python_api_package
else
echo "z9264f_platform : Invalid option !"
fi

View File

@ -0,0 +1 @@
../s6100/setup.py

View File

@ -0,0 +1,3 @@
__all__ = ["chassis", "sfp", "eeprom"]
from sonic_platform import *

View File

@ -0,0 +1,247 @@
#!/usr/bin/env python
#############################################################################
# DELLEMC Z9264F
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
import os
import select
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.sfp import Sfp
from sonic_platform.eeprom import Eeprom
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Chassis(ChassisBase):
"""
DELLEMC Platform-specific Chassis class
"""
OIR_FD_PATH = "/sys/bus/pci/devices/0000:04:00.0/port_msi"
oir_fd = -1
epoll = -1
_global_port_pres_dict = {}
def __init__(self):
ChassisBase.__init__(self)
# sfp.py will read eeprom contents and retrive the eeprom data.
# We pass the eeprom path from chassis.py
self.PORT_START = 1
self.PORT_END = 66
PORTS_IN_BLOCK = (self.PORT_END + 1)
_sfp_port = range(65, self.PORT_END + 1)
eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
for index in range(self.PORT_START, PORTS_IN_BLOCK):
port_num = index + 1
eeprom_path = eeprom_base.format(port_num)
if index not in _sfp_port:
sfp_node = Sfp(index, 'QSFP', eeprom_path)
else:
sfp_node = Sfp(index, 'SFP', eeprom_path)
self._sfp_list.append(sfp_node)
self._eeprom = Eeprom()
for port_num in range(self.PORT_START, (self.PORT_END + 1)):
presence = self.get_sfp(port_num).get_presence()
if presence:
self._global_port_pres_dict[port_num] = '1'
else:
self._global_port_pres_dict[port_num] = '0'
def __del__(self):
if self.oir_fd != -1:
self.epoll.unregister(self.oir_fd.fileno())
self.epoll.close()
self.oir_fd.close()
def _get_register(self, reg_file):
retval = 'ERR'
if (not os.path.isfile(reg_file)):
print reg_file, 'not found !'
return retval
try:
with os.fdopen(os.open(reg_file, os.O_RDONLY)) as fd:
retval = fd.read()
except:
pass
retval = retval.rstrip('\r\n')
retval = retval.lstrip(" ")
return retval
def _check_interrupts(self, port_dict):
retval = 0
is_port_dict_updated = False
for port_num in range(self.PORT_START, (self.PORT_END + 1)):
sfp = self.get_sfp(port_num)
presence = sfp.get_presence()
if(presence and (self._global_port_pres_dict[port_num] == '0')):
is_port_dict_updated = True
self._global_port_pres_dict[port_num] = '1'
port_dict[port_num] = '1'
elif(not presence and (self._global_port_pres_dict[port_num] == '1')):
is_port_dict_updated = True
self._global_port_pres_dict[port_num] = '0'
port_dict[port_num] = '0'
return retval, is_port_dict_updated
def get_change_event(self, timeout=0):
"""
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
"""
port_dict = {}
change_dict = {}
change_dict['sfp'] = port_dict
try:
# We get notified when there is a MSI interrupt (vector 4/5)CVR
# Open the sysfs file and register the epoll object
self.oir_fd = os.fdopen(os.open(self.OIR_FD_PATH, os.O_RDONLY))
if self.oir_fd != -1:
# Do a dummy read before epoll register
self.oir_fd.read()
self.epoll = select.epoll()
self.epoll.register(
self.oir_fd.fileno(), select.EPOLLIN & select.EPOLLET)
else:
print("get_transceiver_change_event : unable to create fd")
return False, change_dict
# Check for missed interrupts by invoking self._check_interrupts
# which will update the port_dict.
while True:
interrupt_count_start = self._get_register(self.OIR_FD_PATH)
retval, is_port_dict_updated = self._check_interrupts(port_dict)
if ((retval == 0) and (is_port_dict_updated is True)):
return True, change_dict
interrupt_count_end = self._get_register(self.OIR_FD_PATH)
if (interrupt_count_start == 'ERR' or
interrupt_count_end == 'ERR'):
print("get_transceiver_change_event : \
unable to retrive interrupt count")
break
# check_interrupts() itself may take upto 100s of msecs.
# We detect a missed interrupt based on the count
if interrupt_count_start == interrupt_count_end:
break
# Block until an xcvr is inserted or removed with timeout = -1
events = self.epoll.poll(
timeout=timeout if timeout != 0 else -1)
if events:
# check interrupts and return the change_dict
retval, is_port_dict_updated = \
self._check_interrupts(port_dict)
if (retval != 0):
return False, change_dict
return True, change_dict
except:
return False, change_dict
finally:
if self.oir_fd != -1:
self.epoll.unregister(self.oir_fd.fileno())
self.epoll.close()
self.oir_fd.close()
self.oir_fd = -1
self.epoll = -1
return False, change_dict
def get_sfp(self, index):
"""
Retrieves sfp represented by (1-based) index <index>
Args:
index: An integer, the index (1-based) of the sfp to retrieve.
The index should be the sequence of a physical port in a chassis,
starting from 1.
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
Returns:
An object dervied from SfpBase representing the specified sfp
"""
sfp = None
try:
# The index will start from 1
sfp = self._sfp_list[index-1]
except IndexError:
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)))
return sfp
def get_name(self):
"""
Retrieves the name of the chassis
Returns:
string: The name of the chassis
"""
return self._eeprom.modelstr()
def get_presence(self):
"""
Retrieves the presence of the chassis
Returns:
bool: True if chassis is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the chassis
Returns:
string: Model/part number of chassis
"""
return self._eeprom.part_number_str()
def get_serial(self):
"""
Retrieves the serial number of the chassis (Service tag)
Returns:
string: Serial number of chassis
"""
return self._eeprom.serial_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
return self._eeprom.system_eeprom_info()

View File

@ -0,0 +1,140 @@
#!/usr/bin/env python
#############################################################################
# DellEmc Z9264F
#
# Platform and model specific eeprom subclass, inherits from the base class,
# and provides the followings:
# - the eeprom format definition
# - specific encoder/decoder if there is special need
#############################################################################
try:
import os.path
from sonic_eeprom import eeprom_tlvinfo
import binascii
except ImportError, e:
raise ImportError(str(e) + "- required module not found")
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
self.eeprom_path = None
for b in (0, 1):
f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b)
if os.path.exists(f):
self.eeprom_path = f
break
if self.eeprom_path is None:
return
super(Eeprom, self).__init__(self.eeprom_path, 0, '', True)
self.eeprom_tlv_dict = dict()
try:
self.eeprom_data = self.read_eeprom()
except:
self.eeprom_data = "N/A"
raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return
total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10])
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break
tlv = eeprom[tlv_index:tlv_index + 2
+ ord(eeprom[tlv_index + 1])]
code = "0x%02X" % (ord(tlv[0]))
if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT:
value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) |
(ord(tlv[4]) << 8) | ord(tlv[5]))
value += str(tlv[6:6 + ord(tlv[1])])
else:
name, value = self.decoder(None, tlv)
self.eeprom_tlv_dict[code] = value
if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32:
break
tlv_index += ord(eeprom[tlv_index+1]) + 2
def serial_number_str(self):
"""
Returns the serial number
"""
(is_valid, results) = self.get_tlv_field(
self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
if not is_valid:
return "N/A"
return results[2]
def base_mac_addr(self):
"""
Returns the base mac address found in the system EEPROM
"""
(is_valid, t) = self.get_tlv_field(
self.eeprom_data, self._TLV_CODE_MAC_BASE)
if not is_valid or t[1] != 6:
return super(TlvInfoDecoder, self).switchaddrstr(e)
return ":".join([binascii.b2a_hex(T) for T in t[2]])
def modelstr(self):
"""
Returns the Model name
"""
(is_valid, results) = self.get_tlv_field(
self.eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
return results[2]
def part_number_str(self):
"""
Returns the part number
"""
(is_valid, results) = self.get_tlv_field(
self.eeprom_data, self._TLV_CODE_PART_NUMBER)
if not is_valid:
return "N/A"
return results[2]
def serial_str(self):
"""
Returns the servicetag number
"""
(is_valid, results) = self.get_tlv_field(
self.eeprom_data, self._TLV_CODE_SERVICE_TAG)
if not is_valid:
return "N/A"
return results[2]
def revision_str(self):
"""
Returns the device revision
"""
(is_valid, results) = self.get_tlv_field(
self.eeprom_data, self._TLV_CODE_DEVICE_VERSION)
if not is_valid:
return "N/A"
return results[2]
def system_eeprom_info(self):
"""
Returns a dictionary, where keys are the type code defined in
ONIE EEPROM format and values are their corresponding values
found in the system EEPROM.
"""
return self.eeprom_tlv_dict

File diff suppressed because it is too large Load Diff