[Centec][arm64] support new board E530-48s4x and E530-24x2q (#7189)
1. support new board E530-48s4x E530-24x2q 2. optimize platform driver for Centec TsingMa board Co-authored-by: shi lei <shil@centecnetworks.com>
This commit is contained in:
parent
78b45085e9
commit
be4cf09b5d
@ -1,27 +1,27 @@
|
||||
# name lanes alias speed
|
||||
Ethernet1 0 eth-0-1 10000
|
||||
Ethernet2 1 eth-0-2 10000
|
||||
Ethernet3 2 eth-0-3 10000
|
||||
Ethernet4 3 eth-0-4 10000
|
||||
Ethernet5 8 eth-0-5 10000
|
||||
Ethernet6 9 eth-0-6 10000
|
||||
Ethernet7 10 eth-0-7 10000
|
||||
Ethernet8 11 eth-0-8 10000
|
||||
Ethernet9 20 eth-0-9 10000
|
||||
Ethernet10 21 eth-0-10 10000
|
||||
Ethernet11 22 eth-0-11 10000
|
||||
Ethernet12 23 eth-0-12 10000
|
||||
Ethernet13 12 eth-0-13 10000
|
||||
Ethernet14 13 eth-0-14 10000
|
||||
Ethernet15 14 eth-0-15 10000
|
||||
Ethernet16 15 eth-0-16 10000
|
||||
Ethernet17 24 eth-0-17 10000
|
||||
Ethernet18 25 eth-0-18 10000
|
||||
Ethernet19 26 eth-0-19 10000
|
||||
Ethernet20 27 eth-0-20 10000
|
||||
Ethernet21 28 eth-0-21 10000
|
||||
Ethernet22 29 eth-0-22 10000
|
||||
Ethernet23 30 eth-0-23 10000
|
||||
Ethernet24 31 eth-0-24 10000
|
||||
Ethernet25 61,60,63,62 eth-0-25 100000
|
||||
Ethernet26 45,44,47,46 eth-0-26 100000
|
||||
# name lanes alias index speed fec
|
||||
Ethernet0 0 eth-0-1 0 10000 none
|
||||
Ethernet1 1 eth-0-2 1 10000 none
|
||||
Ethernet2 2 eth-0-3 2 10000 none
|
||||
Ethernet3 3 eth-0-4 3 10000 none
|
||||
Ethernet4 8 eth-0-5 4 10000 none
|
||||
Ethernet5 9 eth-0-6 5 10000 none
|
||||
Ethernet6 10 eth-0-7 6 10000 none
|
||||
Ethernet7 11 eth-0-8 7 10000 none
|
||||
Ethernet8 20 eth-0-9 8 10000 none
|
||||
Ethernet9 21 eth-0-10 9 10000 none
|
||||
Ethernet10 22 eth-0-11 10 10000 none
|
||||
Ethernet11 23 eth-0-12 11 10000 none
|
||||
Ethernet12 12 eth-0-13 12 10000 none
|
||||
Ethernet13 13 eth-0-14 13 10000 none
|
||||
Ethernet14 14 eth-0-15 14 10000 none
|
||||
Ethernet15 15 eth-0-16 15 10000 none
|
||||
Ethernet16 24 eth-0-17 16 10000 none
|
||||
Ethernet17 25 eth-0-18 17 10000 none
|
||||
Ethernet18 26 eth-0-19 18 10000 none
|
||||
Ethernet19 27 eth-0-20 19 10000 none
|
||||
Ethernet20 28 eth-0-21 20 10000 none
|
||||
Ethernet21 29 eth-0-22 21 10000 none
|
||||
Ethernet22 30 eth-0-23 22 10000 none
|
||||
Ethernet23 31 eth-0-24 23 10000 none
|
||||
Ethernet24 61,60,63,62 eth-0-25 24 100000 none
|
||||
Ethernet25 45,44,47,46 eth-0-26 25 100000 none
|
||||
|
@ -1 +1,12 @@
|
||||
# Configuration file generated by pwmconfig, changes will be lost
|
||||
INTERVAL=10
|
||||
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
|
||||
DEVNAME=hwmon1=ctc5236fan
|
||||
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input
|
||||
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input
|
||||
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30
|
||||
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90
|
||||
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12
|
||||
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
|
||||
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
|
||||
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18
|
||||
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"chassis": {
|
||||
"E530-24x2c": {
|
||||
"component": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
device/centec/arm64-centec_e530_24x2c-r0/platform_reboot
Executable file
11
device/centec/arm64-centec_e530_24x2c-r0/platform_reboot
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
|
||||
def main():
|
||||
# reboot the system
|
||||
os.system('echo 502 > /sys/class/gpio/export')
|
||||
os.system('echo out > /sys/class/gpio/gpio502/direction')
|
||||
os.system('echo 1 > /sys/class/gpio/gpio502/value')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec E550-24X8Y2C
|
||||
#
|
||||
@ -10,7 +12,7 @@
|
||||
try:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# led_control.py
|
||||
#
|
||||
@ -5,37 +6,110 @@
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_led.led_control_base import LedControlBase
|
||||
import os
|
||||
import re
|
||||
import syslog
|
||||
from socket import *
|
||||
from select import *
|
||||
import collections
|
||||
from sonic_led.led_control_base import LedControlBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + " - required module not found")
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
def DBG_PRINT(str):
|
||||
syslog.openlog("centec-led")
|
||||
syslog.syslog(syslog.LOG_INFO, str)
|
||||
syslog.closelog()
|
||||
|
||||
|
||||
class LedControl(LedControlBase):
|
||||
"""Platform specific LED control class"""
|
||||
|
||||
# Constructor
|
||||
def __init__(self):
|
||||
|
||||
self.mac_to_led = {
|
||||
0: 1,
|
||||
1: 2,
|
||||
2: 3,
|
||||
3: 4,
|
||||
8: 5,
|
||||
9: 6,
|
||||
10: 7,
|
||||
11: 8,
|
||||
20: 9,
|
||||
21:10,
|
||||
22:11,
|
||||
23:12,
|
||||
12:13,
|
||||
13:14,
|
||||
14:15,
|
||||
15:16,
|
||||
24:17,
|
||||
25:18,
|
||||
26:19,
|
||||
27:20,
|
||||
28:21,
|
||||
29:22,
|
||||
30:23,
|
||||
31:24,
|
||||
61:-1,
|
||||
60:25,
|
||||
63:-1,
|
||||
62:-1,
|
||||
45:-1,
|
||||
44:26,
|
||||
47:-1,
|
||||
46:-1,
|
||||
}
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
raise
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"])
|
||||
try:
|
||||
f = open(port_config_file)
|
||||
except:
|
||||
raise
|
||||
for line in f:
|
||||
line.strip()
|
||||
if re.search('^#', line) is not None:
|
||||
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
|
||||
break
|
||||
f.close()
|
||||
f = open(port_config_file)
|
||||
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
|
||||
for line in f if re.search('^#', line) is None]
|
||||
f.close()
|
||||
|
||||
self.LED_MODE_UP = [11, 11]
|
||||
self.LED_MODE_DOWN = [7, 7]
|
||||
self.f_led = "/sys/class/leds/{}/brightness"
|
||||
self._initDefaultConfig()
|
||||
|
||||
# Helper method to map SONiC port name to index
|
||||
def _port_name_to_index(self, port_name):
|
||||
# Strip "Ethernet" off port name
|
||||
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
|
||||
return -1
|
||||
|
||||
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
|
||||
return port_idx
|
||||
for port_cfg in self._port_cfgs:
|
||||
if port_name == port_cfg.name:
|
||||
macs = [int(x) for x in (port_cfg.lanes.split(','))]
|
||||
led = self.mac_to_led[min(macs)]
|
||||
if led < 0:
|
||||
return None
|
||||
return led
|
||||
return None
|
||||
|
||||
def _port_state_to_mode(self, port_idx, state):
|
||||
if state == "up":
|
||||
return self.LED_MODE_UP[0] if (port_idx < 25) else self.LED_MODE_UP[1]
|
||||
return self.LED_MODE_UP[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_UP[0]
|
||||
else:
|
||||
return self.LED_MODE_DOWN[0] if (port_idx < 25) else self.LED_MODE_DOWN[1]
|
||||
return self.LED_MODE_DOWN[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_DOWN[0]
|
||||
|
||||
def _port_led_mode_update(self, port_idx, ledMode):
|
||||
with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file:
|
||||
@ -57,11 +131,15 @@ class LedControl(LedControlBase):
|
||||
shouldInit = (int(led_file.read()) == 0)
|
||||
|
||||
if shouldInit == True:
|
||||
for idx in range(1, 27):
|
||||
defmode = self._port_state_to_mode(idx, "down")
|
||||
with open(self.f_led.format("port{}".format(idx)), 'w') as led_file:
|
||||
for port_cfg in self._port_cfgs:
|
||||
macs = [int(x) for x in (port_cfg.lanes.split(','))]
|
||||
led = self.mac_to_led[min(macs)]
|
||||
if led < 0:
|
||||
continue
|
||||
defmode = self._port_state_to_mode(led, "down")
|
||||
with open(self.f_led.format("port{}".format(led)), 'w') as led_file:
|
||||
led_file.write(str(defmode))
|
||||
DBG_PRINT("init port{} led to mode={}".format(idx, defmode))
|
||||
DBG_PRINT("init port{} led to mode={}".format(led, defmode))
|
||||
|
||||
def _initDefaultConfig(self):
|
||||
DBG_PRINT("start init led")
|
||||
@ -72,9 +150,10 @@ class LedControl(LedControlBase):
|
||||
DBG_PRINT("init led done")
|
||||
|
||||
# Concrete implementation of port_link_state_change() method
|
||||
|
||||
def port_link_state_change(self, portname, state):
|
||||
port_idx = self._port_name_to_index(portname)
|
||||
if port_idx is None:
|
||||
return
|
||||
ledMode = self._port_state_to_mode(port_idx, state)
|
||||
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
|
||||
saveMode = int(led_file.read())
|
||||
@ -84,13 +163,3 @@ class LedControl(LedControlBase):
|
||||
|
||||
self._port_led_mode_update(port_idx, ledMode)
|
||||
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
|
||||
|
||||
# Constructor
|
||||
|
||||
def __init__(self):
|
||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||
self.LED_MODE_UP = [11, 11]
|
||||
self.LED_MODE_DOWN = [7, 7]
|
||||
|
||||
self.f_led = "/sys/class/leds/{}/brightness"
|
||||
self._initDefaultConfig()
|
||||
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec
|
||||
#
|
||||
@ -9,8 +11,7 @@
|
||||
try:
|
||||
from sonic_psu.psu_base import PsuBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
class PsuUtil(PsuBase):
|
||||
"""Platform-specific PSUutil class"""
|
||||
|
@ -1,28 +1,117 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# sfputil.py
|
||||
#
|
||||
# Platform-specific SFP transceiver interface for SONiC
|
||||
#
|
||||
|
||||
try:
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
from socket import *
|
||||
from select import *
|
||||
import collections
|
||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % str(e))
|
||||
|
||||
|
||||
def DBG_PRINT(str):
|
||||
print(str + "\n")
|
||||
|
||||
|
||||
SFP_STATUS_INSERTED = '1'
|
||||
SFP_STATUS_REMOVED = '0'
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class SfpUtil(SfpUtilBase):
|
||||
"""Platform-specific SfpUtil class"""
|
||||
|
||||
def __init__(self):
|
||||
self.mac_to_sfp = {
|
||||
0: 1,
|
||||
1: 2,
|
||||
2: 3,
|
||||
3: 4,
|
||||
8: 5,
|
||||
9: 6,
|
||||
10: 7,
|
||||
11: 8,
|
||||
20: 9,
|
||||
21:10,
|
||||
22:11,
|
||||
23:12,
|
||||
12:13,
|
||||
13:14,
|
||||
14:15,
|
||||
15:16,
|
||||
24:17,
|
||||
25:18,
|
||||
26:19,
|
||||
27:20,
|
||||
28:21,
|
||||
29:22,
|
||||
30:23,
|
||||
31:24,
|
||||
61:25,
|
||||
60:25,
|
||||
63:25,
|
||||
62:25,
|
||||
45:26,
|
||||
44:26,
|
||||
47:26,
|
||||
46:26,
|
||||
}
|
||||
self.logical = []
|
||||
self.physical_to_logical = {}
|
||||
self.logical_to_physical = {}
|
||||
self.logical_to_asic = {}
|
||||
self.data = {'valid':0, 'last':0}
|
||||
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
|
||||
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
raise
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"])
|
||||
try:
|
||||
f = open(port_config_file)
|
||||
except:
|
||||
raise
|
||||
for line in f:
|
||||
line.strip()
|
||||
if re.search('^#', line) is not None:
|
||||
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
|
||||
break
|
||||
f.close()
|
||||
f = open(port_config_file)
|
||||
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
|
||||
for line in f if re.search('^#', line) is None]
|
||||
f.close()
|
||||
|
||||
self.PORT_START = 256
|
||||
self.PORT_END = 0
|
||||
for port_cfg in self._port_cfgs:
|
||||
if int(port_cfg.index) <= self.PORT_START:
|
||||
self.PORT_START = int(port_cfg.index)
|
||||
elif int(port_cfg.index) >= self.PORT_END:
|
||||
self.PORT_END = int(port_cfg.index)
|
||||
|
||||
self.eeprom_mapping = {}
|
||||
self.presence = {}
|
||||
for port_cfg in self._port_cfgs:
|
||||
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
|
||||
if sfp_idx > 0:
|
||||
self.eeprom_mapping[int(port_cfg.index)] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(sfp_idx)
|
||||
self.logical.append(port_cfg.name)
|
||||
else:
|
||||
self.eeprom_mapping[int(port_cfg.index)] = None
|
||||
self.presence[int(port_cfg.index)] = False
|
||||
|
||||
SfpUtilBase.__init__(self)
|
||||
|
||||
@property
|
||||
def port_start(self):
|
||||
return self.PORT_START
|
||||
@ -33,11 +122,20 @@ class SfpUtil(SfpUtilBase):
|
||||
|
||||
@property
|
||||
def sfp_base(self):
|
||||
return self.SFP_BASE
|
||||
return self.PORT_START
|
||||
|
||||
@property
|
||||
def qsfp_ports(self):
|
||||
return list(range(25, self.PORTS_IN_BLOCK + 1))
|
||||
start = 256
|
||||
end = 0
|
||||
for port_cfg in self._port_cfgs:
|
||||
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
|
||||
if sfp_idx == 25 or sfp_idx == 26:
|
||||
if int(port_cfg.index) <= start:
|
||||
start = int(port_cfg.index)
|
||||
elif int(port_cfg.index) >= end:
|
||||
end = int(port_cfg.index)
|
||||
return range(start, end + 1)
|
||||
|
||||
@property
|
||||
def port_to_eeprom_mapping(self):
|
||||
@ -46,93 +144,32 @@ class SfpUtil(SfpUtilBase):
|
||||
def is_logical_port(self, port_name):
|
||||
return True
|
||||
|
||||
def get_eeprom_data(self, port):
|
||||
ret = None
|
||||
port_num = self.get_logical_to_physical(port)[0]
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return ret
|
||||
if port_num < self.sfp_base:
|
||||
return ret
|
||||
try:
|
||||
with open(self.eeprom_mapping[port_num], 'r') as eeprom_file:
|
||||
ret = eeprom_file.read()
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
|
||||
return ret
|
||||
|
||||
# todo
|
||||
# def _get_port_eeprom_path(self, port_num, devid):
|
||||
# pass
|
||||
|
||||
def __init__(self):
|
||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||
self.PORT_START = 1
|
||||
self.PORT_END = 26
|
||||
self.SFP_BASE = 1
|
||||
self.PORTS_IN_BLOCK = 26
|
||||
self.logical = []
|
||||
self.physical_to_logical = {}
|
||||
self.logical_to_physical = {}
|
||||
|
||||
self.eeprom_mapping = {}
|
||||
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
|
||||
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
|
||||
for x in range(self.port_start, self.sfp_base):
|
||||
self.eeprom_mapping[x] = None
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(
|
||||
x - self.sfp_base + 1)
|
||||
self.presence = {}
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.presence[x] = False
|
||||
|
||||
SfpUtilBase.__init__(self)
|
||||
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.logical.append('Ethernet' + str(x))
|
||||
|
||||
def get_presence(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
if port_num < self.sfp_base:
|
||||
return False
|
||||
try:
|
||||
with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file:
|
||||
return 1 == int(sfp_file.read())
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
|
||||
for port_cfg in self._port_cfgs:
|
||||
if int(port_cfg.index) == port_num:
|
||||
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
|
||||
if sfp_idx >= 0:
|
||||
try:
|
||||
with open(self.f_sfp_present.format(sfp_idx), 'r') as sfp_file:
|
||||
return 1 == int(sfp_file.read())
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
return False
|
||||
|
||||
def get_low_power_mode(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def set_low_power_mode(self, port_num, lpmode):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def reset(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def read_porttab_mappings(self, porttabfile):
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.logical_to_physical['Ethernet' + str(x)] = [x]
|
||||
self.physical_to_logical[x] = ['Ethernet' + str(x)]
|
||||
|
||||
data = {'valid': 0, 'last': 0}
|
||||
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
|
||||
for port_cfg in self._port_cfgs:
|
||||
self.logical_to_physical[port_cfg.name] = [int(port_cfg.index)]
|
||||
self.logical_to_asic[port_cfg.name] = 0
|
||||
self.physical_to_logical[int(port_cfg.index)] = [port_cfg.name]
|
||||
|
||||
def get_transceiver_change_event(self, timeout=2000):
|
||||
now = time.time()
|
||||
@ -140,19 +177,19 @@ class SfpUtil(SfpUtilBase):
|
||||
|
||||
if timeout < 1000:
|
||||
timeout = 1000
|
||||
timeout = (timeout) / float(1000) # Convert to secs
|
||||
timeout = (timeout) / float(1000) # Convert to secs
|
||||
|
||||
if now < (self.data['last'] + timeout) and self.data['valid']:
|
||||
return True, {}
|
||||
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
presence = self.get_presence(x)
|
||||
if presence != self.presence[x]:
|
||||
self.presence[x] = presence
|
||||
for port_cfg in self._port_cfgs:
|
||||
presence = self.get_presence(int(port_cfg.index))
|
||||
if presence != self.presence[int(port_cfg.index)]:
|
||||
self.presence[int(port_cfg.index)] = presence
|
||||
if presence:
|
||||
port_dict[x] = SFP_STATUS_INSERTED
|
||||
port_dict[int(port_cfg.index)] = SFP_STATUS_INSERTED
|
||||
else:
|
||||
port_dict[x] = SFP_STATUS_REMOVED
|
||||
port_dict[int(port_cfg.index)] = SFP_STATUS_REMOVED
|
||||
|
||||
if bool(port_dict):
|
||||
self.data['last'] = now
|
||||
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
{# Default values which will be used if no actual configura available #}
|
||||
{% set default_cable = '40m' %}
|
||||
{% set default_ports_num = 54 -%}
|
||||
|
||||
{# Port configuration to cable length look-up table #}
|
||||
{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
|
||||
{# Roles described in the minigraph #}
|
||||
{% set ports2cable = {
|
||||
'torrouter_server' : '5m',
|
||||
'leafrouter_torrouter' : '40m',
|
||||
'spinerouter_leafrouter' : '300m'
|
||||
}
|
||||
%}
|
||||
|
||||
{%- macro cable_length(port_name) -%}
|
||||
{%- set cable_len = [] -%}
|
||||
{%- for local_port in DEVICE_NEIGHBOR -%}
|
||||
{%- if local_port == port_name -%}
|
||||
{%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
|
||||
{%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
|
||||
{%- set neighbor_role = neighbor.type -%}
|
||||
{%- set roles1 = switch_role + '_' + neighbor_role %}
|
||||
{%- set roles2 = neighbor_role + '_' + switch_role -%}
|
||||
{%- set roles1 = roles1 | lower -%}
|
||||
{%- set roles2 = roles2 | lower -%}
|
||||
{%- if roles1 in ports2cable -%}
|
||||
{%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
|
||||
{%- elif roles2 in ports2cable -%}
|
||||
{%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- if cable_len -%}
|
||||
{{ cable_len.0 }}
|
||||
{%- else -%}
|
||||
{{ default_cable }}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{%- if DEVICE_METADATA is defined %}
|
||||
{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
|
||||
{%- endif -%}
|
||||
|
||||
{# Generate list of ports if not defined #}
|
||||
{% if PORT is not defined %}
|
||||
{% set PORT = [] %}
|
||||
{% for port_idx in range(1,default_ports_num+1) %}
|
||||
{% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
|
||||
{% set port_names_list = [] %}
|
||||
{% for port in PORT %}
|
||||
{%- if port_names_list.append(port) %}{% endif %}
|
||||
{% endfor %}
|
||||
{% set port_names = port_names_list | join(',') -%}
|
||||
|
||||
{
|
||||
"CABLE_LENGTH": {
|
||||
"AZURE": {
|
||||
{% for port in PORT %}
|
||||
{% set cable = cable_length(port) -%}
|
||||
"{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
# PG lossless profiles.
|
||||
# speed cable size xon xoff threshold
|
||||
1000 5m 34816 18432 16384 0
|
||||
10000 5m 34816 18432 16384 0
|
||||
25000 5m 34816 18432 16384 0
|
||||
40000 5m 34816 18432 16384 0
|
||||
50000 5m 34816 18432 16384 0
|
||||
100000 5m 36864 18432 18432 0
|
||||
1000 40m 36864 18432 18432 0
|
||||
10000 40m 36864 18432 18432 0
|
||||
25000 40m 39936 18432 21504 0
|
||||
40000 40m 41984 18432 23552 0
|
||||
50000 40m 41984 18432 23552 0
|
||||
100000 40m 54272 18432 35840 0
|
||||
1000 300m 49152 18432 30720 0
|
||||
10000 300m 49152 18432 30720 0
|
||||
25000 300m 71680 18432 53248 0
|
||||
40000 300m 94208 18432 75776 0
|
||||
50000 300m 94208 18432 75776 0
|
||||
100000 300m 184320 18432 165888 0
|
||||
|
@ -0,0 +1,27 @@
|
||||
# name lanes alias index speed fec
|
||||
Ethernet0 0 eth-0-1 0 10000 none
|
||||
Ethernet1 1 eth-0-2 1 10000 none
|
||||
Ethernet2 2 eth-0-3 2 10000 none
|
||||
Ethernet3 3 eth-0-4 3 10000 none
|
||||
Ethernet4 8 eth-0-5 4 10000 none
|
||||
Ethernet5 9 eth-0-6 5 10000 none
|
||||
Ethernet6 10 eth-0-7 6 10000 none
|
||||
Ethernet7 11 eth-0-8 7 10000 none
|
||||
Ethernet8 20 eth-0-9 8 10000 none
|
||||
Ethernet9 21 eth-0-10 9 10000 none
|
||||
Ethernet10 22 eth-0-11 10 10000 none
|
||||
Ethernet11 23 eth-0-12 11 10000 none
|
||||
Ethernet12 12 eth-0-13 12 10000 none
|
||||
Ethernet13 13 eth-0-14 13 10000 none
|
||||
Ethernet14 14 eth-0-15 14 10000 none
|
||||
Ethernet15 15 eth-0-16 15 10000 none
|
||||
Ethernet16 24 eth-0-17 16 10000 none
|
||||
Ethernet17 25 eth-0-18 17 10000 none
|
||||
Ethernet18 26 eth-0-19 18 10000 none
|
||||
Ethernet19 27 eth-0-20 19 10000 none
|
||||
Ethernet20 28 eth-0-21 20 10000 none
|
||||
Ethernet21 29 eth-0-22 21 10000 none
|
||||
Ethernet22 30 eth-0-23 22 10000 none
|
||||
Ethernet23 31 eth-0-24 23 10000 none
|
||||
Ethernet24 61,60,63,62 eth-0-25 24 40000 none
|
||||
Ethernet25 45,44,47,46 eth-0-26 25 40000 none
|
@ -0,0 +1 @@
|
||||
{%- include 'qos_config.j2' %}
|
@ -0,0 +1,2 @@
|
||||
SAI_INIT_CONFIG_FILE=/etc/centec/E530-24x2q-chip-profile.txt
|
||||
SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-24x2q-datapath-cfg.txt
|
1
device/centec/arm64-centec_e530_24x2q-r0/default_sku
Normal file
1
device/centec/arm64-centec_e530_24x2q-r0/default_sku
Normal file
@ -0,0 +1 @@
|
||||
E530-24x2q l2
|
12
device/centec/arm64-centec_e530_24x2q-r0/fancontrol
Normal file
12
device/centec/arm64-centec_e530_24x2q-r0/fancontrol
Normal file
@ -0,0 +1,12 @@
|
||||
# Configuration file generated by pwmconfig, changes will be lost
|
||||
INTERVAL=10
|
||||
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
|
||||
DEVNAME=hwmon1=ctc5236fan
|
||||
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input
|
||||
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input
|
||||
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30
|
||||
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90
|
||||
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12
|
||||
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
|
||||
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
|
||||
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"chassis": {
|
||||
"E530-24x2q": {
|
||||
"component": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
device/centec/arm64-centec_e530_24x2q-r0/platform_reboot
Executable file
11
device/centec/arm64-centec_e530_24x2q-r0/platform_reboot
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
|
||||
def main():
|
||||
# reboot the system
|
||||
os.system('echo 502 > /sys/class/gpio/export')
|
||||
os.system('echo out > /sys/class/gpio/gpio502/direction')
|
||||
os.system('echo 1 > /sys/class/gpio/gpio502/value')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
22
device/centec/arm64-centec_e530_24x2q-r0/plugins/eeprom.py
Normal file
22
device/centec/arm64-centec_e530_24x2q-r0/plugins/eeprom.py
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec E550-24X8Y2C
|
||||
#
|
||||
# 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:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self, name, path, cpld_root, ro):
|
||||
self.eeprom_path = "/dev/mtd3"
|
||||
super(board, self).__init__(self.eeprom_path, 0, '', True)
|
165
device/centec/arm64-centec_e530_24x2q-r0/plugins/led_control.py
Normal file
165
device/centec/arm64-centec_e530_24x2q-r0/plugins/led_control.py
Normal file
@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# led_control.py
|
||||
#
|
||||
# Platform-specific LED control functionality for SONiC
|
||||
#
|
||||
|
||||
try:
|
||||
import os
|
||||
import re
|
||||
import syslog
|
||||
import collections
|
||||
from sonic_led.led_control_base import LedControlBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + " - required module not found")
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
def DBG_PRINT(str):
|
||||
syslog.openlog("centec-led")
|
||||
syslog.syslog(syslog.LOG_INFO, str)
|
||||
syslog.closelog()
|
||||
|
||||
class LedControl(LedControlBase):
|
||||
"""Platform specific LED control class"""
|
||||
|
||||
# Constructor
|
||||
def __init__(self):
|
||||
|
||||
self.mac_to_led = {
|
||||
0: 1,
|
||||
1: 2,
|
||||
2: 3,
|
||||
3: 4,
|
||||
8: 5,
|
||||
9: 6,
|
||||
10: 7,
|
||||
11: 8,
|
||||
20: 9,
|
||||
21:10,
|
||||
22:11,
|
||||
23:12,
|
||||
12:13,
|
||||
13:14,
|
||||
14:15,
|
||||
15:16,
|
||||
24:17,
|
||||
25:18,
|
||||
26:19,
|
||||
27:20,
|
||||
28:21,
|
||||
29:22,
|
||||
30:23,
|
||||
31:24,
|
||||
61:-1,
|
||||
60:25,
|
||||
63:-1,
|
||||
62:-1,
|
||||
45:-1,
|
||||
44:26,
|
||||
47:-1,
|
||||
46:-1,
|
||||
}
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
raise
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"])
|
||||
try:
|
||||
f = open(port_config_file)
|
||||
except:
|
||||
raise
|
||||
for line in f:
|
||||
line.strip()
|
||||
if re.search('^#', line) is not None:
|
||||
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
|
||||
break
|
||||
f.close()
|
||||
f = open(port_config_file)
|
||||
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
|
||||
for line in f if re.search('^#', line) is None]
|
||||
f.close()
|
||||
|
||||
self.LED_MODE_UP = [11, 11]
|
||||
self.LED_MODE_DOWN = [7, 7]
|
||||
self.f_led = "/sys/class/leds/{}/brightness"
|
||||
self._initDefaultConfig()
|
||||
|
||||
# Helper method to map SONiC port name to index
|
||||
def _port_name_to_index(self, port_name):
|
||||
for port_cfg in self._port_cfgs:
|
||||
if port_name == port_cfg.name:
|
||||
macs = [int(x) for x in (port_cfg.lanes.split(','))]
|
||||
led = self.mac_to_led[min(macs)]
|
||||
if led < 0:
|
||||
return None
|
||||
return led
|
||||
return None
|
||||
|
||||
def _port_state_to_mode(self, port_idx, state):
|
||||
if state == "up":
|
||||
return self.LED_MODE_UP[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_UP[0]
|
||||
else:
|
||||
return self.LED_MODE_DOWN[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_DOWN[0]
|
||||
|
||||
def _port_led_mode_update(self, port_idx, ledMode):
|
||||
with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file:
|
||||
led_file.write(str(ledMode))
|
||||
|
||||
def _initSystemLed(self):
|
||||
try:
|
||||
with open(self.f_led.format("system"), 'w') as led_file:
|
||||
led_file.write("1")
|
||||
DBG_PRINT("init system led to normal")
|
||||
with open(self.f_led.format("idn"), 'w') as led_file:
|
||||
led_file.write("1")
|
||||
DBG_PRINT("init idn led to off")
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
|
||||
def _initPanelLed(self):
|
||||
with open(self.f_led.format("port1"), 'r') as led_file:
|
||||
shouldInit = (int(led_file.read()) == 0)
|
||||
|
||||
if shouldInit == True:
|
||||
for port_cfg in self._port_cfgs:
|
||||
macs = [int(x) for x in (port_cfg.lanes.split(','))]
|
||||
led = self.mac_to_led[min(macs)]
|
||||
if led < 0:
|
||||
continue
|
||||
defmode = self._port_state_to_mode(led, "down")
|
||||
with open(self.f_led.format("port{}".format(led)), 'w') as led_file:
|
||||
led_file.write(str(defmode))
|
||||
DBG_PRINT("init port{} led to mode={}".format(led, defmode))
|
||||
|
||||
def _initDefaultConfig(self):
|
||||
DBG_PRINT("start init led")
|
||||
|
||||
self._initSystemLed()
|
||||
self._initPanelLed()
|
||||
|
||||
DBG_PRINT("init led done")
|
||||
|
||||
# Concrete implementation of port_link_state_change() method
|
||||
def port_link_state_change(self, portname, state):
|
||||
port_idx = self._port_name_to_index(portname)
|
||||
if port_idx is None:
|
||||
return
|
||||
ledMode = self._port_state_to_mode(port_idx, state)
|
||||
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
|
||||
saveMode = int(led_file.read())
|
||||
|
||||
if ledMode == saveMode:
|
||||
return
|
||||
|
||||
self._port_led_mode_update(port_idx, ledMode)
|
||||
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
|
72
device/centec/arm64-centec_e530_24x2q-r0/plugins/psuutil.py
Normal file
72
device/centec/arm64-centec_e530_24x2q-r0/plugins/psuutil.py
Normal file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec
|
||||
#
|
||||
# Module contains an implementation of SONiC PSU Base API and
|
||||
# provides the PSUs status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
try:
|
||||
from sonic_psu.psu_base import PsuBase
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
class PsuUtil(PsuBase):
|
||||
"""Platform-specific PSUutil class"""
|
||||
|
||||
def __init__(self):
|
||||
PsuBase.__init__(self)
|
||||
|
||||
self.psu_path = "/sys/class/psu/psu{}/"
|
||||
self.psu_presence = "psu_presence"
|
||||
self.psu_oper_status = "psu_status"
|
||||
|
||||
def get_num_psus(self):
|
||||
"""
|
||||
Retrieves the number of PSUs available on the device
|
||||
|
||||
:return: An integer, the number of PSUs available on the device
|
||||
"""
|
||||
return 2
|
||||
|
||||
def get_psu_status(self, index):
|
||||
"""
|
||||
Retrieves the oprational status of power supply unit (PSU) defined
|
||||
by 1-based index <index>
|
||||
|
||||
:param index: An integer, 1-based index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is operating properly, False if PSU is faulty
|
||||
"""
|
||||
if index is None:
|
||||
return False
|
||||
|
||||
status = 0
|
||||
try:
|
||||
with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status:
|
||||
status = int(power_status.read())
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
return status == 1
|
||||
|
||||
def get_psu_presence(self, index):
|
||||
"""
|
||||
Retrieves the presence status of power supply unit (PSU) defined
|
||||
by 1-based index <index>
|
||||
|
||||
:param index: An integer, 1-based index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is plugged, False if not
|
||||
"""
|
||||
if index is None:
|
||||
return False
|
||||
|
||||
status = 0
|
||||
try:
|
||||
with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status:
|
||||
status = int(presence_status.read())
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
return status == 1
|
200
device/centec/arm64-centec_e530_24x2q-r0/plugins/sfputil.py
Normal file
200
device/centec/arm64-centec_e530_24x2q-r0/plugins/sfputil.py
Normal file
@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# sfputil.py
|
||||
#
|
||||
# Platform-specific SFP transceiver interface for SONiC
|
||||
#
|
||||
|
||||
try:
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import collections
|
||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % str(e))
|
||||
|
||||
SFP_STATUS_INSERTED = '1'
|
||||
SFP_STATUS_REMOVED = '0'
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class SfpUtil(SfpUtilBase):
|
||||
"""Platform-specific SfpUtil class"""
|
||||
|
||||
def __init__(self):
|
||||
self.mac_to_sfp = {
|
||||
0: 1,
|
||||
1: 2,
|
||||
2: 3,
|
||||
3: 4,
|
||||
8: 5,
|
||||
9: 6,
|
||||
10: 7,
|
||||
11: 8,
|
||||
20: 9,
|
||||
21:10,
|
||||
22:11,
|
||||
23:12,
|
||||
12:13,
|
||||
13:14,
|
||||
14:15,
|
||||
15:16,
|
||||
24:17,
|
||||
25:18,
|
||||
26:19,
|
||||
27:20,
|
||||
28:21,
|
||||
29:22,
|
||||
30:23,
|
||||
31:24,
|
||||
61:25,
|
||||
60:25,
|
||||
63:25,
|
||||
62:25,
|
||||
45:26,
|
||||
44:26,
|
||||
47:26,
|
||||
46:26,
|
||||
}
|
||||
self.logical = []
|
||||
self.physical_to_logical = {}
|
||||
self.logical_to_physical = {}
|
||||
self.logical_to_asic = {}
|
||||
self.data = {'valid':0, 'last':0}
|
||||
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
|
||||
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
raise
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"])
|
||||
try:
|
||||
f = open(port_config_file)
|
||||
except:
|
||||
raise
|
||||
for line in f:
|
||||
line.strip()
|
||||
if re.search('^#', line) is not None:
|
||||
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
|
||||
break
|
||||
f.close()
|
||||
f = open(port_config_file)
|
||||
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
|
||||
for line in f if re.search('^#', line) is None]
|
||||
f.close()
|
||||
|
||||
self.PORT_START = 256
|
||||
self.PORT_END = 0
|
||||
for port_cfg in self._port_cfgs:
|
||||
if int(port_cfg.index) <= self.PORT_START:
|
||||
self.PORT_START = int(port_cfg.index)
|
||||
elif int(port_cfg.index) >= self.PORT_END:
|
||||
self.PORT_END = int(port_cfg.index)
|
||||
|
||||
self.eeprom_mapping = {}
|
||||
self.presence = {}
|
||||
for port_cfg in self._port_cfgs:
|
||||
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
|
||||
if sfp_idx > 0:
|
||||
self.eeprom_mapping[int(port_cfg.index)] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(sfp_idx)
|
||||
self.logical.append(port_cfg.name)
|
||||
else:
|
||||
self.eeprom_mapping[int(port_cfg.index)] = None
|
||||
self.presence[int(port_cfg.index)] = False
|
||||
|
||||
SfpUtilBase.__init__(self)
|
||||
|
||||
@property
|
||||
def port_start(self):
|
||||
return self.PORT_START
|
||||
|
||||
@property
|
||||
def port_end(self):
|
||||
return self.PORT_END
|
||||
|
||||
@property
|
||||
def sfp_base(self):
|
||||
return self.PORT_START
|
||||
|
||||
@property
|
||||
def qsfp_ports(self):
|
||||
start = 256
|
||||
end = 0
|
||||
for port_cfg in self._port_cfgs:
|
||||
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
|
||||
if sfp_idx == 25 or sfp_idx == 26:
|
||||
if int(port_cfg.index) <= start:
|
||||
start = int(port_cfg.index)
|
||||
elif int(port_cfg.index) >= end:
|
||||
end = int(port_cfg.index)
|
||||
return range(start, end + 1)
|
||||
|
||||
@property
|
||||
def port_to_eeprom_mapping(self):
|
||||
return self.eeprom_mapping
|
||||
|
||||
def is_logical_port(self, port_name):
|
||||
return True
|
||||
|
||||
def get_presence(self, port_num):
|
||||
for port_cfg in self._port_cfgs:
|
||||
if int(port_cfg.index) == port_num:
|
||||
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
|
||||
if sfp_idx >= 0:
|
||||
try:
|
||||
with open(self.f_sfp_present.format(sfp_idx), 'r') as sfp_file:
|
||||
return 1 == int(sfp_file.read())
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
return False
|
||||
|
||||
def get_low_power_mode(self, port_num):
|
||||
return False
|
||||
|
||||
def set_low_power_mode(self, port_num, lpmode):
|
||||
return False
|
||||
|
||||
def reset(self, port_num):
|
||||
return False
|
||||
|
||||
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
|
||||
for port_cfg in self._port_cfgs:
|
||||
self.logical_to_physical[port_cfg.name] = [int(port_cfg.index)]
|
||||
self.logical_to_asic[port_cfg.name] = 0
|
||||
self.physical_to_logical[int(port_cfg.index)] = [port_cfg.name]
|
||||
|
||||
def get_transceiver_change_event(self, timeout=2000):
|
||||
now = time.time()
|
||||
port_dict = {}
|
||||
|
||||
if timeout < 1000:
|
||||
timeout = 1000
|
||||
timeout = (timeout) / float(1000) # Convert to secs
|
||||
|
||||
if now < (self.data['last'] + timeout) and self.data['valid']:
|
||||
return True, {}
|
||||
|
||||
for port_cfg in self._port_cfgs:
|
||||
presence = self.get_presence(int(port_cfg.index))
|
||||
if presence != self.presence[int(port_cfg.index)]:
|
||||
self.presence[int(port_cfg.index)] = presence
|
||||
if presence:
|
||||
port_dict[int(port_cfg.index)] = SFP_STATUS_INSERTED
|
||||
else:
|
||||
port_dict[int(port_cfg.index)] = SFP_STATUS_REMOVED
|
||||
|
||||
if bool(port_dict):
|
||||
self.data['last'] = now
|
||||
self.data['valid'] = 1
|
||||
return True, port_dict
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
return True, {}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
{# Default values which will be used if no actual configura available #}
|
||||
{% set default_cable = '40m' %}
|
||||
{% set default_ports_num = 54 -%}
|
||||
|
||||
{# Port configuration to cable length look-up table #}
|
||||
{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
|
||||
{# Roles described in the minigraph #}
|
||||
{% set ports2cable = {
|
||||
'torrouter_server' : '5m',
|
||||
'leafrouter_torrouter' : '40m',
|
||||
'spinerouter_leafrouter' : '300m'
|
||||
}
|
||||
%}
|
||||
|
||||
{%- macro cable_length(port_name) -%}
|
||||
{%- set cable_len = [] -%}
|
||||
{%- for local_port in DEVICE_NEIGHBOR -%}
|
||||
{%- if local_port == port_name -%}
|
||||
{%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
|
||||
{%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
|
||||
{%- set neighbor_role = neighbor.type -%}
|
||||
{%- set roles1 = switch_role + '_' + neighbor_role %}
|
||||
{%- set roles2 = neighbor_role + '_' + switch_role -%}
|
||||
{%- set roles1 = roles1 | lower -%}
|
||||
{%- set roles2 = roles2 | lower -%}
|
||||
{%- if roles1 in ports2cable -%}
|
||||
{%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
|
||||
{%- elif roles2 in ports2cable -%}
|
||||
{%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- if cable_len -%}
|
||||
{{ cable_len.0 }}
|
||||
{%- else -%}
|
||||
{{ default_cable }}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{%- if DEVICE_METADATA is defined %}
|
||||
{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
|
||||
{%- endif -%}
|
||||
|
||||
{# Generate list of ports if not defined #}
|
||||
{% if PORT is not defined %}
|
||||
{% set PORT = [] %}
|
||||
{% for port_idx in range(1,default_ports_num+1) %}
|
||||
{% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
|
||||
{% set port_names_list = [] %}
|
||||
{% for port in PORT %}
|
||||
{%- if port_names_list.append(port) %}{% endif %}
|
||||
{% endfor %}
|
||||
{% set port_names = port_names_list | join(',') -%}
|
||||
|
||||
{
|
||||
"CABLE_LENGTH": {
|
||||
"AZURE": {
|
||||
{% for port in PORT %}
|
||||
{% set cable = cable_length(port) -%}
|
||||
"{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
# PG lossless profiles.
|
||||
# speed cable size xon xoff threshold
|
||||
1000 5m 34816 18432 16384 0
|
||||
10000 5m 34816 18432 16384 0
|
||||
25000 5m 34816 18432 16384 0
|
||||
40000 5m 34816 18432 16384 0
|
||||
50000 5m 34816 18432 16384 0
|
||||
100000 5m 36864 18432 18432 0
|
||||
1000 40m 36864 18432 18432 0
|
||||
10000 40m 36864 18432 18432 0
|
||||
25000 40m 39936 18432 21504 0
|
||||
40000 40m 41984 18432 23552 0
|
||||
50000 40m 41984 18432 23552 0
|
||||
100000 40m 54272 18432 35840 0
|
||||
1000 300m 49152 18432 30720 0
|
||||
10000 300m 49152 18432 30720 0
|
||||
25000 300m 71680 18432 53248 0
|
||||
40000 300m 94208 18432 75776 0
|
||||
50000 300m 94208 18432 75776 0
|
||||
100000 300m 184320 18432 165888 0
|
||||
|
@ -0,0 +1,53 @@
|
||||
# name lanes alias index speed fec
|
||||
Ethernet0 0 eth-0-1 0 1000 none
|
||||
Ethernet1 1 eth-0-2 1 1000 none
|
||||
Ethernet2 2 eth-0-3 2 1000 none
|
||||
Ethernet3 3 eth-0-4 3 1000 none
|
||||
Ethernet4 4 eth-0-5 4 1000 none
|
||||
Ethernet5 5 eth-0-6 5 1000 none
|
||||
Ethernet6 6 eth-0-7 6 1000 none
|
||||
Ethernet7 7 eth-0-8 7 1000 none
|
||||
Ethernet8 16 eth-0-9 8 1000 none
|
||||
Ethernet9 17 eth-0-10 9 1000 none
|
||||
Ethernet10 18 eth-0-11 10 1000 none
|
||||
Ethernet11 19 eth-0-12 11 1000 none
|
||||
Ethernet12 20 eth-0-13 12 1000 none
|
||||
Ethernet13 21 eth-0-14 13 1000 none
|
||||
Ethernet14 22 eth-0-15 14 1000 none
|
||||
Ethernet15 23 eth-0-16 15 1000 none
|
||||
Ethernet16 8 eth-0-17 16 1000 none
|
||||
Ethernet17 9 eth-0-18 17 1000 none
|
||||
Ethernet18 10 eth-0-19 18 1000 none
|
||||
Ethernet19 11 eth-0-20 19 1000 none
|
||||
Ethernet20 32 eth-0-21 20 1000 none
|
||||
Ethernet21 33 eth-0-22 21 1000 none
|
||||
Ethernet22 34 eth-0-23 22 1000 none
|
||||
Ethernet23 35 eth-0-24 23 1000 none
|
||||
Ethernet24 36 eth-0-25 24 1000 none
|
||||
Ethernet25 37 eth-0-26 25 1000 none
|
||||
Ethernet26 38 eth-0-27 26 1000 none
|
||||
Ethernet27 39 eth-0-28 27 1000 none
|
||||
Ethernet28 40 eth-0-29 28 1000 none
|
||||
Ethernet29 41 eth-0-30 29 1000 none
|
||||
Ethernet30 42 eth-0-31 30 1000 none
|
||||
Ethernet31 43 eth-0-32 31 1000 none
|
||||
Ethernet32 25 eth-0-33 32 1000 none
|
||||
Ethernet33 24 eth-0-34 33 1000 none
|
||||
Ethernet34 27 eth-0-35 34 1000 none
|
||||
Ethernet35 26 eth-0-36 35 1000 none
|
||||
Ethernet36 13 eth-0-37 36 1000 none
|
||||
Ethernet37 12 eth-0-38 37 1000 none
|
||||
Ethernet38 15 eth-0-39 38 1000 none
|
||||
Ethernet39 14 eth-0-40 39 1000 none
|
||||
Ethernet40 29 eth-0-41 40 1000 none
|
||||
Ethernet41 28 eth-0-42 41 1000 none
|
||||
Ethernet42 31 eth-0-43 42 1000 none
|
||||
Ethernet43 30 eth-0-44 43 1000 none
|
||||
Ethernet44 61 eth-0-45 44 1000 none
|
||||
Ethernet45 60 eth-0-46 45 1000 none
|
||||
Ethernet46 63 eth-0-47 46 1000 none
|
||||
Ethernet47 62 eth-0-48 47 1000 none
|
||||
Ethernet48 44 eth-0-49 48 10000 none
|
||||
Ethernet49 45 eth-0-50 49 10000 none
|
||||
Ethernet50 47 eth-0-51 50 10000 none
|
||||
Ethernet51 46 eth-0-52 51 10000 none
|
@ -0,0 +1 @@
|
||||
{%- include 'qos_config.j2' %}
|
@ -0,0 +1,2 @@
|
||||
SAI_INIT_CONFIG_FILE=/etc/centec/E530-48s4x-chip-profile.txt
|
||||
SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-48s4x-datapath.txt
|
1
device/centec/arm64-centec_e530_48s4x-r0/default_sku
Normal file
1
device/centec/arm64-centec_e530_48s4x-r0/default_sku
Normal file
@ -0,0 +1 @@
|
||||
E530-48s4x l2
|
12
device/centec/arm64-centec_e530_48s4x-r0/fancontrol
Normal file
12
device/centec/arm64-centec_e530_48s4x-r0/fancontrol
Normal file
@ -0,0 +1,12 @@
|
||||
# Configuration file generated by pwmconfig, changes will be lost
|
||||
INTERVAL=10
|
||||
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
|
||||
DEVNAME=hwmon1=ctc5236fan
|
||||
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input hwmon1/pwm4=hwmon1/temp1_input
|
||||
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm4=hwmon1/fan4_input
|
||||
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30 hwmon1/pwm4=30
|
||||
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90 hwmon1/pwm4=90
|
||||
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12 hwmon1/pwm4=12
|
||||
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 hwmon1/pwm4=6
|
||||
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 hwmon1/pwm4=6
|
||||
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18 hwmon1/pwm4=18
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"chassis": {
|
||||
"E530-48s4x": {
|
||||
"component": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
device/centec/arm64-centec_e530_48s4x-r0/platform_reboot
Executable file
12
device/centec/arm64-centec_e530_48s4x-r0/platform_reboot
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
|
||||
def main():
|
||||
# reboot the system
|
||||
os.system('modprobe i2c-dev')
|
||||
os.system('i2cset -y 0 0x36 0x23 0x0')
|
||||
os.system('sleep 1')
|
||||
os.system('i2cset -y 0 0x36 0x23 0x3')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
22
device/centec/arm64-centec_e530_48s4x-r0/plugins/eeprom.py
Normal file
22
device/centec/arm64-centec_e530_48s4x-r0/plugins/eeprom.py
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec E530-48S4X
|
||||
#
|
||||
# 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:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self, name, path, cpld_root, ro):
|
||||
self.eeprom_path = "/dev/mtd3"
|
||||
super(board, self).__init__(self.eeprom_path, 0, '', True)
|
@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# led_control.py
|
||||
#
|
||||
# Platform-specific LED control functionality for SONiC
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_led.led_control_base import LedControlBase
|
||||
import syslog
|
||||
from socket import *
|
||||
from select import *
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + " - required module not found")
|
||||
|
||||
|
||||
def DBG_PRINT(str):
|
||||
syslog.openlog("centec-led")
|
||||
syslog.syslog(syslog.LOG_INFO, str)
|
||||
syslog.closelog()
|
||||
|
||||
|
||||
class LedControl(LedControlBase):
|
||||
"""Platform specific LED control class"""
|
||||
|
||||
|
||||
# Helper method to map SONiC port name to index
|
||||
def _port_name_to_index(self, port_name):
|
||||
# Strip "Ethernet" off port name
|
||||
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
|
||||
return -1
|
||||
|
||||
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
|
||||
return port_idx + 1
|
||||
|
||||
def _port_state_to_mode(self, port_idx, state):
|
||||
if state == "up":
|
||||
return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1]
|
||||
else:
|
||||
return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1]
|
||||
|
||||
def _port_led_mode_update(self, port_idx, ledMode):
|
||||
with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file:
|
||||
led_file.write(str(ledMode))
|
||||
|
||||
def _initSystemLed(self):
|
||||
try:
|
||||
with open(self.f_led.format("system"), 'w') as led_file:
|
||||
led_file.write("3")
|
||||
DBG_PRINT("init system led to normal")
|
||||
with open(self.f_led.format("idn"), 'w') as led_file:
|
||||
led_file.write("1")
|
||||
DBG_PRINT("init idn led to off")
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
|
||||
def _initPanelLed(self):
|
||||
with open(self.f_led.format("port1"), 'r') as led_file:
|
||||
shouldInit = (int(led_file.read()) == 0)
|
||||
|
||||
if shouldInit == True:
|
||||
for idx in range(1, 53):
|
||||
defmode = self._port_state_to_mode(idx, "down")
|
||||
with open(self.f_led.format("port{}".format(idx)), 'w') as led_file:
|
||||
led_file.write(str(defmode))
|
||||
DBG_PRINT("init port{} led to mode={}".format(idx, defmode))
|
||||
|
||||
def _initDefaultConfig(self):
|
||||
DBG_PRINT("start init led")
|
||||
|
||||
self._initSystemLed()
|
||||
self._initPanelLed()
|
||||
|
||||
DBG_PRINT("init led done")
|
||||
|
||||
|
||||
# Concrete implementation of port_link_state_change() method
|
||||
def port_link_state_change(self, portname, state):
|
||||
port_idx = self._port_name_to_index(portname)
|
||||
ledMode = self._port_state_to_mode(port_idx, state)
|
||||
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
|
||||
saveMode = int(led_file.read())
|
||||
|
||||
if ledMode == saveMode:
|
||||
return
|
||||
|
||||
self._port_led_mode_update(port_idx, ledMode)
|
||||
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
|
||||
|
||||
|
||||
# Constructor
|
||||
def __init__(self):
|
||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||
self.LED_MODE_UP = [5, 6]
|
||||
self.LED_MODE_DOWN = [7, 7]
|
||||
|
||||
self.f_led = "/sys/class/leds/{}/brightness"
|
||||
self._initDefaultConfig()
|
72
device/centec/arm64-centec_e530_48s4x-r0/plugins/psuutil.py
Normal file
72
device/centec/arm64-centec_e530_48s4x-r0/plugins/psuutil.py
Normal file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec
|
||||
#
|
||||
# Module contains an implementation of SONiC PSU Base API and
|
||||
# provides the PSUs status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
try:
|
||||
from sonic_psu.psu_base import PsuBase
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
class PsuUtil(PsuBase):
|
||||
"""Platform-specific PSUutil class"""
|
||||
|
||||
def __init__(self):
|
||||
PsuBase.__init__(self)
|
||||
|
||||
self.psu_path = "/sys/class/psu/psu{}/"
|
||||
self.psu_presence = "psu_presence"
|
||||
self.psu_oper_status = "psu_status"
|
||||
|
||||
def get_num_psus(self):
|
||||
"""
|
||||
Retrieves the number of PSUs available on the device
|
||||
|
||||
:return: An integer, the number of PSUs available on the device
|
||||
"""
|
||||
return 2
|
||||
|
||||
def get_psu_status(self, index):
|
||||
"""
|
||||
Retrieves the oprational status of power supply unit (PSU) defined
|
||||
by 1-based index <index>
|
||||
|
||||
:param index: An integer, 1-based index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is operating properly, False if PSU is faulty
|
||||
"""
|
||||
if index is None:
|
||||
return False
|
||||
|
||||
status = 0
|
||||
try:
|
||||
with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status:
|
||||
status = int(power_status.read())
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
return status == 1
|
||||
|
||||
def get_psu_presence(self, index):
|
||||
"""
|
||||
Retrieves the presence status of power supply unit (PSU) defined
|
||||
by 1-based index <index>
|
||||
|
||||
:param index: An integer, 1-based index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is plugged, False if not
|
||||
"""
|
||||
if index is None:
|
||||
return False
|
||||
|
||||
status = 0
|
||||
try:
|
||||
with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status:
|
||||
status = int(presence_status.read())
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
return status == 1
|
161
device/centec/arm64-centec_e530_48s4x-r0/plugins/sfputil.py
Normal file
161
device/centec/arm64-centec_e530_48s4x-r0/plugins/sfputil.py
Normal file
@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# sfputil.py
|
||||
#
|
||||
# Platform-specific SFP transceiver interface for SONiC
|
||||
#
|
||||
|
||||
try:
|
||||
import time
|
||||
from socket import *
|
||||
from select import *
|
||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % str(e))
|
||||
|
||||
|
||||
def DBG_PRINT(str):
|
||||
print(str + "\n")
|
||||
|
||||
SFP_STATUS_INSERTED = '1'
|
||||
SFP_STATUS_REMOVED = '0'
|
||||
|
||||
class SfpUtil(SfpUtilBase):
|
||||
"""Platform-specific SfpUtil class"""
|
||||
|
||||
@property
|
||||
def port_start(self):
|
||||
return self.PORT_START
|
||||
|
||||
@property
|
||||
def port_end(self):
|
||||
return self.PORT_END
|
||||
|
||||
@property
|
||||
def sfp_base(self):
|
||||
return self.SFP_BASE
|
||||
|
||||
@property
|
||||
def qsfp_ports(self):
|
||||
return ()
|
||||
|
||||
@property
|
||||
def port_to_eeprom_mapping(self):
|
||||
return self.eeprom_mapping
|
||||
|
||||
def is_logical_port(self, port_name):
|
||||
return True
|
||||
|
||||
def get_eeprom_data(self, port):
|
||||
ret = None
|
||||
port_num = self.get_logical_to_physical(port)[0] + 1
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return ret
|
||||
if port_num < self.sfp_base:
|
||||
return ret
|
||||
try:
|
||||
with open(self.eeprom_mapping[port_num], 'r') as eeprom_file:
|
||||
ret = eeprom_file.read()
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
|
||||
return ret
|
||||
|
||||
def __init__(self):
|
||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||
self.PORT_START = 0
|
||||
self.PORT_END = 51
|
||||
self.SFP_BASE = 0
|
||||
self.PORTS_IN_BLOCK = 52
|
||||
self.logical = []
|
||||
self.physical_to_logical = {}
|
||||
self.logical_to_physical = {}
|
||||
self.logical_to_asic = {}
|
||||
self.data = {'valid':0, 'last':0}
|
||||
|
||||
self.eeprom_mapping = {}
|
||||
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
|
||||
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
|
||||
for x in range(self.port_start, self.sfp_base):
|
||||
self.eeprom_mapping[x] = None
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1)
|
||||
self.presence = {}
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.presence[x] = False;
|
||||
|
||||
SfpUtilBase.__init__(self)
|
||||
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.logical.append('Ethernet' + str(x))
|
||||
|
||||
def get_presence(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
if port_num < self.sfp_base:
|
||||
return False
|
||||
try:
|
||||
with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file:
|
||||
return 1 == int(sfp_file.read())
|
||||
except IOError as e:
|
||||
DBG_PRINT(str(e))
|
||||
|
||||
return False
|
||||
|
||||
def get_low_power_mode(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def set_low_power_mode(self, port_num, lpmode):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def reset(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.logical_to_physical['Ethernet' + str(x)] = [x]
|
||||
self.logical_to_asic['Ethernet' + str(x)] = 0
|
||||
self.physical_to_logical[x] = ['Ethernet' + str(x)]
|
||||
|
||||
def get_transceiver_change_event(self, timeout=2000):
|
||||
now = time.time()
|
||||
port_dict = {}
|
||||
|
||||
if timeout < 1000:
|
||||
timeout = 1000
|
||||
timeout = (timeout) / float(1000) # Convert to secs
|
||||
|
||||
if now < (self.data['last'] + timeout) and self.data['valid']:
|
||||
return True, {}
|
||||
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
presence = self.get_presence(x)
|
||||
if presence != self.presence[x]:
|
||||
self.presence[x] = presence
|
||||
# index in port_config.ini
|
||||
if presence:
|
||||
port_dict[x] = SFP_STATUS_INSERTED
|
||||
else:
|
||||
port_dict[x] = SFP_STATUS_REMOVED
|
||||
|
||||
if bool(port_dict):
|
||||
self.data['last'] = now
|
||||
self.data['valid'] = 1
|
||||
return True, port_dict
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
return True, {}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
@ -1,53 +1,53 @@
|
||||
# name lanes alias speed
|
||||
Ethernet1 1 eth-0-1 1000
|
||||
Ethernet2 0 eth-0-2 1000
|
||||
Ethernet3 3 eth-0-3 1000
|
||||
Ethernet4 2 eth-0-4 1000
|
||||
Ethernet5 5 eth-0-5 1000
|
||||
Ethernet6 4 eth-0-6 1000
|
||||
Ethernet7 7 eth-0-7 1000
|
||||
Ethernet8 6 eth-0-8 1000
|
||||
Ethernet9 17 eth-0-9 1000
|
||||
Ethernet10 16 eth-0-10 1000
|
||||
Ethernet11 19 eth-0-11 1000
|
||||
Ethernet12 18 eth-0-12 1000
|
||||
Ethernet13 21 eth-0-13 1000
|
||||
Ethernet14 20 eth-0-14 1000
|
||||
Ethernet15 23 eth-0-15 1000
|
||||
Ethernet16 22 eth-0-16 1000
|
||||
Ethernet17 9 eth-0-17 1000
|
||||
Ethernet18 8 eth-0-18 1000
|
||||
Ethernet19 11 eth-0-19 1000
|
||||
Ethernet20 10 eth-0-20 1000
|
||||
Ethernet21 33 eth-0-21 1000
|
||||
Ethernet22 32 eth-0-22 1000
|
||||
Ethernet23 35 eth-0-23 1000
|
||||
Ethernet24 34 eth-0-24 1000
|
||||
Ethernet25 37 eth-0-25 1000
|
||||
Ethernet26 36 eth-0-26 1000
|
||||
Ethernet27 39 eth-0-27 1000
|
||||
Ethernet28 38 eth-0-28 1000
|
||||
Ethernet29 41 eth-0-29 1000
|
||||
Ethernet30 40 eth-0-30 1000
|
||||
Ethernet31 43 eth-0-31 1000
|
||||
Ethernet32 42 eth-0-32 1000
|
||||
Ethernet33 25 eth-0-33 1000
|
||||
Ethernet34 24 eth-0-34 1000
|
||||
Ethernet35 27 eth-0-35 1000
|
||||
Ethernet36 26 eth-0-36 1000
|
||||
Ethernet37 49 eth-0-37 1000
|
||||
Ethernet38 48 eth-0-38 1000
|
||||
Ethernet39 51 eth-0-39 1000
|
||||
Ethernet40 50 eth-0-40 1000
|
||||
Ethernet41 53 eth-0-41 1000
|
||||
Ethernet42 52 eth-0-42 1000
|
||||
Ethernet43 55 eth-0-43 1000
|
||||
Ethernet44 54 eth-0-44 1000
|
||||
Ethernet45 57 eth-0-45 1000
|
||||
Ethernet46 56 eth-0-46 1000
|
||||
Ethernet47 59 eth-0-47 1000
|
||||
Ethernet48 58 eth-0-48 1000
|
||||
Ethernet49 13 eth-0-49 10000
|
||||
Ethernet50 12 eth-0-50 10000
|
||||
Ethernet51 15 eth-0-51 10000
|
||||
Ethernet52 14 eth-0-52 10000
|
||||
# name lanes alias index speed fec
|
||||
Ethernet0 1 eth-0-1 0 1000 none
|
||||
Ethernet1 0 eth-0-2 1 1000 none
|
||||
Ethernet2 3 eth-0-3 2 1000 none
|
||||
Ethernet3 2 eth-0-4 3 1000 none
|
||||
Ethernet4 5 eth-0-5 4 1000 none
|
||||
Ethernet5 4 eth-0-6 5 1000 none
|
||||
Ethernet6 7 eth-0-7 6 1000 none
|
||||
Ethernet7 6 eth-0-8 7 1000 none
|
||||
Ethernet8 17 eth-0-9 8 1000 none
|
||||
Ethernet9 16 eth-0-10 9 1000 none
|
||||
Ethernet10 19 eth-0-11 10 1000 none
|
||||
Ethernet11 18 eth-0-12 11 1000 none
|
||||
Ethernet12 21 eth-0-13 12 1000 none
|
||||
Ethernet13 20 eth-0-14 13 1000 none
|
||||
Ethernet14 23 eth-0-15 14 1000 none
|
||||
Ethernet15 22 eth-0-16 15 1000 none
|
||||
Ethernet16 9 eth-0-17 16 1000 none
|
||||
Ethernet17 8 eth-0-18 17 1000 none
|
||||
Ethernet18 11 eth-0-19 18 1000 none
|
||||
Ethernet19 10 eth-0-20 19 1000 none
|
||||
Ethernet20 33 eth-0-21 20 1000 none
|
||||
Ethernet21 32 eth-0-22 21 1000 none
|
||||
Ethernet22 35 eth-0-23 22 1000 none
|
||||
Ethernet23 34 eth-0-24 23 1000 none
|
||||
Ethernet24 37 eth-0-25 24 1000 none
|
||||
Ethernet25 36 eth-0-26 25 1000 none
|
||||
Ethernet26 39 eth-0-27 26 1000 none
|
||||
Ethernet27 38 eth-0-28 27 1000 none
|
||||
Ethernet28 41 eth-0-29 28 1000 none
|
||||
Ethernet29 40 eth-0-30 29 1000 none
|
||||
Ethernet30 43 eth-0-31 30 1000 none
|
||||
Ethernet31 42 eth-0-32 31 1000 none
|
||||
Ethernet32 25 eth-0-33 32 1000 none
|
||||
Ethernet33 24 eth-0-34 33 1000 none
|
||||
Ethernet34 27 eth-0-35 34 1000 none
|
||||
Ethernet35 26 eth-0-36 35 1000 none
|
||||
Ethernet36 49 eth-0-37 36 1000 none
|
||||
Ethernet37 48 eth-0-38 37 1000 none
|
||||
Ethernet38 51 eth-0-39 38 1000 none
|
||||
Ethernet39 50 eth-0-40 39 1000 none
|
||||
Ethernet40 53 eth-0-41 40 1000 none
|
||||
Ethernet41 52 eth-0-42 41 1000 none
|
||||
Ethernet42 55 eth-0-43 42 1000 none
|
||||
Ethernet43 54 eth-0-44 43 1000 none
|
||||
Ethernet44 57 eth-0-45 44 1000 none
|
||||
Ethernet45 56 eth-0-46 45 1000 none
|
||||
Ethernet46 59 eth-0-47 46 1000 none
|
||||
Ethernet47 58 eth-0-48 47 1000 none
|
||||
Ethernet48 13 eth-0-49 48 10000 none
|
||||
Ethernet49 12 eth-0-50 49 10000 none
|
||||
Ethernet50 15 eth-0-51 50 10000 none
|
||||
Ethernet51 14 eth-0-52 51 10000 none
|
||||
|
@ -1 +1,12 @@
|
||||
# Configuration file generated by pwmconfig, changes will be lost
|
||||
INTERVAL=10
|
||||
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
|
||||
DEVNAME=hwmon1=ctc5236fan
|
||||
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input
|
||||
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input
|
||||
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30
|
||||
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90
|
||||
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12
|
||||
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
|
||||
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
|
||||
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18
|
||||
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"chassis": {
|
||||
"E530-48t4x-p": {
|
||||
"component": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
device/centec/arm64-centec_e530_48t4x_p-r0/platform_reboot
Executable file
11
device/centec/arm64-centec_e530_48t4x_p-r0/platform_reboot
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
|
||||
def main():
|
||||
# reboot the system
|
||||
os.system('echo 502 > /sys/class/gpio/export')
|
||||
os.system('echo out > /sys/class/gpio/gpio502/direction')
|
||||
os.system('echo 1 > /sys/class/gpio/gpio502/value')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec E550-24X8Y2C
|
||||
#
|
||||
@ -10,7 +12,7 @@
|
||||
try:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# led_control.py
|
||||
#
|
||||
# Platform-specific LED control functionality for SONiC
|
||||
@ -21,6 +23,7 @@ def DBG_PRINT(str):
|
||||
class LedControl(LedControlBase):
|
||||
"""Platform specific LED control class"""
|
||||
|
||||
|
||||
# Helper method to map SONiC port name to index
|
||||
def _port_name_to_index(self, port_name):
|
||||
# Strip "Ethernet" off port name
|
||||
@ -28,7 +31,7 @@ class LedControl(LedControlBase):
|
||||
return -1
|
||||
|
||||
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
|
||||
return port_idx
|
||||
return port_idx + 1
|
||||
|
||||
def _port_state_to_mode(self, port_idx, state):
|
||||
if state == "up":
|
||||
@ -70,8 +73,8 @@ class LedControl(LedControlBase):
|
||||
|
||||
DBG_PRINT("init led done")
|
||||
|
||||
# Concrete implementation of port_link_state_change() method
|
||||
|
||||
# Concrete implementation of port_link_state_change() method
|
||||
def port_link_state_change(self, portname, state):
|
||||
port_idx = self._port_name_to_index(portname)
|
||||
ledMode = self._port_state_to_mode(port_idx, state)
|
||||
@ -84,8 +87,8 @@ class LedControl(LedControlBase):
|
||||
self._port_led_mode_update(port_idx, ledMode)
|
||||
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
|
||||
|
||||
# Constructor
|
||||
|
||||
# Constructor
|
||||
def __init__(self):
|
||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||
self.LED_MODE_UP = [2, 11]
|
||||
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Centec
|
||||
#
|
||||
@ -9,8 +11,7 @@
|
||||
try:
|
||||
from sonic_psu.psu_base import PsuBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
class PsuUtil(PsuBase):
|
||||
"""Platform-specific PSUutil class"""
|
||||
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# sfputil.py
|
||||
#
|
||||
# Platform-specific SFP transceiver interface for SONiC
|
||||
@ -15,6 +17,8 @@ except ImportError as e:
|
||||
def DBG_PRINT(str):
|
||||
print(str + "\n")
|
||||
|
||||
SFP_STATUS_INSERTED = '1'
|
||||
SFP_STATUS_REMOVED = '0'
|
||||
|
||||
class SfpUtil(SfpUtilBase):
|
||||
"""Platform-specific SfpUtil class"""
|
||||
@ -42,17 +46,9 @@ class SfpUtil(SfpUtilBase):
|
||||
def is_logical_port(self, port_name):
|
||||
return True
|
||||
|
||||
def get_logical_to_physical(self, port_name):
|
||||
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
|
||||
return None
|
||||
|
||||
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
|
||||
|
||||
return [port_idx]
|
||||
|
||||
def get_eeprom_data(self, port):
|
||||
ret = None
|
||||
port_num = self.get_logical_to_physical(port)[0]
|
||||
port_num = self.get_logical_to_physical(port)[0] + 1
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return ret
|
||||
if port_num < self.sfp_base:
|
||||
@ -65,16 +61,17 @@ class SfpUtil(SfpUtilBase):
|
||||
|
||||
return ret
|
||||
|
||||
# todo
|
||||
# def _get_port_eeprom_path(self, port_num, devid):
|
||||
# pass
|
||||
|
||||
def __init__(self):
|
||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||
self.PORT_START = 1
|
||||
self.PORT_END = 52
|
||||
self.SFP_BASE = 49
|
||||
self.PORT_START = 0
|
||||
self.PORT_END = 51
|
||||
self.SFP_BASE = 48
|
||||
self.PORTS_IN_BLOCK = 52
|
||||
self.logical = []
|
||||
self.physical_to_logical = {}
|
||||
self.logical_to_physical = {}
|
||||
self.logical_to_asic = {}
|
||||
self.data = {'valid':0, 'last':0}
|
||||
|
||||
self.eeprom_mapping = {}
|
||||
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
|
||||
@ -82,14 +79,16 @@ class SfpUtil(SfpUtilBase):
|
||||
for x in range(self.port_start, self.sfp_base):
|
||||
self.eeprom_mapping[x] = None
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(
|
||||
x - self.sfp_base + 1)
|
||||
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1)
|
||||
self.presence = {}
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.presence[x] = False
|
||||
self.presence[x] = False;
|
||||
|
||||
SfpUtilBase.__init__(self)
|
||||
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.logical.append('Ethernet' + str(x))
|
||||
|
||||
def get_presence(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
@ -125,13 +124,38 @@ class SfpUtil(SfpUtilBase):
|
||||
|
||||
return False
|
||||
|
||||
def get_transceiver_change_event(self, timeout=0):
|
||||
|
||||
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
self.logical_to_physical['Ethernet' + str(x)] = [x]
|
||||
self.logical_to_asic['Ethernet' + str(x)] = 0
|
||||
self.physical_to_logical[x] = ['Ethernet' + str(x)]
|
||||
|
||||
def get_transceiver_change_event(self, timeout=2000):
|
||||
now = time.time()
|
||||
port_dict = {}
|
||||
while True:
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
presence = self.get_presence(x)
|
||||
if presence != self.presence[x]:
|
||||
self.presence[x] = presence
|
||||
port_dict[x] = presence
|
||||
return True, port_dict
|
||||
|
||||
if timeout < 1000:
|
||||
timeout = 1000
|
||||
timeout = (timeout) / float(1000) # Convert to secs
|
||||
|
||||
if now < (self.data['last'] + timeout) and self.data['valid']:
|
||||
return True, {}
|
||||
|
||||
for x in range(self.sfp_base, self.port_end + 1):
|
||||
presence = self.get_presence(x)
|
||||
if presence != self.presence[x]:
|
||||
self.presence[x] = presence
|
||||
# index in port_config.ini
|
||||
if presence:
|
||||
port_dict[x] = SFP_STATUS_INSERTED
|
||||
else:
|
||||
port_dict[x] = SFP_STATUS_REMOVED
|
||||
|
||||
if bool(port_dict):
|
||||
self.data['last'] = now
|
||||
self.data['valid'] = 1
|
||||
return True, port_dict
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
return True, {}
|
||||
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
@ -82,7 +82,7 @@ class SfpUtil(SfpUtilBase):
|
||||
try:
|
||||
reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode")
|
||||
except IOError as e:
|
||||
print "Error: unable to open file: %s" % str(e)
|
||||
print("Error: unable to open file: %s" % str(e))
|
||||
|
||||
content = reg_file.readline().rstrip()
|
||||
|
||||
|
@ -8,6 +8,8 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR)
|
||||
$(SONIC_ONE_IMAGE)_INSTALLS += $(TSINGMA_BSP_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48S4X_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2Q_PLATFORM_MODULE)
|
||||
|
||||
ifeq ($(INSTALL_DEBUG_TOOLS),y)
|
||||
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
|
||||
|
@ -1,8 +1,10 @@
|
||||
# Centec E530-48T4X-P Platform modules
|
||||
|
||||
|
||||
CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.1
|
||||
CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.1
|
||||
CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.3
|
||||
CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.3
|
||||
CENTEC_E530_48S4X_PLATFORM_MODULE_VERSION =1.3
|
||||
CENTEC_E530_24X2Q_PLATFORM_MODULE_VERSION =1.3
|
||||
|
||||
export CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION
|
||||
|
||||
@ -16,3 +18,11 @@ SONIC_DPKG_DEBS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE)
|
||||
CENTEC_E530_24X2C_PLATFORM_MODULE = platform-modules-e530-24x2c_$(CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION)_arm64.deb
|
||||
$(CENTEC_E530_24X2C_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2c-r0
|
||||
$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2C_PLATFORM_MODULE)))
|
||||
|
||||
CENTEC_E530_48S4X_PLATFORM_MODULE = platform-modules-e530-48s4x_$(CENTEC_E530_48S4X_PLATFORM_MODULE_VERSION)_arm64.deb
|
||||
$(CENTEC_E530_48S4X_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_48s4x-r0
|
||||
$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_48S4X_PLATFORM_MODULE)))
|
||||
|
||||
CENTEC_E530_24X2Q_PLATFORM_MODULE = platform-modules-e530-24x2q_$(CENTEC_E530_24X2Q_PLATFORM_MODULE_VERSION)_arm64.deb
|
||||
$(CENTEC_E530_24X2Q_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2q-r0
|
||||
$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2Q_PLATFORM_MODULE)))
|
||||
|
@ -4,43 +4,45 @@
|
||||
|
||||
echo "Preparing for installation ... "
|
||||
|
||||
demo_mnt=/mnt
|
||||
|
||||
hw_load() {
|
||||
echo "ext4load mmc 0:2 \$loadaddr onie_uimage"
|
||||
}
|
||||
|
||||
create_partition() {
|
||||
echo y | mkfs.ext4 -L CTC-SYSTEM /dev/mmcblk0p1
|
||||
}
|
||||
|
||||
mount_partition() {
|
||||
echo "mount flash"
|
||||
echo "mount flash partition"
|
||||
demo_mnt=/mnt
|
||||
mount -t ext4 /dev/mmcblk0p1 $demo_mnt
|
||||
}
|
||||
|
||||
bootloader_menu_config() {
|
||||
mkdir -p $demo_mnt/boot
|
||||
mount -t ext4 /dev/mmcblk0p2 $demo_mnt/boot
|
||||
|
||||
rm $demo_mnt/boot/centec-e530.itb -rf
|
||||
cp $demo_mnt/$image_dir/boot/sonic_arm64.fit $demo_mnt/boot/centec-e530.itb
|
||||
cd $demo_mnt/boot
|
||||
rm onie_uimage -rf
|
||||
ln -s centec-e530.itb onie_uimage
|
||||
cd -
|
||||
sync
|
||||
umount -l $demo_mnt/boot
|
||||
if [ "$install_env" = "onie" ]; then
|
||||
fw_setenv -f nos_bootcmd "test -n \$boot_once && setenv do_boot_once \$boot_once && setenv boot_once && saveenv && run do_boot_once; run boot_next"
|
||||
|
||||
hw_load_str="$(hw_load)"
|
||||
fw_setenv -f sonic_image_1 "ext4load mmc 0:1 \$loadaddr \$sonic_dir_1/boot/sonic_arm64.fit && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=\$sonic_dir_1/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr"
|
||||
fw_setenv -f sonic_image_2 "NONE"
|
||||
fw_setenv -f sonic_dir_1 $image_dir
|
||||
fw_setenv -f sonic_dir_2 "NONE"
|
||||
fw_setenv -f sonic_version_1 `echo $image_dir | sed "s/^image-/SONiC-OS-/g"`
|
||||
fw_setenv -f sonic_version_2 "NONE"
|
||||
|
||||
(cat <<EOF
|
||||
hw_load $hw_load_str
|
||||
copy_img echo "Loading Demo $platform image..." && run hw_load
|
||||
nos_bootcmd run copy_img && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=$image_dir/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr
|
||||
EOF
|
||||
) > /tmp/env.txt
|
||||
fw_setenv -f boot_next "run sonic_image_1"
|
||||
else
|
||||
running_sonic_revision=`cat /etc/sonic/sonic_version.yml | grep build_version | awk -F \' '{print $2}'`
|
||||
SONIC_IMAGE_MAX=2
|
||||
idx=0
|
||||
for i in $(seq 1 $SONIC_IMAGE_MAX); do
|
||||
if [ "`fw_printenv sonic_version_$i 2>/dev/null | awk -F = '{print $2}'`" != "SONiC-OS-$running_sonic_revision" ]; then
|
||||
idx=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
fw_setenv -f -s /tmp/env.txt
|
||||
fw_setenv -f image_dir $image_dir
|
||||
fw_setenv nos_bootcmd "test -n \$boot_once && setenv do_boot_once \$boot_once && setenv boot_once && saveenv && run do_boot_once; run boot_next"
|
||||
|
||||
fw_setenv sonic_image_$idx "ext4load mmc 0:1 \$loadaddr \$sonic_dir_$idx/boot/sonic_arm64.fit && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=\$sonic_dir_$idx/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr"
|
||||
fw_setenv sonic_dir_$idx $image_dir
|
||||
fw_setenv sonic_version_$idx `echo $image_dir | sed "s/^image-/SONiC-OS-/g"`
|
||||
|
||||
fw_setenv boot_next "run sonic_image_$idx"
|
||||
fi
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Centec SAI
|
||||
|
||||
export CENTEC_SAI_VERSION = 1.6.3-1
|
||||
export CENTEC_SAI_VERSION = 1.7.1-1
|
||||
export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb
|
||||
|
||||
$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI)
|
||||
|
@ -5,11 +5,11 @@ from setuptools import setup
|
||||
os.listdir
|
||||
|
||||
setup(
|
||||
name='24x2c',
|
||||
version='1.1',
|
||||
name='sonic_platform',
|
||||
version='1.0',
|
||||
description='Module to initialize centec e530-24x2c platforms',
|
||||
|
||||
packages=['24x2c'],
|
||||
package_dir={'24x2c': '24x2c/classes'},
|
||||
packages=['sonic_platform'],
|
||||
package_dir={'sonic_platform': 'sonic_platform'},
|
||||
)
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
|
||||
from . import platform
|
||||
|
@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: chassis.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
import os
|
||||
import re
|
||||
import collections
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
from .fan_drawer import FanDrawer
|
||||
from .thermal import Thermal
|
||||
from .sfp import Sfp
|
||||
from .psu import Psu
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
NUM_FAN_TRAY = 1
|
||||
NUM_THERMAL = 1
|
||||
NUM_PSU = 2
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Chassis(ChassisBase):
|
||||
|
||||
def __init__(self):
|
||||
ChassisBase.__init__(self)
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
raise
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"])
|
||||
try:
|
||||
f = open(port_config_file)
|
||||
except:
|
||||
raise
|
||||
for line in f:
|
||||
line.strip()
|
||||
if re.search('^#', line) is not None:
|
||||
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
|
||||
break
|
||||
f.close()
|
||||
f = open(port_config_file)
|
||||
_port_cfgs = [Port_cfg(*tuple((line.strip().split())))
|
||||
for line in f if re.search('^#', line) is None]
|
||||
f.close()
|
||||
|
||||
# Initialize EEPROM
|
||||
self._eeprom = Eeprom()
|
||||
# Initialize FAN
|
||||
for i in range(NUM_FAN_TRAY):
|
||||
fandrawer = FanDrawer(i)
|
||||
self._fan_drawer_list.append(fandrawer)
|
||||
self._fan_list.extend(fandrawer._fan_list)
|
||||
# Initialize THERMAL
|
||||
for index in range(0, NUM_THERMAL):
|
||||
thermal = Thermal(index)
|
||||
self._thermal_list.append(thermal)
|
||||
# Initialize SFP
|
||||
for port_cfg in _port_cfgs:
|
||||
sfp = Sfp(int(port_cfg.index))
|
||||
self._sfp_list.append(sfp)
|
||||
# Initialize PSU
|
||||
for index in range(0, NUM_PSU):
|
||||
psu = Psu(index + 1)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
##############################################
|
||||
# Device methods
|
||||
##############################################
|
||||
|
||||
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
|
||||
Returns:
|
||||
string: Serial number of chassis
|
||||
"""
|
||||
return self._eeprom.serial_number_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
|
||||
|
||||
##############################################
|
||||
# Chassis methods
|
||||
##############################################
|
||||
|
||||
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.
|
||||
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
|
||||
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
|
||||
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
|
||||
"""
|
||||
return self._eeprom.system_eeprom_info()
|
||||
|
||||
def get_reboot_cause(self):
|
||||
"""
|
||||
Retrieves the cause of the previous reboot
|
||||
Returns:
|
||||
A tuple (string, string) where the first element is a string
|
||||
containing the cause of the previous reboot. This string must be
|
||||
one of the predefined strings in this class. If the first string
|
||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||
to pass a description of the reboot cause.
|
||||
"""
|
||||
return (None, None)
|
||||
|
||||
def get_change_event(self, timeout=2000):
|
||||
"""
|
||||
Returns a nested dictionary containing all devices which have
|
||||
experienced a change at chassis level
|
||||
|
||||
Args:
|
||||
timeout: Timeout in milliseconds (optional). If timeout == 0,
|
||||
this method will block until a change is detected.
|
||||
|
||||
Returns:
|
||||
(bool, dict):
|
||||
- True if call successful, False if not;
|
||||
- A nested dictionary where key is a device type,
|
||||
value is a dictionary with key:value pairs in the
|
||||
format of {'device_id':'device_event'},
|
||||
where device_id is the device ID for this device and
|
||||
device_event,
|
||||
status='1' represents device inserted,
|
||||
status='0' represents device removed.
|
||||
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
|
||||
indicates that fan 0 has been removed, fan 2
|
||||
has been inserted and sfp 11 has been removed.
|
||||
"""
|
||||
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
|
||||
ret_dict = {"sfp": port_dict}
|
||||
return ret, ret_dict
|
||||
|
||||
def get_num_psus(self):
|
||||
return len(self._psu_list)
|
||||
|
||||
def get_psu(self, psu_index):
|
||||
return self._psu_list[psu_index]
|
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: eeprom.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
import binascii
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self):
|
||||
self.__eeprom_path = "/dev/mtd3"
|
||||
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
|
||||
self.__eeprom_tlv_dict = dict()
|
||||
try:
|
||||
self.open_eeprom()
|
||||
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 = (eeprom[9] << 8) | 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
|
||||
+ eeprom[tlv_index + 1]]
|
||||
code = "0x%02X" % (tlv[0])
|
||||
|
||||
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
|
||||
value = str((tlv[2] << 24) | (tlv[3] << 16) |
|
||||
(tlv[4] << 8) | tlv[5])
|
||||
value += str(tlv[6:6 + tlv[1]])
|
||||
else:
|
||||
name, value = self.decoder(None, tlv)
|
||||
|
||||
self.__eeprom_tlv_dict[code] = value
|
||||
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
|
||||
break
|
||||
|
||||
tlv_index += eeprom[tlv_index+1] + 2
|
||||
|
||||
def serial_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def base_mac_addr(self):
|
||||
(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):
|
||||
(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].decode('ascii')
|
||||
|
||||
def part_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def serial_tag_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def revision_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
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
|
||||
|
@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Celestica
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the fan status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import math
|
||||
import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_base import FanBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
FAN_PATH = "/sys/class/hwmon/hwmon1/"
|
||||
FAN_MAX_PWM = 255
|
||||
FAN_FAN_PWM = "pwm{}"
|
||||
FAN_FAN_INPUT = "fan{}_input"
|
||||
FAN_MAX_RPM = 9000
|
||||
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
|
||||
|
||||
class Fan(FanBase):
|
||||
"""Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fan_tray_index, fan_index=0):
|
||||
self.fan_index = fan_index
|
||||
self.fan_tray_index = fan_tray_index
|
||||
|
||||
FanBase.__init__(self)
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def __write_txt_file(self, file_path, value):
|
||||
try:
|
||||
with open(file_path, 'w') as fd:
|
||||
fd.write(str(value))
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __search_file_by_name(self, directory, file_name):
|
||||
for dirpath, dirnames, files in os.walk(directory):
|
||||
for name in files:
|
||||
file_path = os.path.join(dirpath, name)
|
||||
if name in file_name:
|
||||
return file_path
|
||||
return None
|
||||
|
||||
def get_direction(self):
|
||||
"""
|
||||
Retrieves the direction of fan
|
||||
Returns:
|
||||
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||
depending on fan direction
|
||||
"""
|
||||
direction = self.FAN_DIRECTION_EXHAUST
|
||||
return direction
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Retrieves the speed of fan as a percentage of full speed
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed = pwm_in/255*100
|
||||
"""
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return int(speed)
|
||||
|
||||
def get_target_speed(self):
|
||||
"""
|
||||
Retrieves the target (expected) speed of the fan
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed_pc = pwm_target/255*100
|
||||
|
||||
0 : when PWM mode is use
|
||||
pwm : when pwm mode is not use
|
||||
"""
|
||||
# target = 0
|
||||
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
# fan_target_sysfs_path = self.__search_file_by_name(
|
||||
# FAN_PATH, fan_target_sysfs_name)
|
||||
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
|
||||
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
|
||||
|
||||
# return target
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return speed
|
||||
|
||||
def get_speed_tolerance(self):
|
||||
"""
|
||||
Retrieves the speed tolerance of the fan
|
||||
Returns:
|
||||
An integer, the percentage of variance from target speed which is
|
||||
considered tolerable
|
||||
"""
|
||||
return 10
|
||||
|
||||
def set_speed(self, speed):
|
||||
"""
|
||||
Sets the fan speed
|
||||
Args:
|
||||
speed: An integer, the percentage of full fan speed to set fan to,
|
||||
in the range 0 (off) to 100 (full speed)
|
||||
Returns:
|
||||
A boolean, True if speed is set successfully, False if not
|
||||
|
||||
Note:
|
||||
Depends on pwm or target mode is selected:
|
||||
1) pwm = speed_pc * 255 <-- Currently use this mode.
|
||||
2) target_pwm = speed_pc * 100 / 255
|
||||
2.1) set pwm{}_enable to 3
|
||||
|
||||
"""
|
||||
pwm = speed * 255 / 100
|
||||
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
fan_target_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_target_sysfs_name)
|
||||
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
|
||||
|
||||
def set_status_led(self, color):
|
||||
"""
|
||||
Sets the state of the fan module status LED
|
||||
Args:
|
||||
color: A string representing the color with which to set the
|
||||
fan module status LED
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
fan_name = FAN_NAME_LIST[self.fan_index]
|
||||
|
||||
return fan_name
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
|
||||
return True
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the status of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# Centec E530 24x2c
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the Fan-Drawers' information available in the platform.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
||||
from .fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
CENTEC_FANS_PER_FANTRAY = 3
|
||||
|
||||
|
||||
class FanDrawer(FanDrawerBase):
|
||||
"""Centec E530 24x2c Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fantray_index):
|
||||
|
||||
FanDrawerBase.__init__(self)
|
||||
self.fantrayindex = fantray_index
|
||||
for i in range(CENTEC_FANS_PER_FANTRAY):
|
||||
self._fan_list.append(Fan(fantray_index, i))
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the fan drawer name
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
return "FanTray{}".format(self.fantrayindex)
|
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: platform.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-24X2C
|
||||
#
|
||||
|
||||
|
||||
try:
|
||||
from sonic_platform_base.platform_base import PlatformBase
|
||||
from sonic_platform.chassis import Chassis
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Platform(PlatformBase):
|
||||
|
||||
def __init__(self):
|
||||
PlatformBase.__init__(self)
|
||||
self._chassis = Chassis()
|
||||
|
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import imp
|
||||
import os
|
||||
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % e)
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Psu(PsuBase):
|
||||
"""Centec Platform-specific PSU class"""
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
self._fan_list = []
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
return
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
|
||||
module = imp.load_source("psuutil", module_file)
|
||||
psu_util_class = getattr(module, "PsuUtil")
|
||||
self._psuutil = psu_util_class()
|
||||
|
||||
def _get_psuutil(self):
|
||||
return self._psuutil
|
||||
|
||||
def get_presence(self):
|
||||
return self._get_psuutil().get_psu_presence(self._index)
|
||||
|
||||
def get_powergood_status(self):
|
||||
return self._get_psuutil().get_psu_status(self._index)
|
@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import imp
|
||||
import os
|
||||
|
||||
try:
|
||||
from sonic_platform_base.sfp_base import SfpBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % e)
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Sfp(SfpBase):
|
||||
"""
|
||||
Platform-specific sfp class
|
||||
|
||||
Unimplemented methods:
|
||||
- get_model
|
||||
- get_serial
|
||||
- get_status
|
||||
- get_transceiver_info
|
||||
- get_transceiver_bulk_status
|
||||
- get_transceiver_threshold_info
|
||||
- get_reset_status
|
||||
- get_rx_los
|
||||
- get_tx_fault
|
||||
- get_tx_disable_channel
|
||||
- get_power_override
|
||||
- get_temperature
|
||||
- get_voltage
|
||||
- get_tx_bias
|
||||
- get_rx_power
|
||||
- get_tx_power
|
||||
- tx_disable_channel
|
||||
- set_power_override
|
||||
"""
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
return
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
module_file = "/".join([platform_path, "plugins", "sfputil.py"])
|
||||
module = imp.load_source("sfputil", module_file)
|
||||
sfp_util_class = getattr(module, "SfpUtil")
|
||||
self._sfputil = sfp_util_class()
|
||||
|
||||
def get_id(self):
|
||||
return self._index
|
||||
|
||||
def get_name(self):
|
||||
return "Ethernet{}".format(self._index)
|
||||
|
||||
def get_lpmode(self):
|
||||
return False
|
||||
|
||||
def set_lpmode(self, lpmode):
|
||||
return False
|
||||
|
||||
def get_tx_disable(self):
|
||||
return False
|
||||
|
||||
def tx_disable(self, tx_disable):
|
||||
return False
|
||||
|
||||
def reset(self):
|
||||
pass
|
||||
|
||||
def clear_interrupt(self):
|
||||
return False
|
||||
|
||||
def get_interrupt_file(self):
|
||||
return None
|
||||
|
||||
def _get_sfputil(self):
|
||||
return self._sfputil
|
||||
|
||||
def get_presence(self):
|
||||
return self._get_sfputil().get_presence(self._index)
|
||||
|
||||
def get_transceiver_info(self):
|
||||
return self._get_sfputil().get_transceiver_info_dict(self._index)
|
||||
|
||||
def get_transceiver_bulk_status(self):
|
||||
return self._get_sfputil().get_transceiver_dom_info_dict(self._index)
|
||||
|
||||
def get_transceiver_threshold_info(self):
|
||||
return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index)
|
||||
|
||||
def get_transceiver_change_event(self, timeout):
|
||||
return self._get_sfputil().get_transceiver_change_event(timeout)
|
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Celestica
|
||||
#
|
||||
# Thermal contains an implementation of SONiC Platform Base API and
|
||||
# provides the thermal device status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.thermal_base import ThermalBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Thermal(ThermalBase):
|
||||
"""Platform-specific Thermal class"""
|
||||
|
||||
THERMAL_NAME_LIST = []
|
||||
CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1"
|
||||
|
||||
def __init__(self, thermal_index):
|
||||
self.index = thermal_index
|
||||
self.high_threshold = float(112)
|
||||
|
||||
# Add thermal name
|
||||
self.THERMAL_NAME_LIST.append("SENSOR-1")
|
||||
|
||||
# Set hwmon path
|
||||
self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH
|
||||
self.ss_key = self.THERMAL_NAME_LIST[self.index - 1]
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
raise IOError("Unable to open %s file !" % file_path)
|
||||
|
||||
def __get_temp(self, temp_file):
|
||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||
raw_temp = self.__read_txt_file(temp_file_path)
|
||||
temp = float(raw_temp)/1000
|
||||
return float("{:.3f}".format(temp))
|
||||
|
||||
def __set_threshold(self, file_name, temperature):
|
||||
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
||||
try:
|
||||
with open(temp_file_path, 'w') as fd:
|
||||
fd.write(str(temperature))
|
||||
return True
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
def get_temperature(self):
|
||||
"""
|
||||
Retrieves current temperature reading from thermal
|
||||
Returns:
|
||||
A float number of current temperature in Celsius up to nearest thousandth
|
||||
of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
temp_file = "temp{}_input".format(self.ss_index)
|
||||
return self.__get_temp(temp_file)
|
||||
|
||||
def get_high_threshold(self):
|
||||
"""
|
||||
Retrieves the high threshold temperature of thermal
|
||||
Returns:
|
||||
A float number, the high threshold temperature of thermal in Celsius
|
||||
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
return self.high_threshold
|
||||
|
||||
def set_high_threshold(self, temperature):
|
||||
"""
|
||||
Sets the high threshold temperature of thermal
|
||||
Args :
|
||||
temperature: A float number up to nearest thousandth of one degree Celsius,
|
||||
e.g. 30.125
|
||||
Returns:
|
||||
A boolean, True if threshold is set successfully, False if not
|
||||
"""
|
||||
self.high_threshold = float(temperature)
|
||||
return True
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the thermal device
|
||||
Returns:
|
||||
string: The name of the thermal device
|
||||
"""
|
||||
return self.THERMAL_NAME_LIST[self.index]
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the PSU
|
||||
Returns:
|
||||
bool: True if PSU is present, False if not
|
||||
"""
|
||||
temp_file = "temp{}_input".format(self.ss_index)
|
||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||
return os.path.isfile(temp_file_path)
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the device
|
||||
Returns:
|
||||
A boolean value, True if device is operating properly, False if not
|
||||
"""
|
||||
if not self.get_presence():
|
||||
return False
|
||||
|
||||
return True
|
@ -0,0 +1 @@
|
||||
obj-m := centec_e530_24x2q_platform.o
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Centec modules init
|
||||
After=local-fs.target
|
||||
Before=syncd.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=-/etc/init.d/platform-modules-e530-24x2q start
|
||||
ExecStop=-/etc/init.d/platform-modules-e530-24x2q stop
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
from setuptools import setup
|
||||
os.listdir
|
||||
|
||||
setup(
|
||||
name='sonic_platform',
|
||||
version='1.0',
|
||||
description='Module to initialize centec e530-24x2q platforms',
|
||||
|
||||
packages=['sonic_platform'],
|
||||
package_dir={'sonic_platform': 'sonic_platform'},
|
||||
)
|
||||
|
@ -0,0 +1,3 @@
|
||||
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
|
||||
from . import platform
|
||||
|
@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: chassis.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
import os
|
||||
import re
|
||||
import collections
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
from .fan_drawer import FanDrawer
|
||||
from .thermal import Thermal
|
||||
from .sfp import Sfp
|
||||
from .psu import Psu
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
NUM_FAN_TRAY = 1
|
||||
NUM_THERMAL = 1
|
||||
NUM_PSU = 2
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Chassis(ChassisBase):
|
||||
|
||||
def __init__(self):
|
||||
ChassisBase.__init__(self)
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
raise
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"])
|
||||
try:
|
||||
f = open(port_config_file)
|
||||
except:
|
||||
raise
|
||||
for line in f:
|
||||
line.strip()
|
||||
if re.search('^#', line) is not None:
|
||||
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
|
||||
break
|
||||
f.close()
|
||||
f = open(port_config_file)
|
||||
_port_cfgs = [Port_cfg(*tuple((line.strip().split())))
|
||||
for line in f if re.search('^#', line) is None]
|
||||
f.close()
|
||||
|
||||
# Initialize EEPROM
|
||||
self._eeprom = Eeprom()
|
||||
# Initialize FAN
|
||||
for i in range(NUM_FAN_TRAY):
|
||||
fandrawer = FanDrawer(i)
|
||||
self._fan_drawer_list.append(fandrawer)
|
||||
self._fan_list.extend(fandrawer._fan_list)
|
||||
# Initialize THERMAL
|
||||
for index in range(0, NUM_THERMAL):
|
||||
thermal = Thermal(index)
|
||||
self._thermal_list.append(thermal)
|
||||
# Initialize SFP
|
||||
for port_cfg in _port_cfgs:
|
||||
sfp = Sfp(int(port_cfg.index))
|
||||
self._sfp_list.append(sfp)
|
||||
# Initialize PSU
|
||||
for index in range(0, NUM_PSU):
|
||||
psu = Psu(index + 1)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
##############################################
|
||||
# Device methods
|
||||
##############################################
|
||||
|
||||
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
|
||||
Returns:
|
||||
string: Serial number of chassis
|
||||
"""
|
||||
return self._eeprom.serial_number_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
|
||||
|
||||
##############################################
|
||||
# Chassis methods
|
||||
##############################################
|
||||
|
||||
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.
|
||||
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
|
||||
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
|
||||
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
|
||||
"""
|
||||
return self._eeprom.system_eeprom_info()
|
||||
|
||||
def get_reboot_cause(self):
|
||||
"""
|
||||
Retrieves the cause of the previous reboot
|
||||
Returns:
|
||||
A tuple (string, string) where the first element is a string
|
||||
containing the cause of the previous reboot. This string must be
|
||||
one of the predefined strings in this class. If the first string
|
||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||
to pass a description of the reboot cause.
|
||||
"""
|
||||
return (None, None)
|
||||
|
||||
def get_change_event(self, timeout=2000):
|
||||
"""
|
||||
Returns a nested dictionary containing all devices which have
|
||||
experienced a change at chassis level
|
||||
|
||||
Args:
|
||||
timeout: Timeout in milliseconds (optional). If timeout == 0,
|
||||
this method will block until a change is detected.
|
||||
|
||||
Returns:
|
||||
(bool, dict):
|
||||
- True if call successful, False if not;
|
||||
- A nested dictionary where key is a device type,
|
||||
value is a dictionary with key:value pairs in the
|
||||
format of {'device_id':'device_event'},
|
||||
where device_id is the device ID for this device and
|
||||
device_event,
|
||||
status='1' represents device inserted,
|
||||
status='0' represents device removed.
|
||||
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
|
||||
indicates that fan 0 has been removed, fan 2
|
||||
has been inserted and sfp 11 has been removed.
|
||||
"""
|
||||
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
|
||||
ret_dict = {"sfp": port_dict}
|
||||
return ret, ret_dict
|
||||
|
||||
def get_num_psus(self):
|
||||
return len(self._psu_list)
|
||||
|
||||
def get_psu(self, psu_index):
|
||||
return self._psu_list[psu_index]
|
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: eeprom.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
import binascii
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self):
|
||||
self.__eeprom_path = "/dev/mtd3"
|
||||
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
|
||||
self.__eeprom_tlv_dict = dict()
|
||||
try:
|
||||
self.open_eeprom()
|
||||
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 = (eeprom[9] << 8) | 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
|
||||
+ eeprom[tlv_index + 1]]
|
||||
code = "0x%02X" % (tlv[0])
|
||||
|
||||
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
|
||||
value = str((tlv[2] << 24) | (tlv[3] << 16) |
|
||||
(tlv[4] << 8) | tlv[5])
|
||||
value += str(tlv[6:6 + tlv[1]])
|
||||
else:
|
||||
name, value = self.decoder(None, tlv)
|
||||
|
||||
self.__eeprom_tlv_dict[code] = value
|
||||
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
|
||||
break
|
||||
|
||||
tlv_index += eeprom[tlv_index+1] + 2
|
||||
|
||||
def serial_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def base_mac_addr(self):
|
||||
(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):
|
||||
(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].decode('ascii')
|
||||
|
||||
def part_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def serial_tag_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def revision_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
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
|
||||
|
@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Celestica
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the fan status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import math
|
||||
import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_base import FanBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
FAN_PATH = "/sys/class/hwmon/hwmon1/"
|
||||
FAN_MAX_PWM = 255
|
||||
FAN_FAN_PWM = "pwm{}"
|
||||
FAN_FAN_INPUT = "fan{}_input"
|
||||
FAN_MAX_RPM = 9000
|
||||
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
|
||||
|
||||
class Fan(FanBase):
|
||||
"""Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fan_tray_index, fan_index=0):
|
||||
self.fan_index = fan_index
|
||||
self.fan_tray_index = fan_tray_index
|
||||
|
||||
FanBase.__init__(self)
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def __write_txt_file(self, file_path, value):
|
||||
try:
|
||||
with open(file_path, 'w') as fd:
|
||||
fd.write(str(value))
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __search_file_by_name(self, directory, file_name):
|
||||
for dirpath, dirnames, files in os.walk(directory):
|
||||
for name in files:
|
||||
file_path = os.path.join(dirpath, name)
|
||||
if name in file_name:
|
||||
return file_path
|
||||
return None
|
||||
|
||||
def get_direction(self):
|
||||
"""
|
||||
Retrieves the direction of fan
|
||||
Returns:
|
||||
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||
depending on fan direction
|
||||
"""
|
||||
direction = self.FAN_DIRECTION_EXHAUST
|
||||
return direction
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Retrieves the speed of fan as a percentage of full speed
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed = pwm_in/255*100
|
||||
"""
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return int(speed)
|
||||
|
||||
def get_target_speed(self):
|
||||
"""
|
||||
Retrieves the target (expected) speed of the fan
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed_pc = pwm_target/255*100
|
||||
|
||||
0 : when PWM mode is use
|
||||
pwm : when pwm mode is not use
|
||||
"""
|
||||
# target = 0
|
||||
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
# fan_target_sysfs_path = self.__search_file_by_name(
|
||||
# FAN_PATH, fan_target_sysfs_name)
|
||||
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
|
||||
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
|
||||
|
||||
# return target
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return speed
|
||||
|
||||
def get_speed_tolerance(self):
|
||||
"""
|
||||
Retrieves the speed tolerance of the fan
|
||||
Returns:
|
||||
An integer, the percentage of variance from target speed which is
|
||||
considered tolerable
|
||||
"""
|
||||
return 10
|
||||
|
||||
def set_speed(self, speed):
|
||||
"""
|
||||
Sets the fan speed
|
||||
Args:
|
||||
speed: An integer, the percentage of full fan speed to set fan to,
|
||||
in the range 0 (off) to 100 (full speed)
|
||||
Returns:
|
||||
A boolean, True if speed is set successfully, False if not
|
||||
|
||||
Note:
|
||||
Depends on pwm or target mode is selected:
|
||||
1) pwm = speed_pc * 255 <-- Currently use this mode.
|
||||
2) target_pwm = speed_pc * 100 / 255
|
||||
2.1) set pwm{}_enable to 3
|
||||
|
||||
"""
|
||||
pwm = speed * 255 / 100
|
||||
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
fan_target_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_target_sysfs_name)
|
||||
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
|
||||
|
||||
def set_status_led(self, color):
|
||||
"""
|
||||
Sets the state of the fan module status LED
|
||||
Args:
|
||||
color: A string representing the color with which to set the
|
||||
fan module status LED
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
fan_name = FAN_NAME_LIST[self.fan_index]
|
||||
|
||||
return fan_name
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
|
||||
return True
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the status of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# Centec E530 24x2q
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the Fan-Drawers' information available in the platform.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
||||
from .fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
CENTEC_FANS_PER_FANTRAY = 3
|
||||
|
||||
|
||||
class FanDrawer(FanDrawerBase):
|
||||
"""Centec E530 24x2q Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fantray_index):
|
||||
|
||||
FanDrawerBase.__init__(self)
|
||||
self.fantrayindex = fantray_index
|
||||
for i in range(CENTEC_FANS_PER_FANTRAY):
|
||||
self._fan_list.append(Fan(fantray_index, i))
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the fan drawer name
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
return "FanTray{}".format(self.fantrayindex)
|
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: platform.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-24X2Q
|
||||
#
|
||||
|
||||
|
||||
try:
|
||||
from sonic_platform_base.platform_base import PlatformBase
|
||||
from sonic_platform.chassis import Chassis
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Platform(PlatformBase):
|
||||
|
||||
def __init__(self):
|
||||
PlatformBase.__init__(self)
|
||||
self._chassis = Chassis()
|
||||
|
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import imp
|
||||
import os
|
||||
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % e)
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Psu(PsuBase):
|
||||
"""Centec Platform-specific PSU class"""
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
self._fan_list = []
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
return
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
|
||||
module = imp.load_source("psuutil", module_file)
|
||||
psu_util_class = getattr(module, "PsuUtil")
|
||||
self._psuutil = psu_util_class()
|
||||
|
||||
def _get_psuutil(self):
|
||||
return self._psuutil
|
||||
|
||||
def get_presence(self):
|
||||
return self._get_psuutil().get_psu_presence(self._index)
|
||||
|
||||
def get_powergood_status(self):
|
||||
return self._get_psuutil().get_psu_status(self._index)
|
@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import imp
|
||||
import os
|
||||
|
||||
try:
|
||||
from sonic_platform_base.sfp_base import SfpBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % e)
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Sfp(SfpBase):
|
||||
"""
|
||||
Platform-specific sfp class
|
||||
|
||||
Unimplemented methods:
|
||||
- get_model
|
||||
- get_serial
|
||||
- get_status
|
||||
- get_transceiver_info
|
||||
- get_transceiver_bulk_status
|
||||
- get_transceiver_threshold_info
|
||||
- get_reset_status
|
||||
- get_rx_los
|
||||
- get_tx_fault
|
||||
- get_tx_disable_channel
|
||||
- get_power_override
|
||||
- get_temperature
|
||||
- get_voltage
|
||||
- get_tx_bias
|
||||
- get_rx_power
|
||||
- get_tx_power
|
||||
- tx_disable_channel
|
||||
- set_power_override
|
||||
"""
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
return
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
module_file = "/".join([platform_path, "plugins", "sfputil.py"])
|
||||
module = imp.load_source("sfputil", module_file)
|
||||
sfp_util_class = getattr(module, "SfpUtil")
|
||||
self._sfputil = sfp_util_class()
|
||||
|
||||
def get_id(self):
|
||||
return self._index
|
||||
|
||||
def get_name(self):
|
||||
return "Ethernet{}".format(self._index)
|
||||
|
||||
def get_lpmode(self):
|
||||
return False
|
||||
|
||||
def set_lpmode(self, lpmode):
|
||||
return False
|
||||
|
||||
def get_tx_disable(self):
|
||||
return False
|
||||
|
||||
def tx_disable(self, tx_disable):
|
||||
return False
|
||||
|
||||
def reset(self):
|
||||
pass
|
||||
|
||||
def clear_interrupt(self):
|
||||
return False
|
||||
|
||||
def get_interrupt_file(self):
|
||||
return None
|
||||
|
||||
def _get_sfputil(self):
|
||||
return self._sfputil
|
||||
|
||||
def get_presence(self):
|
||||
return self._get_sfputil().get_presence(self._index)
|
||||
|
||||
def get_transceiver_info(self):
|
||||
return self._get_sfputil().get_transceiver_info_dict(self._index)
|
||||
|
||||
def get_transceiver_bulk_status(self):
|
||||
return self._get_sfputil().get_transceiver_dom_info_dict(self._index)
|
||||
|
||||
def get_transceiver_threshold_info(self):
|
||||
return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index)
|
||||
|
||||
def get_transceiver_change_event(self, timeout):
|
||||
return self._get_sfputil().get_transceiver_change_event(timeout)
|
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Celestica
|
||||
#
|
||||
# Thermal contains an implementation of SONiC Platform Base API and
|
||||
# provides the thermal device status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.thermal_base import ThermalBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Thermal(ThermalBase):
|
||||
"""Platform-specific Thermal class"""
|
||||
|
||||
THERMAL_NAME_LIST = []
|
||||
CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1"
|
||||
|
||||
def __init__(self, thermal_index):
|
||||
self.index = thermal_index
|
||||
self.high_threshold = float(112)
|
||||
|
||||
# Add thermal name
|
||||
self.THERMAL_NAME_LIST.append("SENSOR-1")
|
||||
|
||||
# Set hwmon path
|
||||
self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH
|
||||
self.ss_key = self.THERMAL_NAME_LIST[self.index - 1]
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
raise IOError("Unable to open %s file !" % file_path)
|
||||
|
||||
def __get_temp(self, temp_file):
|
||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||
raw_temp = self.__read_txt_file(temp_file_path)
|
||||
temp = float(raw_temp)/1000
|
||||
return float("{:.3f}".format(temp))
|
||||
|
||||
def __set_threshold(self, file_name, temperature):
|
||||
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
||||
try:
|
||||
with open(temp_file_path, 'w') as fd:
|
||||
fd.write(str(temperature))
|
||||
return True
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
def get_temperature(self):
|
||||
"""
|
||||
Retrieves current temperature reading from thermal
|
||||
Returns:
|
||||
A float number of current temperature in Celsius up to nearest thousandth
|
||||
of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
temp_file = "temp{}_input".format(self.ss_index)
|
||||
return self.__get_temp(temp_file)
|
||||
|
||||
def get_high_threshold(self):
|
||||
"""
|
||||
Retrieves the high threshold temperature of thermal
|
||||
Returns:
|
||||
A float number, the high threshold temperature of thermal in Celsius
|
||||
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
return self.high_threshold
|
||||
|
||||
def set_high_threshold(self, temperature):
|
||||
"""
|
||||
Sets the high threshold temperature of thermal
|
||||
Args :
|
||||
temperature: A float number up to nearest thousandth of one degree Celsius,
|
||||
e.g. 30.125
|
||||
Returns:
|
||||
A boolean, True if threshold is set successfully, False if not
|
||||
"""
|
||||
self.high_threshold = float(temperature)
|
||||
return True
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the thermal device
|
||||
Returns:
|
||||
string: The name of the thermal device
|
||||
"""
|
||||
return self.THERMAL_NAME_LIST[self.index]
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the PSU
|
||||
Returns:
|
||||
bool: True if PSU is present, False if not
|
||||
"""
|
||||
temp_file = "temp{}_input".format(self.ss_index)
|
||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||
return os.path.isfile(temp_file_path)
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the device
|
||||
Returns:
|
||||
A boolean value, True if device is operating properly, False if not
|
||||
"""
|
||||
if not self.get_presence():
|
||||
return False
|
||||
|
||||
return True
|
@ -0,0 +1 @@
|
||||
obj-m := centec_e530_48s4x_platform.o
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Centec modules init
|
||||
After=local-fs.target
|
||||
Before=syncd.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=-/etc/init.d/platform-modules-e530-48s4x start
|
||||
ExecStop=-/etc/init.d/platform-modules-e530-48s4x stop
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
from setuptools import setup
|
||||
os.listdir
|
||||
|
||||
setup(
|
||||
name='sonic_platform',
|
||||
version='1.0',
|
||||
description='Module to initialize centec e530-48s4x platforms',
|
||||
|
||||
packages=['sonic_platform'],
|
||||
package_dir={'sonic_platform': 'sonic_platform'},
|
||||
)
|
||||
|
@ -0,0 +1,3 @@
|
||||
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
|
||||
from . import platform
|
||||
|
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: chassis.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
from .fan_drawer import FanDrawer
|
||||
from .thermal import Thermal
|
||||
from .sfp import Sfp
|
||||
from .psu import Psu
|
||||
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
NUM_FAN_TRAY = 1
|
||||
NUM_THERMAL = 1
|
||||
NUM_PORT = 52
|
||||
NUM_PSU = 2
|
||||
|
||||
class Chassis(ChassisBase):
|
||||
|
||||
def __init__(self):
|
||||
ChassisBase.__init__(self)
|
||||
# Initialize EEPROM
|
||||
self._eeprom = Eeprom()
|
||||
# Initialize FAN
|
||||
for i in range(NUM_FAN_TRAY):
|
||||
fandrawer = FanDrawer(i)
|
||||
self._fan_drawer_list.append(fandrawer)
|
||||
self._fan_list.extend(fandrawer._fan_list)
|
||||
# Initialize THERMAL
|
||||
for index in range(0, NUM_THERMAL):
|
||||
thermal = Thermal(index)
|
||||
self._thermal_list.append(thermal)
|
||||
# Initialize SFP
|
||||
for index in range(0, NUM_PORT):
|
||||
sfp = Sfp(index)
|
||||
self._sfp_list.append(sfp)
|
||||
# Initialize PSU
|
||||
for index in range(0, NUM_PSU):
|
||||
psu = Psu(index + 1)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
##############################################
|
||||
# Device methods
|
||||
##############################################
|
||||
|
||||
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
|
||||
Returns:
|
||||
string: Serial number of chassis
|
||||
"""
|
||||
return self._eeprom.serial_number_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
|
||||
|
||||
##############################################
|
||||
# Chassis methods
|
||||
##############################################
|
||||
|
||||
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.
|
||||
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
|
||||
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
|
||||
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
|
||||
"""
|
||||
return self._eeprom.system_eeprom_info()
|
||||
|
||||
def get_reboot_cause(self):
|
||||
"""
|
||||
Retrieves the cause of the previous reboot
|
||||
Returns:
|
||||
A tuple (string, string) where the first element is a string
|
||||
containing the cause of the previous reboot. This string must be
|
||||
one of the predefined strings in this class. If the first string
|
||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||
to pass a description of the reboot cause.
|
||||
"""
|
||||
return (None, None)
|
||||
|
||||
def get_change_event(self, timeout=2000):
|
||||
"""
|
||||
Returns a nested dictionary containing all devices which have
|
||||
experienced a change at chassis level
|
||||
|
||||
Args:
|
||||
timeout: Timeout in milliseconds (optional). If timeout == 0,
|
||||
this method will block until a change is detected.
|
||||
|
||||
Returns:
|
||||
(bool, dict):
|
||||
- True if call successful, False if not;
|
||||
- A nested dictionary where key is a device type,
|
||||
value is a dictionary with key:value pairs in the
|
||||
format of {'device_id':'device_event'},
|
||||
where device_id is the device ID for this device and
|
||||
device_event,
|
||||
status='1' represents device inserted,
|
||||
status='0' represents device removed.
|
||||
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
|
||||
indicates that fan 0 has been removed, fan 2
|
||||
has been inserted and sfp 11 has been removed.
|
||||
"""
|
||||
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
|
||||
ret_dict = {"sfp": port_dict}
|
||||
return ret, ret_dict
|
||||
|
||||
def get_num_psus(self):
|
||||
return len(self._psu_list)
|
||||
|
||||
def get_psu(self, psu_index):
|
||||
return self._psu_list[psu_index]
|
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: eeprom.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
import binascii
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self):
|
||||
self.__eeprom_path = "/dev/mtd3"
|
||||
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
|
||||
self.__eeprom_tlv_dict = dict()
|
||||
try:
|
||||
self.open_eeprom()
|
||||
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 = (eeprom[9] << 8) | 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
|
||||
+ eeprom[tlv_index + 1]]
|
||||
code = "0x%02X" % (tlv[0])
|
||||
|
||||
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
|
||||
value = str((tlv[2] << 24) | (tlv[3] << 16) |
|
||||
(tlv[4] << 8) | tlv[5])
|
||||
value += str(tlv[6:6 + tlv[1]])
|
||||
else:
|
||||
name, value = self.decoder(None, tlv)
|
||||
|
||||
self.__eeprom_tlv_dict[code] = value
|
||||
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
|
||||
break
|
||||
|
||||
tlv_index += eeprom[tlv_index+1] + 2
|
||||
|
||||
def serial_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def base_mac_addr(self):
|
||||
(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):
|
||||
(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].decode('ascii')
|
||||
|
||||
def part_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def serial_tag_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def revision_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
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
|
||||
|
@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Celestica
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the fan status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import math
|
||||
import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_base import FanBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
FAN_PATH = "/sys/class/hwmon/hwmon1/"
|
||||
FAN_MAX_PWM = 255
|
||||
FAN_FAN_PWM = "pwm{}"
|
||||
FAN_FAN_INPUT = "fan{}_input"
|
||||
FAN_MAX_RPM = 9000
|
||||
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
|
||||
|
||||
class Fan(FanBase):
|
||||
"""Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fan_tray_index, fan_index=0):
|
||||
self.fan_index = fan_index
|
||||
self.fan_tray_index = fan_tray_index
|
||||
|
||||
FanBase.__init__(self)
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def __write_txt_file(self, file_path, value):
|
||||
try:
|
||||
with open(file_path, 'w') as fd:
|
||||
fd.write(str(value))
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __search_file_by_name(self, directory, file_name):
|
||||
for dirpath, dirnames, files in os.walk(directory):
|
||||
for name in files:
|
||||
file_path = os.path.join(dirpath, name)
|
||||
if name in file_name:
|
||||
return file_path
|
||||
return None
|
||||
|
||||
def get_direction(self):
|
||||
"""
|
||||
Retrieves the direction of fan
|
||||
Returns:
|
||||
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||
depending on fan direction
|
||||
"""
|
||||
direction = self.FAN_DIRECTION_EXHAUST
|
||||
return direction
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Retrieves the speed of fan as a percentage of full speed
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed = pwm_in/255*100
|
||||
"""
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return int(speed)
|
||||
|
||||
def get_target_speed(self):
|
||||
"""
|
||||
Retrieves the target (expected) speed of the fan
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed_pc = pwm_target/255*100
|
||||
|
||||
0 : when PWM mode is use
|
||||
pwm : when pwm mode is not use
|
||||
"""
|
||||
# target = 0
|
||||
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
# fan_target_sysfs_path = self.__search_file_by_name(
|
||||
# FAN_PATH, fan_target_sysfs_name)
|
||||
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
|
||||
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
|
||||
|
||||
# return target
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return speed
|
||||
|
||||
def get_speed_tolerance(self):
|
||||
"""
|
||||
Retrieves the speed tolerance of the fan
|
||||
Returns:
|
||||
An integer, the percentage of variance from target speed which is
|
||||
considered tolerable
|
||||
"""
|
||||
return 10
|
||||
|
||||
def set_speed(self, speed):
|
||||
"""
|
||||
Sets the fan speed
|
||||
Args:
|
||||
speed: An integer, the percentage of full fan speed to set fan to,
|
||||
in the range 0 (off) to 100 (full speed)
|
||||
Returns:
|
||||
A boolean, True if speed is set successfully, False if not
|
||||
|
||||
Note:
|
||||
Depends on pwm or target mode is selected:
|
||||
1) pwm = speed_pc * 255 <-- Currently use this mode.
|
||||
2) target_pwm = speed_pc * 100 / 255
|
||||
2.1) set pwm{}_enable to 3
|
||||
|
||||
"""
|
||||
pwm = speed * 255 / 100
|
||||
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
fan_target_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_target_sysfs_name)
|
||||
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
|
||||
|
||||
def set_status_led(self, color):
|
||||
"""
|
||||
Sets the state of the fan module status LED
|
||||
Args:
|
||||
color: A string representing the color with which to set the
|
||||
fan module status LED
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
fan_name = FAN_NAME_LIST[self.fan_index]
|
||||
|
||||
return fan_name
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
|
||||
return True
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the status of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# Centec E530 48s4x
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the Fan-Drawers' information available in the platform.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
||||
from .fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
CENTEC_FANS_PER_FANTRAY = 4
|
||||
|
||||
|
||||
class FanDrawer(FanDrawerBase):
|
||||
"""Centec E530 48s4x Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fantray_index):
|
||||
|
||||
FanDrawerBase.__init__(self)
|
||||
self.fantrayindex = fantray_index
|
||||
for i in range(CENTEC_FANS_PER_FANTRAY):
|
||||
self._fan_list.append(Fan(fantray_index, i))
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the fan drawer name
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
return "FanTray{}".format(self.fantrayindex)
|
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: platform.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-48S4X
|
||||
#
|
||||
|
||||
|
||||
try:
|
||||
from sonic_platform_base.platform_base import PlatformBase
|
||||
from sonic_platform.chassis import Chassis
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Platform(PlatformBase):
|
||||
|
||||
def __init__(self):
|
||||
PlatformBase.__init__(self)
|
||||
self._chassis = Chassis()
|
||||
|
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import imp
|
||||
import os
|
||||
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % e)
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Psu(PsuBase):
|
||||
"""Centec Platform-specific PSU class"""
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
self._fan_list = []
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
return
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
|
||||
module = imp.load_source("psuutil", module_file)
|
||||
psu_util_class = getattr(module, "PsuUtil")
|
||||
self._psuutil = psu_util_class()
|
||||
|
||||
def _get_psuutil(self):
|
||||
return self._psuutil
|
||||
|
||||
def get_presence(self):
|
||||
return self._get_psuutil().get_psu_presence(self._index)
|
||||
|
||||
def get_powergood_status(self):
|
||||
return self._get_psuutil().get_psu_status(self._index)
|
@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import imp
|
||||
import os
|
||||
|
||||
try:
|
||||
from sonic_platform_base.sfp_base import SfpBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % e)
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Sfp(SfpBase):
|
||||
"""
|
||||
Platform-specific sfp class
|
||||
|
||||
Unimplemented methods:
|
||||
- get_model
|
||||
- get_serial
|
||||
- get_status
|
||||
- get_transceiver_info
|
||||
- get_transceiver_bulk_status
|
||||
- get_transceiver_threshold_info
|
||||
- get_reset_status
|
||||
- get_rx_los
|
||||
- get_tx_fault
|
||||
- get_tx_disable_channel
|
||||
- get_power_override
|
||||
- get_temperature
|
||||
- get_voltage
|
||||
- get_tx_bias
|
||||
- get_rx_power
|
||||
- get_tx_power
|
||||
- tx_disable_channel
|
||||
- set_power_override
|
||||
"""
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
return
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
module_file = "/".join([platform_path, "plugins", "sfputil.py"])
|
||||
module = imp.load_source("sfputil", module_file)
|
||||
sfp_util_class = getattr(module, "SfpUtil")
|
||||
self._sfputil = sfp_util_class()
|
||||
|
||||
def get_id(self):
|
||||
return self._index
|
||||
|
||||
def get_name(self):
|
||||
return "Ethernet{}".format(self._index)
|
||||
|
||||
def get_lpmode(self):
|
||||
return False
|
||||
|
||||
def set_lpmode(self, lpmode):
|
||||
return False
|
||||
|
||||
def get_tx_disable(self):
|
||||
return False
|
||||
|
||||
def tx_disable(self, tx_disable):
|
||||
return False
|
||||
|
||||
def reset(self):
|
||||
pass
|
||||
|
||||
def clear_interrupt(self):
|
||||
return False
|
||||
|
||||
def get_interrupt_file(self):
|
||||
return None
|
||||
|
||||
def _get_sfputil(self):
|
||||
return self._sfputil
|
||||
|
||||
def get_presence(self):
|
||||
return self._get_sfputil().get_presence(self._index)
|
||||
|
||||
def get_transceiver_info(self):
|
||||
return self._get_sfputil().get_transceiver_info_dict(self._index)
|
||||
|
||||
def get_transceiver_bulk_status(self):
|
||||
return self._get_sfputil().get_transceiver_dom_info_dict(self._index)
|
||||
|
||||
def get_transceiver_threshold_info(self):
|
||||
return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index)
|
||||
|
||||
def get_transceiver_change_event(self, timeout):
|
||||
return self._get_sfputil().get_transceiver_change_event(timeout)
|
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Celestica
|
||||
#
|
||||
# Thermal contains an implementation of SONiC Platform Base API and
|
||||
# provides the thermal device status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.thermal_base import ThermalBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Thermal(ThermalBase):
|
||||
"""Platform-specific Thermal class"""
|
||||
|
||||
THERMAL_NAME_LIST = []
|
||||
CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1"
|
||||
|
||||
def __init__(self, thermal_index):
|
||||
self.index = thermal_index
|
||||
self.high_threshold = float(112)
|
||||
|
||||
# Add thermal name
|
||||
self.THERMAL_NAME_LIST.append("SENSOR-1")
|
||||
|
||||
# Set hwmon path
|
||||
self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH
|
||||
self.ss_key = self.THERMAL_NAME_LIST[self.index - 1]
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
raise IOError("Unable to open %s file !" % file_path)
|
||||
|
||||
def __get_temp(self, temp_file):
|
||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||
raw_temp = self.__read_txt_file(temp_file_path)
|
||||
temp = float(raw_temp)/1000
|
||||
return float("{:.3f}".format(temp))
|
||||
|
||||
def __set_threshold(self, file_name, temperature):
|
||||
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
||||
try:
|
||||
with open(temp_file_path, 'w') as fd:
|
||||
fd.write(str(temperature))
|
||||
return True
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
def get_temperature(self):
|
||||
"""
|
||||
Retrieves current temperature reading from thermal
|
||||
Returns:
|
||||
A float number of current temperature in Celsius up to nearest thousandth
|
||||
of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
temp_file = "temp{}_input".format(self.ss_index)
|
||||
return self.__get_temp(temp_file)
|
||||
|
||||
def get_high_threshold(self):
|
||||
"""
|
||||
Retrieves the high threshold temperature of thermal
|
||||
Returns:
|
||||
A float number, the high threshold temperature of thermal in Celsius
|
||||
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
return self.high_threshold
|
||||
|
||||
def set_high_threshold(self, temperature):
|
||||
"""
|
||||
Sets the high threshold temperature of thermal
|
||||
Args :
|
||||
temperature: A float number up to nearest thousandth of one degree Celsius,
|
||||
e.g. 30.125
|
||||
Returns:
|
||||
A boolean, True if threshold is set successfully, False if not
|
||||
"""
|
||||
self.high_threshold = float(temperature)
|
||||
return True
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the thermal device
|
||||
Returns:
|
||||
string: The name of the thermal device
|
||||
"""
|
||||
return self.THERMAL_NAME_LIST[self.index]
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the PSU
|
||||
Returns:
|
||||
bool: True if PSU is present, False if not
|
||||
"""
|
||||
temp_file = "temp{}_input".format(self.ss_index)
|
||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||
return os.path.isfile(temp_file_path)
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the device
|
||||
Returns:
|
||||
A boolean value, True if device is operating properly, False if not
|
||||
"""
|
||||
if not self.get_presence():
|
||||
return False
|
||||
|
||||
return True
|
@ -8,16 +8,92 @@
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#define SEP(XXX) 1
|
||||
#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_))
|
||||
#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_))
|
||||
|
||||
#if SEP("defines")
|
||||
|
||||
#define CTC_GPIO_BASE 496
|
||||
int xirq_gpio_0 = 0;
|
||||
int xirq_gpio_1 = 0;
|
||||
int xirq_gpio_6 = 0; /* add for E530_48S4X EPLD INT0*/
|
||||
int xirq_gpio_7 = 0; /* add for E530_48S4X EPLD INT1*/
|
||||
int xirq_gpio_15 = 0;
|
||||
#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_))
|
||||
#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_))
|
||||
#define SFP_NUM 4
|
||||
#define PORT_NUM (48+SFP_NUM)
|
||||
#endif
|
||||
|
||||
#if SEP("ctc:pinctl")
|
||||
u8 ctc_gpio_set(u8 gpio_pin, u8 val)
|
||||
{
|
||||
gpio_set_value_cansleep(gpio_pin + CTC_GPIO_BASE, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 ctc_gpio_get(u8 gpio_pin)
|
||||
{
|
||||
return gpio_get_value_cansleep(gpio_pin + CTC_GPIO_BASE);
|
||||
}
|
||||
|
||||
u8 ctc_gpio_direction_config(u8 gpio_pin, u8 dir,u8 default_out)
|
||||
{
|
||||
return dir ? gpio_direction_input(gpio_pin + CTC_GPIO_BASE)
|
||||
: gpio_direction_output(gpio_pin + CTC_GPIO_BASE,default_out);
|
||||
}
|
||||
|
||||
static void ctc_pincrtl_init(void)
|
||||
{
|
||||
/* configure mgmt-phy reset-pin output on product, mgmt-phy release must before this */
|
||||
ctc_gpio_direction_config(4, 0, 1);
|
||||
/* configure power-up pin output on product */
|
||||
ctc_gpio_direction_config(6, 0, 0);
|
||||
/* configure phy interrupt pin input */
|
||||
ctc_gpio_direction_config(0, 1, 0);
|
||||
ctc_gpio_direction_config(1, 1, 0);
|
||||
/* configure phy reset-pin output, for release phy */
|
||||
ctc_gpio_direction_config(5, 0, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ctc_irq_init(void)
|
||||
{
|
||||
struct device_node *xnp;
|
||||
for_each_node_by_type(xnp, "ctc-irq")
|
||||
{
|
||||
if (of_device_is_compatible(xnp, "centec,ctc-irq"))
|
||||
{
|
||||
xirq_gpio_0 = irq_of_parse_and_map(xnp, 0);
|
||||
printk(KERN_INFO "ctc-irq GPIO0 IRQ is %d\n", xirq_gpio_0);
|
||||
xirq_gpio_1 = irq_of_parse_and_map(xnp, 1);
|
||||
printk(KERN_INFO "ctc-irq GPIO1 IRQ is %d\n", xirq_gpio_1);
|
||||
xirq_gpio_15 = irq_of_parse_and_map(xnp, 2);
|
||||
printk(KERN_INFO "ctc-irq GPIO15 IRQ is %d\n", xirq_gpio_15);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SEP("i2c:smbus")
|
||||
static int e530_48t4x_p_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value)
|
||||
{
|
||||
@ -966,6 +1042,9 @@ static int e530_48t4x_p_init(void)
|
||||
int failed = 0;
|
||||
|
||||
printk(KERN_ALERT "install e530_48t4x_p board dirver...\n");
|
||||
|
||||
ctc_irq_init();
|
||||
ctc_pincrtl_init();
|
||||
|
||||
ret = e530_48t4x_p_init_i2c_master();
|
||||
if (ret != 0)
|
@ -5,11 +5,11 @@ from setuptools import setup
|
||||
os.listdir
|
||||
|
||||
setup(
|
||||
name='48t4x_p',
|
||||
version='1.1',
|
||||
name='sonic_platform',
|
||||
version='1.0',
|
||||
description='Module to initialize centec e530-48t4x-p platforms',
|
||||
|
||||
packages=['48t4x_p'],
|
||||
package_dir={'48t4x_p': '48t4x_p/classes'},
|
||||
packages=['sonic_platform'],
|
||||
package_dir={'sonic_platform': 'sonic_platform'},
|
||||
)
|
||||
|
@ -0,0 +1,3 @@
|
||||
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
|
||||
from . import platform
|
||||
|
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: chassis.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
from .fan_drawer import FanDrawer
|
||||
from .thermal import Thermal
|
||||
from .sfp import Sfp
|
||||
from .psu import Psu
|
||||
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
NUM_FAN_TRAY = 1
|
||||
NUM_THERMAL = 1
|
||||
NUM_PORT = 52
|
||||
NUM_PSU = 2
|
||||
|
||||
class Chassis(ChassisBase):
|
||||
|
||||
def __init__(self):
|
||||
ChassisBase.__init__(self)
|
||||
# Initialize EEPROM
|
||||
self._eeprom = Eeprom()
|
||||
# Initialize FAN
|
||||
for i in range(NUM_FAN_TRAY):
|
||||
fandrawer = FanDrawer(i)
|
||||
self._fan_drawer_list.append(fandrawer)
|
||||
self._fan_list.extend(fandrawer._fan_list)
|
||||
# Initialize THERMAL
|
||||
for index in range(0, NUM_THERMAL):
|
||||
thermal = Thermal(index)
|
||||
self._thermal_list.append(thermal)
|
||||
# Initialize SFP
|
||||
for index in range(0, NUM_PORT):
|
||||
sfp = Sfp(index)
|
||||
self._sfp_list.append(sfp)
|
||||
# Initialize PSU
|
||||
for index in range(0, NUM_PSU):
|
||||
psu = Psu(index + 1)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
##############################################
|
||||
# Device methods
|
||||
##############################################
|
||||
|
||||
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
|
||||
Returns:
|
||||
string: Serial number of chassis
|
||||
"""
|
||||
return self._eeprom.serial_number_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
|
||||
|
||||
##############################################
|
||||
# Chassis methods
|
||||
##############################################
|
||||
|
||||
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.
|
||||
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
|
||||
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
|
||||
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
|
||||
"""
|
||||
return self._eeprom.system_eeprom_info()
|
||||
|
||||
def get_reboot_cause(self):
|
||||
"""
|
||||
Retrieves the cause of the previous reboot
|
||||
Returns:
|
||||
A tuple (string, string) where the first element is a string
|
||||
containing the cause of the previous reboot. This string must be
|
||||
one of the predefined strings in this class. If the first string
|
||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||
to pass a description of the reboot cause.
|
||||
"""
|
||||
return (None, None)
|
||||
|
||||
def get_change_event(self, timeout=2000):
|
||||
"""
|
||||
Returns a nested dictionary containing all devices which have
|
||||
experienced a change at chassis level
|
||||
|
||||
Args:
|
||||
timeout: Timeout in milliseconds (optional). If timeout == 0,
|
||||
this method will block until a change is detected.
|
||||
|
||||
Returns:
|
||||
(bool, dict):
|
||||
- True if call successful, False if not;
|
||||
- A nested dictionary where key is a device type,
|
||||
value is a dictionary with key:value pairs in the
|
||||
format of {'device_id':'device_event'},
|
||||
where device_id is the device ID for this device and
|
||||
device_event,
|
||||
status='1' represents device inserted,
|
||||
status='0' represents device removed.
|
||||
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
|
||||
indicates that fan 0 has been removed, fan 2
|
||||
has been inserted and sfp 11 has been removed.
|
||||
"""
|
||||
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
|
||||
ret_dict = {"sfp": port_dict}
|
||||
return ret, ret_dict
|
||||
|
||||
def get_num_psus(self):
|
||||
return len(self._psu_list)
|
||||
|
||||
def get_psu(self, psu_index):
|
||||
return self._psu_list[psu_index]
|
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: eeprom.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
import binascii
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self):
|
||||
self.__eeprom_path = "/dev/mtd3"
|
||||
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
|
||||
self.__eeprom_tlv_dict = dict()
|
||||
try:
|
||||
self.open_eeprom()
|
||||
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 = (eeprom[9] << 8) | 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
|
||||
+ eeprom[tlv_index + 1]]
|
||||
code = "0x%02X" % (tlv[0])
|
||||
|
||||
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
|
||||
value = str((tlv[2] << 24) | (tlv[3] << 16) |
|
||||
(tlv[4] << 8) | tlv[5])
|
||||
value += str(tlv[6:6 + tlv[1]])
|
||||
else:
|
||||
name, value = self.decoder(None, tlv)
|
||||
|
||||
self.__eeprom_tlv_dict[code] = value
|
||||
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
|
||||
break
|
||||
|
||||
tlv_index += eeprom[tlv_index+1] + 2
|
||||
|
||||
def serial_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def base_mac_addr(self):
|
||||
(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):
|
||||
(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].decode('ascii')
|
||||
|
||||
def part_number_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def serial_tag_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
def revision_str(self):
|
||||
(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].decode('ascii')
|
||||
|
||||
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
|
||||
|
@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# Celestica
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the fan status which are available in the platform
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import math
|
||||
import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_base import FanBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
FAN_PATH = "/sys/class/hwmon/hwmon1/"
|
||||
FAN_MAX_PWM = 255
|
||||
FAN_FAN_PWM = "pwm{}"
|
||||
FAN_FAN_INPUT = "fan{}_input"
|
||||
FAN_MAX_RPM = 9000
|
||||
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
|
||||
|
||||
class Fan(FanBase):
|
||||
"""Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fan_tray_index, fan_index=0):
|
||||
self.fan_index = fan_index
|
||||
self.fan_tray_index = fan_tray_index
|
||||
|
||||
FanBase.__init__(self)
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def __write_txt_file(self, file_path, value):
|
||||
try:
|
||||
with open(file_path, 'w') as fd:
|
||||
fd.write(str(value))
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __search_file_by_name(self, directory, file_name):
|
||||
for dirpath, dirnames, files in os.walk(directory):
|
||||
for name in files:
|
||||
file_path = os.path.join(dirpath, name)
|
||||
if name in file_name:
|
||||
return file_path
|
||||
return None
|
||||
|
||||
def get_direction(self):
|
||||
"""
|
||||
Retrieves the direction of fan
|
||||
Returns:
|
||||
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||
depending on fan direction
|
||||
"""
|
||||
direction = self.FAN_DIRECTION_EXHAUST
|
||||
return direction
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Retrieves the speed of fan as a percentage of full speed
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed = pwm_in/255*100
|
||||
"""
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return int(speed)
|
||||
|
||||
def get_target_speed(self):
|
||||
"""
|
||||
Retrieves the target (expected) speed of the fan
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
|
||||
Note:
|
||||
speed_pc = pwm_target/255*100
|
||||
|
||||
0 : when PWM mode is use
|
||||
pwm : when pwm mode is not use
|
||||
"""
|
||||
# target = 0
|
||||
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
# fan_target_sysfs_path = self.__search_file_by_name(
|
||||
# FAN_PATH, fan_target_sysfs_name)
|
||||
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
|
||||
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
|
||||
|
||||
# return target
|
||||
speed = 0
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
|
||||
|
||||
return speed
|
||||
|
||||
def get_speed_tolerance(self):
|
||||
"""
|
||||
Retrieves the speed tolerance of the fan
|
||||
Returns:
|
||||
An integer, the percentage of variance from target speed which is
|
||||
considered tolerable
|
||||
"""
|
||||
return 10
|
||||
|
||||
def set_speed(self, speed):
|
||||
"""
|
||||
Sets the fan speed
|
||||
Args:
|
||||
speed: An integer, the percentage of full fan speed to set fan to,
|
||||
in the range 0 (off) to 100 (full speed)
|
||||
Returns:
|
||||
A boolean, True if speed is set successfully, False if not
|
||||
|
||||
Note:
|
||||
Depends on pwm or target mode is selected:
|
||||
1) pwm = speed_pc * 255 <-- Currently use this mode.
|
||||
2) target_pwm = speed_pc * 100 / 255
|
||||
2.1) set pwm{}_enable to 3
|
||||
|
||||
"""
|
||||
pwm = speed * 255 / 100
|
||||
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
|
||||
fan_target_sysfs_path = self.__search_file_by_name(
|
||||
FAN_PATH, fan_target_sysfs_name)
|
||||
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
|
||||
|
||||
def set_status_led(self, color):
|
||||
"""
|
||||
Sets the state of the fan module status LED
|
||||
Args:
|
||||
color: A string representing the color with which to set the
|
||||
fan module status LED
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
fan_name = FAN_NAME_LIST[self.fan_index]
|
||||
|
||||
return fan_name
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
|
||||
return True
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the status of the FAN
|
||||
Returns:
|
||||
bool: always True
|
||||
"""
|
||||
return True
|
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# Centec E530 48t4x-p
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the Fan-Drawers' information available in the platform.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
||||
from .fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
CENTEC_FANS_PER_FANTRAY = 3
|
||||
|
||||
|
||||
class FanDrawer(FanDrawerBase):
|
||||
"""Centec E530 48t4x-p Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fantray_index):
|
||||
|
||||
FanDrawerBase.__init__(self)
|
||||
self.fantrayindex = fantray_index
|
||||
for i in range(CENTEC_FANS_PER_FANTRAY):
|
||||
self._fan_list.append(Fan(fantray_index, i))
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the fan drawer name
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
return "FanTray{}".format(self.fantrayindex)
|
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Name: platform.py, version: 1.0
|
||||
#
|
||||
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-48T4X-P
|
||||
#
|
||||
|
||||
|
||||
try:
|
||||
from sonic_platform_base.platform_base import PlatformBase
|
||||
from sonic_platform.chassis import Chassis
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Platform(PlatformBase):
|
||||
|
||||
def __init__(self):
|
||||
PlatformBase.__init__(self)
|
||||
self._chassis = Chassis()
|
||||
|
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import imp
|
||||
import os
|
||||
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_py_common import device_info
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % e)
|
||||
|
||||
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
|
||||
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
|
||||
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
|
||||
|
||||
class Psu(PsuBase):
|
||||
"""Centec Platform-specific PSU class"""
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
self._fan_list = []
|
||||
|
||||
if os.path.isdir(CONTAINER_PLATFORM_PATH):
|
||||
platform_path = CONTAINER_PLATFORM_PATH
|
||||
else:
|
||||
platform = device_info.get_platform()
|
||||
if platform is None:
|
||||
return
|
||||
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
|
||||
|
||||
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
|
||||
module = imp.load_source("psuutil", module_file)
|
||||
psu_util_class = getattr(module, "PsuUtil")
|
||||
self._psuutil = psu_util_class()
|
||||
|
||||
def _get_psuutil(self):
|
||||
return self._psuutil
|
||||
|
||||
def get_presence(self):
|
||||
return self._get_psuutil().get_psu_presence(self._index)
|
||||
|
||||
def get_powergood_status(self):
|
||||
return self._get_psuutil().get_psu_status(self._index)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user