[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
|
# name lanes alias index speed fec
|
||||||
Ethernet1 0 eth-0-1 10000
|
Ethernet0 0 eth-0-1 0 10000 none
|
||||||
Ethernet2 1 eth-0-2 10000
|
Ethernet1 1 eth-0-2 1 10000 none
|
||||||
Ethernet3 2 eth-0-3 10000
|
Ethernet2 2 eth-0-3 2 10000 none
|
||||||
Ethernet4 3 eth-0-4 10000
|
Ethernet3 3 eth-0-4 3 10000 none
|
||||||
Ethernet5 8 eth-0-5 10000
|
Ethernet4 8 eth-0-5 4 10000 none
|
||||||
Ethernet6 9 eth-0-6 10000
|
Ethernet5 9 eth-0-6 5 10000 none
|
||||||
Ethernet7 10 eth-0-7 10000
|
Ethernet6 10 eth-0-7 6 10000 none
|
||||||
Ethernet8 11 eth-0-8 10000
|
Ethernet7 11 eth-0-8 7 10000 none
|
||||||
Ethernet9 20 eth-0-9 10000
|
Ethernet8 20 eth-0-9 8 10000 none
|
||||||
Ethernet10 21 eth-0-10 10000
|
Ethernet9 21 eth-0-10 9 10000 none
|
||||||
Ethernet11 22 eth-0-11 10000
|
Ethernet10 22 eth-0-11 10 10000 none
|
||||||
Ethernet12 23 eth-0-12 10000
|
Ethernet11 23 eth-0-12 11 10000 none
|
||||||
Ethernet13 12 eth-0-13 10000
|
Ethernet12 12 eth-0-13 12 10000 none
|
||||||
Ethernet14 13 eth-0-14 10000
|
Ethernet13 13 eth-0-14 13 10000 none
|
||||||
Ethernet15 14 eth-0-15 10000
|
Ethernet14 14 eth-0-15 14 10000 none
|
||||||
Ethernet16 15 eth-0-16 10000
|
Ethernet15 15 eth-0-16 15 10000 none
|
||||||
Ethernet17 24 eth-0-17 10000
|
Ethernet16 24 eth-0-17 16 10000 none
|
||||||
Ethernet18 25 eth-0-18 10000
|
Ethernet17 25 eth-0-18 17 10000 none
|
||||||
Ethernet19 26 eth-0-19 10000
|
Ethernet18 26 eth-0-19 18 10000 none
|
||||||
Ethernet20 27 eth-0-20 10000
|
Ethernet19 27 eth-0-20 19 10000 none
|
||||||
Ethernet21 28 eth-0-21 10000
|
Ethernet20 28 eth-0-21 20 10000 none
|
||||||
Ethernet22 29 eth-0-22 10000
|
Ethernet21 29 eth-0-22 21 10000 none
|
||||||
Ethernet23 30 eth-0-23 10000
|
Ethernet22 30 eth-0-23 22 10000 none
|
||||||
Ethernet24 31 eth-0-24 10000
|
Ethernet23 31 eth-0-24 23 10000 none
|
||||||
Ethernet25 61,60,63,62 eth-0-25 100000
|
Ethernet24 61,60,63,62 eth-0-25 24 100000 none
|
||||||
Ethernet26 45,44,47,46 eth-0-26 100000
|
Ethernet25 45,44,47,46 eth-0-26 25 100000 none
|
||||||
|
@ -1 +1,12 @@
|
|||||||
# Configuration file generated by pwmconfig, changes will be lost
|
# 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
|
# Centec E550-24X8Y2C
|
||||||
#
|
#
|
||||||
@ -10,7 +12,7 @@
|
|||||||
try:
|
try:
|
||||||
from sonic_eeprom import eeprom_tlvinfo
|
from sonic_eeprom import eeprom_tlvinfo
|
||||||
except ImportError as e:
|
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):
|
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
#
|
#
|
||||||
# led_control.py
|
# led_control.py
|
||||||
#
|
#
|
||||||
@ -5,37 +6,110 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_led.led_control_base import LedControlBase
|
import os
|
||||||
|
import re
|
||||||
import syslog
|
import syslog
|
||||||
from socket import *
|
import collections
|
||||||
from select import *
|
from sonic_led.led_control_base import LedControlBase
|
||||||
|
from sonic_py_common import device_info
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + " - required module not found")
|
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):
|
def DBG_PRINT(str):
|
||||||
syslog.openlog("centec-led")
|
syslog.openlog("centec-led")
|
||||||
syslog.syslog(syslog.LOG_INFO, str)
|
syslog.syslog(syslog.LOG_INFO, str)
|
||||||
syslog.closelog()
|
syslog.closelog()
|
||||||
|
|
||||||
|
|
||||||
class LedControl(LedControlBase):
|
class LedControl(LedControlBase):
|
||||||
"""Platform specific LED control class"""
|
"""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
|
# Helper method to map SONiC port name to index
|
||||||
def _port_name_to_index(self, port_name):
|
def _port_name_to_index(self, port_name):
|
||||||
# Strip "Ethernet" off port name
|
for port_cfg in self._port_cfgs:
|
||||||
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
|
if port_name == port_cfg.name:
|
||||||
return -1
|
macs = [int(x) for x in (port_cfg.lanes.split(','))]
|
||||||
|
led = self.mac_to_led[min(macs)]
|
||||||
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
|
if led < 0:
|
||||||
return port_idx
|
return None
|
||||||
|
return led
|
||||||
|
return None
|
||||||
|
|
||||||
def _port_state_to_mode(self, port_idx, state):
|
def _port_state_to_mode(self, port_idx, state):
|
||||||
if state == "up":
|
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:
|
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):
|
def _port_led_mode_update(self, port_idx, ledMode):
|
||||||
with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file:
|
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)
|
shouldInit = (int(led_file.read()) == 0)
|
||||||
|
|
||||||
if shouldInit == True:
|
if shouldInit == True:
|
||||||
for idx in range(1, 27):
|
for port_cfg in self._port_cfgs:
|
||||||
defmode = self._port_state_to_mode(idx, "down")
|
macs = [int(x) for x in (port_cfg.lanes.split(','))]
|
||||||
with open(self.f_led.format("port{}".format(idx)), 'w') as led_file:
|
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))
|
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):
|
def _initDefaultConfig(self):
|
||||||
DBG_PRINT("start init led")
|
DBG_PRINT("start init led")
|
||||||
@ -72,9 +150,10 @@ class LedControl(LedControlBase):
|
|||||||
DBG_PRINT("init led done")
|
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):
|
def port_link_state_change(self, portname, state):
|
||||||
port_idx = self._port_name_to_index(portname)
|
port_idx = self._port_name_to_index(portname)
|
||||||
|
if port_idx is None:
|
||||||
|
return
|
||||||
ledMode = self._port_state_to_mode(port_idx, state)
|
ledMode = self._port_state_to_mode(port_idx, state)
|
||||||
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
|
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
|
||||||
saveMode = int(led_file.read())
|
saveMode = int(led_file.read())
|
||||||
@ -84,13 +163,3 @@ class LedControl(LedControlBase):
|
|||||||
|
|
||||||
self._port_led_mode_update(port_idx, ledMode)
|
self._port_led_mode_update(port_idx, ledMode)
|
||||||
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, 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
|
# Centec
|
||||||
#
|
#
|
||||||
@ -9,8 +11,7 @@
|
|||||||
try:
|
try:
|
||||||
from sonic_psu.psu_base import PsuBase
|
from sonic_psu.psu_base import PsuBase
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError (str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
class PsuUtil(PsuBase):
|
class PsuUtil(PsuBase):
|
||||||
"""Platform-specific PSUutil class"""
|
"""Platform-specific PSUutil class"""
|
||||||
|
@ -1,28 +1,117 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
# sfputil.py
|
# sfputil.py
|
||||||
#
|
#
|
||||||
# Platform-specific SFP transceiver interface for SONiC
|
# Platform-specific SFP transceiver interface for SONiC
|
||||||
#
|
#
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
import os
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
from socket import *
|
import collections
|
||||||
from select import *
|
|
||||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||||
|
from sonic_py_common import device_info
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError("%s - required module not found" % str(e))
|
raise ImportError("%s - required module not found" % str(e))
|
||||||
|
|
||||||
|
|
||||||
def DBG_PRINT(str):
|
|
||||||
print(str + "\n")
|
|
||||||
|
|
||||||
|
|
||||||
SFP_STATUS_INSERTED = '1'
|
SFP_STATUS_INSERTED = '1'
|
||||||
SFP_STATUS_REMOVED = '0'
|
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):
|
class SfpUtil(SfpUtilBase):
|
||||||
"""Platform-specific SfpUtil class"""
|
"""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
|
@property
|
||||||
def port_start(self):
|
def port_start(self):
|
||||||
return self.PORT_START
|
return self.PORT_START
|
||||||
@ -33,11 +122,20 @@ class SfpUtil(SfpUtilBase):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def sfp_base(self):
|
def sfp_base(self):
|
||||||
return self.SFP_BASE
|
return self.PORT_START
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def qsfp_ports(self):
|
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
|
@property
|
||||||
def port_to_eeprom_mapping(self):
|
def port_to_eeprom_mapping(self):
|
||||||
@ -46,93 +144,32 @@ class SfpUtil(SfpUtilBase):
|
|||||||
def is_logical_port(self, port_name):
|
def is_logical_port(self, port_name):
|
||||||
return True
|
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):
|
def get_presence(self, port_num):
|
||||||
# Check for invalid port_num
|
for port_cfg in self._port_cfgs:
|
||||||
if port_num < self.port_start or port_num > self.port_end:
|
if int(port_cfg.index) == port_num:
|
||||||
return False
|
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
|
||||||
if port_num < self.sfp_base:
|
if sfp_idx >= 0:
|
||||||
return False
|
try:
|
||||||
try:
|
with open(self.f_sfp_present.format(sfp_idx), 'r') as sfp_file:
|
||||||
with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file:
|
return 1 == int(sfp_file.read())
|
||||||
return 1 == int(sfp_file.read())
|
except IOError as e:
|
||||||
except IOError as e:
|
DBG_PRINT(str(e))
|
||||||
DBG_PRINT(str(e))
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_low_power_mode(self, port_num):
|
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
|
return False
|
||||||
|
|
||||||
def set_low_power_mode(self, port_num, lpmode):
|
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
|
return False
|
||||||
|
|
||||||
def reset(self, port_num):
|
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
|
return False
|
||||||
|
|
||||||
def read_porttab_mappings(self, porttabfile):
|
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
|
||||||
for x in range(self.sfp_base, self.port_end + 1):
|
for port_cfg in self._port_cfgs:
|
||||||
self.logical_to_physical['Ethernet' + str(x)] = [x]
|
self.logical_to_physical[port_cfg.name] = [int(port_cfg.index)]
|
||||||
self.physical_to_logical[x] = ['Ethernet' + str(x)]
|
self.logical_to_asic[port_cfg.name] = 0
|
||||||
|
self.physical_to_logical[int(port_cfg.index)] = [port_cfg.name]
|
||||||
data = {'valid': 0, 'last': 0}
|
|
||||||
|
|
||||||
def get_transceiver_change_event(self, timeout=2000):
|
def get_transceiver_change_event(self, timeout=2000):
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@ -140,19 +177,19 @@ class SfpUtil(SfpUtilBase):
|
|||||||
|
|
||||||
if timeout < 1000:
|
if timeout < 1000:
|
||||||
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']:
|
if now < (self.data['last'] + timeout) and self.data['valid']:
|
||||||
return True, {}
|
return True, {}
|
||||||
|
|
||||||
for x in range(self.sfp_base, self.port_end + 1):
|
for port_cfg in self._port_cfgs:
|
||||||
presence = self.get_presence(x)
|
presence = self.get_presence(int(port_cfg.index))
|
||||||
if presence != self.presence[x]:
|
if presence != self.presence[int(port_cfg.index)]:
|
||||||
self.presence[x] = presence
|
self.presence[int(port_cfg.index)] = presence
|
||||||
if presence:
|
if presence:
|
||||||
port_dict[x] = SFP_STATUS_INSERTED
|
port_dict[int(port_cfg.index)] = SFP_STATUS_INSERTED
|
||||||
else:
|
else:
|
||||||
port_dict[x] = SFP_STATUS_REMOVED
|
port_dict[int(port_cfg.index)] = SFP_STATUS_REMOVED
|
||||||
|
|
||||||
if bool(port_dict):
|
if bool(port_dict):
|
||||||
self.data['last'] = now
|
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
|
# name lanes alias index speed fec
|
||||||
Ethernet1 1 eth-0-1 1000
|
Ethernet0 1 eth-0-1 0 1000 none
|
||||||
Ethernet2 0 eth-0-2 1000
|
Ethernet1 0 eth-0-2 1 1000 none
|
||||||
Ethernet3 3 eth-0-3 1000
|
Ethernet2 3 eth-0-3 2 1000 none
|
||||||
Ethernet4 2 eth-0-4 1000
|
Ethernet3 2 eth-0-4 3 1000 none
|
||||||
Ethernet5 5 eth-0-5 1000
|
Ethernet4 5 eth-0-5 4 1000 none
|
||||||
Ethernet6 4 eth-0-6 1000
|
Ethernet5 4 eth-0-6 5 1000 none
|
||||||
Ethernet7 7 eth-0-7 1000
|
Ethernet6 7 eth-0-7 6 1000 none
|
||||||
Ethernet8 6 eth-0-8 1000
|
Ethernet7 6 eth-0-8 7 1000 none
|
||||||
Ethernet9 17 eth-0-9 1000
|
Ethernet8 17 eth-0-9 8 1000 none
|
||||||
Ethernet10 16 eth-0-10 1000
|
Ethernet9 16 eth-0-10 9 1000 none
|
||||||
Ethernet11 19 eth-0-11 1000
|
Ethernet10 19 eth-0-11 10 1000 none
|
||||||
Ethernet12 18 eth-0-12 1000
|
Ethernet11 18 eth-0-12 11 1000 none
|
||||||
Ethernet13 21 eth-0-13 1000
|
Ethernet12 21 eth-0-13 12 1000 none
|
||||||
Ethernet14 20 eth-0-14 1000
|
Ethernet13 20 eth-0-14 13 1000 none
|
||||||
Ethernet15 23 eth-0-15 1000
|
Ethernet14 23 eth-0-15 14 1000 none
|
||||||
Ethernet16 22 eth-0-16 1000
|
Ethernet15 22 eth-0-16 15 1000 none
|
||||||
Ethernet17 9 eth-0-17 1000
|
Ethernet16 9 eth-0-17 16 1000 none
|
||||||
Ethernet18 8 eth-0-18 1000
|
Ethernet17 8 eth-0-18 17 1000 none
|
||||||
Ethernet19 11 eth-0-19 1000
|
Ethernet18 11 eth-0-19 18 1000 none
|
||||||
Ethernet20 10 eth-0-20 1000
|
Ethernet19 10 eth-0-20 19 1000 none
|
||||||
Ethernet21 33 eth-0-21 1000
|
Ethernet20 33 eth-0-21 20 1000 none
|
||||||
Ethernet22 32 eth-0-22 1000
|
Ethernet21 32 eth-0-22 21 1000 none
|
||||||
Ethernet23 35 eth-0-23 1000
|
Ethernet22 35 eth-0-23 22 1000 none
|
||||||
Ethernet24 34 eth-0-24 1000
|
Ethernet23 34 eth-0-24 23 1000 none
|
||||||
Ethernet25 37 eth-0-25 1000
|
Ethernet24 37 eth-0-25 24 1000 none
|
||||||
Ethernet26 36 eth-0-26 1000
|
Ethernet25 36 eth-0-26 25 1000 none
|
||||||
Ethernet27 39 eth-0-27 1000
|
Ethernet26 39 eth-0-27 26 1000 none
|
||||||
Ethernet28 38 eth-0-28 1000
|
Ethernet27 38 eth-0-28 27 1000 none
|
||||||
Ethernet29 41 eth-0-29 1000
|
Ethernet28 41 eth-0-29 28 1000 none
|
||||||
Ethernet30 40 eth-0-30 1000
|
Ethernet29 40 eth-0-30 29 1000 none
|
||||||
Ethernet31 43 eth-0-31 1000
|
Ethernet30 43 eth-0-31 30 1000 none
|
||||||
Ethernet32 42 eth-0-32 1000
|
Ethernet31 42 eth-0-32 31 1000 none
|
||||||
Ethernet33 25 eth-0-33 1000
|
Ethernet32 25 eth-0-33 32 1000 none
|
||||||
Ethernet34 24 eth-0-34 1000
|
Ethernet33 24 eth-0-34 33 1000 none
|
||||||
Ethernet35 27 eth-0-35 1000
|
Ethernet34 27 eth-0-35 34 1000 none
|
||||||
Ethernet36 26 eth-0-36 1000
|
Ethernet35 26 eth-0-36 35 1000 none
|
||||||
Ethernet37 49 eth-0-37 1000
|
Ethernet36 49 eth-0-37 36 1000 none
|
||||||
Ethernet38 48 eth-0-38 1000
|
Ethernet37 48 eth-0-38 37 1000 none
|
||||||
Ethernet39 51 eth-0-39 1000
|
Ethernet38 51 eth-0-39 38 1000 none
|
||||||
Ethernet40 50 eth-0-40 1000
|
Ethernet39 50 eth-0-40 39 1000 none
|
||||||
Ethernet41 53 eth-0-41 1000
|
Ethernet40 53 eth-0-41 40 1000 none
|
||||||
Ethernet42 52 eth-0-42 1000
|
Ethernet41 52 eth-0-42 41 1000 none
|
||||||
Ethernet43 55 eth-0-43 1000
|
Ethernet42 55 eth-0-43 42 1000 none
|
||||||
Ethernet44 54 eth-0-44 1000
|
Ethernet43 54 eth-0-44 43 1000 none
|
||||||
Ethernet45 57 eth-0-45 1000
|
Ethernet44 57 eth-0-45 44 1000 none
|
||||||
Ethernet46 56 eth-0-46 1000
|
Ethernet45 56 eth-0-46 45 1000 none
|
||||||
Ethernet47 59 eth-0-47 1000
|
Ethernet46 59 eth-0-47 46 1000 none
|
||||||
Ethernet48 58 eth-0-48 1000
|
Ethernet47 58 eth-0-48 47 1000 none
|
||||||
Ethernet49 13 eth-0-49 10000
|
Ethernet48 13 eth-0-49 48 10000 none
|
||||||
Ethernet50 12 eth-0-50 10000
|
Ethernet49 12 eth-0-50 49 10000 none
|
||||||
Ethernet51 15 eth-0-51 10000
|
Ethernet50 15 eth-0-51 50 10000 none
|
||||||
Ethernet52 14 eth-0-52 10000
|
Ethernet51 14 eth-0-52 51 10000 none
|
||||||
|
@ -1 +1,12 @@
|
|||||||
# Configuration file generated by pwmconfig, changes will be lost
|
# 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
|
# Centec E550-24X8Y2C
|
||||||
#
|
#
|
||||||
@ -10,7 +12,7 @@
|
|||||||
try:
|
try:
|
||||||
from sonic_eeprom import eeprom_tlvinfo
|
from sonic_eeprom import eeprom_tlvinfo
|
||||||
except ImportError as e:
|
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):
|
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
# led_control.py
|
# led_control.py
|
||||||
#
|
#
|
||||||
# Platform-specific LED control functionality for SONiC
|
# Platform-specific LED control functionality for SONiC
|
||||||
@ -21,6 +23,7 @@ def DBG_PRINT(str):
|
|||||||
class LedControl(LedControlBase):
|
class LedControl(LedControlBase):
|
||||||
"""Platform specific LED control class"""
|
"""Platform specific LED control class"""
|
||||||
|
|
||||||
|
|
||||||
# Helper method to map SONiC port name to index
|
# Helper method to map SONiC port name to index
|
||||||
def _port_name_to_index(self, port_name):
|
def _port_name_to_index(self, port_name):
|
||||||
# Strip "Ethernet" off port name
|
# Strip "Ethernet" off port name
|
||||||
@ -28,7 +31,7 @@ class LedControl(LedControlBase):
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
|
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):
|
def _port_state_to_mode(self, port_idx, state):
|
||||||
if state == "up":
|
if state == "up":
|
||||||
@ -70,8 +73,8 @@ class LedControl(LedControlBase):
|
|||||||
|
|
||||||
DBG_PRINT("init led done")
|
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):
|
def port_link_state_change(self, portname, state):
|
||||||
port_idx = self._port_name_to_index(portname)
|
port_idx = self._port_name_to_index(portname)
|
||||||
ledMode = self._port_state_to_mode(port_idx, state)
|
ledMode = self._port_state_to_mode(port_idx, state)
|
||||||
@ -84,8 +87,8 @@ class LedControl(LedControlBase):
|
|||||||
self._port_led_mode_update(port_idx, ledMode)
|
self._port_led_mode_update(port_idx, ledMode)
|
||||||
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
|
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
|
||||||
|
|
||||||
# Constructor
|
|
||||||
|
|
||||||
|
# Constructor
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||||
self.LED_MODE_UP = [2, 11]
|
self.LED_MODE_UP = [2, 11]
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# Centec
|
# Centec
|
||||||
#
|
#
|
||||||
@ -9,8 +11,7 @@
|
|||||||
try:
|
try:
|
||||||
from sonic_psu.psu_base import PsuBase
|
from sonic_psu.psu_base import PsuBase
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError (str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
class PsuUtil(PsuBase):
|
class PsuUtil(PsuBase):
|
||||||
"""Platform-specific PSUutil class"""
|
"""Platform-specific PSUutil class"""
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
# sfputil.py
|
# sfputil.py
|
||||||
#
|
#
|
||||||
# Platform-specific SFP transceiver interface for SONiC
|
# Platform-specific SFP transceiver interface for SONiC
|
||||||
@ -15,6 +17,8 @@ except ImportError as e:
|
|||||||
def DBG_PRINT(str):
|
def DBG_PRINT(str):
|
||||||
print(str + "\n")
|
print(str + "\n")
|
||||||
|
|
||||||
|
SFP_STATUS_INSERTED = '1'
|
||||||
|
SFP_STATUS_REMOVED = '0'
|
||||||
|
|
||||||
class SfpUtil(SfpUtilBase):
|
class SfpUtil(SfpUtilBase):
|
||||||
"""Platform-specific SfpUtil class"""
|
"""Platform-specific SfpUtil class"""
|
||||||
@ -42,17 +46,9 @@ class SfpUtil(SfpUtilBase):
|
|||||||
def is_logical_port(self, port_name):
|
def is_logical_port(self, port_name):
|
||||||
return True
|
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):
|
def get_eeprom_data(self, port):
|
||||||
ret = None
|
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:
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
return ret
|
return ret
|
||||||
if port_num < self.sfp_base:
|
if port_num < self.sfp_base:
|
||||||
@ -65,16 +61,17 @@ class SfpUtil(SfpUtilBase):
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# todo
|
|
||||||
# def _get_port_eeprom_path(self, port_num, devid):
|
|
||||||
# pass
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
|
||||||
self.PORT_START = 1
|
self.PORT_START = 0
|
||||||
self.PORT_END = 52
|
self.PORT_END = 51
|
||||||
self.SFP_BASE = 49
|
self.SFP_BASE = 48
|
||||||
self.PORTS_IN_BLOCK = 52
|
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.eeprom_mapping = {}
|
||||||
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
|
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):
|
for x in range(self.port_start, self.sfp_base):
|
||||||
self.eeprom_mapping[x] = None
|
self.eeprom_mapping[x] = None
|
||||||
for x in range(self.sfp_base, self.port_end + 1):
|
for x in range(self.sfp_base, self.port_end + 1):
|
||||||
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(
|
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1)
|
||||||
x - self.sfp_base + 1)
|
|
||||||
self.presence = {}
|
self.presence = {}
|
||||||
for x in range(self.sfp_base, self.port_end + 1):
|
for x in range(self.sfp_base, self.port_end + 1):
|
||||||
self.presence[x] = False
|
self.presence[x] = False;
|
||||||
|
|
||||||
SfpUtilBase.__init__(self)
|
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):
|
def get_presence(self, port_num):
|
||||||
# Check for invalid port_num
|
# Check for invalid port_num
|
||||||
if port_num < self.port_start or port_num > self.port_end:
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
@ -125,13 +124,38 @@ class SfpUtil(SfpUtilBase):
|
|||||||
|
|
||||||
return False
|
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 = {}
|
port_dict = {}
|
||||||
while True:
|
|
||||||
for x in range(self.sfp_base, self.port_end + 1):
|
if timeout < 1000:
|
||||||
presence = self.get_presence(x)
|
timeout = 1000
|
||||||
if presence != self.presence[x]:
|
timeout = (timeout) / float(1000) # Convert to secs
|
||||||
self.presence[x] = presence
|
|
||||||
port_dict[x] = presence
|
if now < (self.data['last'] + timeout) and self.data['valid']:
|
||||||
return True, port_dict
|
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)
|
time.sleep(0.5)
|
||||||
|
return True, {}
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -82,7 +82,7 @@ class SfpUtil(SfpUtilBase):
|
|||||||
try:
|
try:
|
||||||
reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode")
|
reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode")
|
||||||
except IOError as e:
|
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()
|
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)_INSTALLS += $(TSINGMA_BSP_MODULE)
|
||||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48T4X_P_PLATFORM_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_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)
|
ifeq ($(INSTALL_DEBUG_TOOLS),y)
|
||||||
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
|
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
# Centec E530-48T4X-P Platform modules
|
# Centec E530-48T4X-P Platform modules
|
||||||
|
|
||||||
|
|
||||||
CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.1
|
CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.3
|
||||||
CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.1
|
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
|
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-modules-e530-24x2c_$(CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION)_arm64.deb
|
||||||
$(CENTEC_E530_24X2C_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2c-r0
|
$(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)))
|
$(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 ... "
|
echo "Preparing for installation ... "
|
||||||
|
|
||||||
demo_mnt=/mnt
|
|
||||||
|
|
||||||
hw_load() {
|
|
||||||
echo "ext4load mmc 0:2 \$loadaddr onie_uimage"
|
|
||||||
}
|
|
||||||
|
|
||||||
create_partition() {
|
create_partition() {
|
||||||
echo y | mkfs.ext4 -L CTC-SYSTEM /dev/mmcblk0p1
|
echo y | mkfs.ext4 -L CTC-SYSTEM /dev/mmcblk0p1
|
||||||
}
|
}
|
||||||
|
|
||||||
mount_partition() {
|
mount_partition() {
|
||||||
echo "mount flash"
|
echo "mount flash partition"
|
||||||
|
demo_mnt=/mnt
|
||||||
mount -t ext4 /dev/mmcblk0p1 $demo_mnt
|
mount -t ext4 /dev/mmcblk0p1 $demo_mnt
|
||||||
}
|
}
|
||||||
|
|
||||||
bootloader_menu_config() {
|
bootloader_menu_config() {
|
||||||
mkdir -p $demo_mnt/boot
|
if [ "$install_env" = "onie" ]; then
|
||||||
mount -t ext4 /dev/mmcblk0p2 $demo_mnt/boot
|
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"
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
fw_setenv -f boot_next "run sonic_image_1"
|
||||||
hw_load $hw_load_str
|
else
|
||||||
copy_img echo "Loading Demo $platform image..." && run hw_load
|
running_sonic_revision=`cat /etc/sonic/sonic_version.yml | grep build_version | awk -F \' '{print $2}'`
|
||||||
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
|
SONIC_IMAGE_MAX=2
|
||||||
EOF
|
idx=0
|
||||||
) > /tmp/env.txt
|
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 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 -f image_dir $image_dir
|
|
||||||
|
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
|
# 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
|
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)
|
$(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
|
os.listdir
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='24x2c',
|
name='sonic_platform',
|
||||||
version='1.1',
|
version='1.0',
|
||||||
description='Module to initialize centec e530-24x2c platforms',
|
description='Module to initialize centec e530-24x2c platforms',
|
||||||
|
|
||||||
packages=['24x2c'],
|
packages=['sonic_platform'],
|
||||||
package_dir={'24x2c': '24x2c/classes'},
|
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/reboot.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/spinlock.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 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")
|
#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 SFP_NUM 4
|
||||||
#define PORT_NUM (48+SFP_NUM)
|
#define PORT_NUM (48+SFP_NUM)
|
||||||
#endif
|
#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")
|
#if SEP("i2c:smbus")
|
||||||
static int e530_48t4x_p_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value)
|
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;
|
int failed = 0;
|
||||||
|
|
||||||
printk(KERN_ALERT "install e530_48t4x_p board dirver...\n");
|
printk(KERN_ALERT "install e530_48t4x_p board dirver...\n");
|
||||||
|
|
||||||
|
ctc_irq_init();
|
||||||
|
ctc_pincrtl_init();
|
||||||
|
|
||||||
ret = e530_48t4x_p_init_i2c_master();
|
ret = e530_48t4x_p_init_i2c_master();
|
||||||
if (ret != 0)
|
if (ret != 0)
|
@ -5,11 +5,11 @@ from setuptools import setup
|
|||||||
os.listdir
|
os.listdir
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='48t4x_p',
|
name='sonic_platform',
|
||||||
version='1.1',
|
version='1.0',
|
||||||
description='Module to initialize centec e530-48t4x-p platforms',
|
description='Module to initialize centec e530-48t4x-p platforms',
|
||||||
|
|
||||||
packages=['48t4x_p'],
|
packages=['sonic_platform'],
|
||||||
package_dir={'48t4x_p': '48t4x_p/classes'},
|
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