sonic-buildimage/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py

315 lines
10 KiB
Python
Raw Normal View History

#!/usr/bin/env python
#
import os
import time
import syslog
import re
from sonic_sfp.bcmshell import bcmshell
# =====================================================================
# global variable init
# =====================================================================
# define data ram address
PORT_DATA_OFFSET_ADDR = 0xA0
PORT_DATA_START_ADDR = 0xF2
TOTAL_SCAN_BITS_ADDR = 0xF4
SYNC_START_LEN_ADDR = 0xF6
SYNC_STOP_LEN_ADDR = 0xF8
# bit streaming rule for CPLD decode
TOTAL_SCAN_BITS = None
SYNC_S = None
SYNC_P = None
# define port data for bit streaming
BIT_LINK = None
BIT_FAULT = None
BIT_TX = None
BIT_RX = None
BIT_SPEED0 = None
BIT_SPEED1 = None
# define port speed
SPEED_100G = 100
SPEED_40G = 40
SPEED_25G = 25
SPEED_10G = 10
# the amount of LED processor
AMOUNT_LED_UP = None
# define board type
INV_REDWOOD = "SONiC-Inventec-d7032-100"
INV_CYPRESS = "SONiC-Inventec-d7054"
INV_SEQUOIA = ""
BOARD_TPYE = ""
EAGLE_CORE = []
PORT_LIST = []
# port status that is auto update by chip in data ram
# there are two byte to indicate each port status
'''
RX equ 0x0 ; received packet
TX equ 0x1 ; transmitted packet
COLL equ 0x2 ; collision indicator
SPEED_C equ 0x3 ; 100 Mbps
SPEED_M equ 0x4 ; 1000 Mbps
DUPLEX equ 0x5 ; half/full duplex
FLOW equ 0x6 ; flow control capable
LINKUP equ 0x7 ; link down/up status
LINKEN equ 0x8 ; link disabled/enabled status
ZERO equ 0xE ; always 0
ONE equ 0xF ; always 1
'''
STATUS_ENABLE = 1<<0
STATUS_RX = 1<<0
STATUS_TX = 1<<1
# object is to execute bcm shell command
BCM_SHELL = None
# =====================================================================
# class object
# =====================================================================
class Led():
up = None
pfw = None
def __init__(self, led_number, program_fw):
self.up = led_number
self.pfw = program_fw
def led_start(self):
BCM_SHELL.cmd("led {0} start".format(self.up))
syslog.syslog(syslog.LOG_INFO, "Start Led({0})".format(self.up))
def led_stop(self):
BCM_SHELL.cmd("led {0} stop".format(self.up))
syslog.syslog(syslog.LOG_INFO, "Stop Led({0})".format(self.up))
def load_prog(self):
BCM_SHELL.cmd("led {0} prog {1}".format(self.up, self.pfw))
syslog.syslog(syslog.LOG_INFO, "Load Led({0}) program firmware".format(self.up))
def write_port_data(self, addr, data):
BCM_SHELL.cmd("setreg CMIC_LEDUP{0}_DATA_RAM({1}) {2}".format(self.up, addr, data))
#syslog.syslog(syslog.LOG_DEBUG, "Write Led({0}) data_ram({1}): {2}".format(self.up, addr, data))
def read_data_ram(self, offset):
return_string = BCM_SHELL.run("getreg CMIC_LEDUP{0}_DATA_RAM({1})".format(self.up, offset))
for line in return_string.split("\n"):
re_obj = re.search(r"\<DATA\=(?P<data>.+)\>",line)
if re_obj is not None:
#syslog.syslog(syslog.LOG_DEBUG, "Read Led({0}) data_ram({1}): {2}".format(self.up, offset, re_obj.group("data")))
return int(re_obj.group("data"), 16)
return None
# =====================================================================
# Function
# =====================================================================
def _remap_registers():
fp = open('/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/led_proc_init.soc', "r")
content = fp.readlines()
fp.close()
err = False
for line in content:
try:
BCM_SHELL.cmd(line.rstrip())
except Exception, e:
err = True
syslog.syslog(syslog.LOG_ERR, "remap register abnormal: {0}".format(str(e)))
if not err:
pass
#syslog.syslog(syslog.LOG_DEBUG, "remap Led registers successfully")
def _update_port_list():
global PORT_LIST
PORT_LIST = []
number = 0
count = 0
content = BCM_SHELL.run("ps")
for line in content.split("\n"):
re_obj = re.search(r"(?P<port_name>(xe|ce)\d+)\(\s*(?P<bcm_id>\d+)\)\s+(?P<link>(up|down|!ena)).+\s+(?P<speed>\d+)G",line)
if re_obj is not None:
if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
PORT_LIST.append({"port_id":number, "name":re_obj.group("port_name"), "bcm_id":int(re_obj.group("bcm_id")), "link":re_obj.group("link"), "speed":int(re_obj.group("speed"))})
number += 1
content = BCM_SHELL.run("led status")
for line in content.split("\n"):
re_obj = re.search(r"(?P<bcm_id>\d+).+(?P<led_up>\d)\:(?P<offset>\d+)",line)
if re_obj is not None:
if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
PORT_LIST[count]["led_up"] = int(re_obj.group("led_up"))
PORT_LIST[count]["offset"] = int(re_obj.group("offset"))
count += 1
if number is not count:
PORT_LIST = []
syslog.syslog(syslog.LOG_ERR, "The amount of port is not match")
else:
pass
#syslog.syslog(syslog.LOG_DEBUG, "update port list successfully")
def _lookup_led_index(p):
index = 0
for port in PORT_LIST:
if p["bcm_id"] == port["bcm_id"]:
break
if p["led_up"] == port["led_up"]:
index += 1
return index + PORT_DATA_OFFSET_ADDR
def _led_init():
global BOARD_TPYE
global AMOUNT_LED_UP
global BIT_LINK
global BIT_FAULT
global BIT_TX
global BIT_RX
global BIT_SPEED0
global BIT_SPEED1
global EAGLE_CORE
global TOTAL_SCAN_BITS
global SYNC_S
global SYNC_P
cmd = "uname -n"
platform = os.popen(cmd).read()
if platform.rstrip() == INV_REDWOOD:
BOARD_TPYE = "inventec_d7032q28b"
AMOUNT_LED_UP = 2
BIT_RX = 1<<0 #0x01
BIT_TX = 1<<1 #0x02
BIT_SPEED0 = 1<<3 #0x08
BIT_SPEED1 = 1<<4 #0x10
BIT_FAULT = 1<<6 #0x40
BIT_LINK = 1<<7 #0x80
TOTAL_SCAN_BITS = 32*1*4
SYNC_S = 15
SYNC_P = 3
EAGLE_CORE = [66, 100]
_remap_registers()
elif platform.rstrip() == INV_CYPRESS:
BOARD_TPYE = "inventec_d7054q28b"
AMOUNT_LED_UP = 2
BIT_LINK = 1<<0 #0x01
BIT_FAULT = 1<<1 #0x02
BIT_SPEED0 = 1<<2 #0x04
EAGLE_CORE = [66, 100]
elif platform.rstrip() == INV_SEQUOIA:
BOARD_TPYE = "inventec_d7264q28b"
AMOUNT_LED_UP = 4
else:
BOARD_TPYE = "not found"
syslog.syslog(syslog.LOG_INFO, "Device: {0}".format(BOARD_TPYE))
#syslog.syslog(syslog.LOG_DEBUG, "led_amount: {0}".format(AMOUNT_LED_UP))
if __name__ == "__main__":
waitSyncd = True
retryCount = 0
syslog.openlog("led_proc", syslog.LOG_PID, facility=syslog.LOG_DAEMON)
while waitSyncd:
try:
BCM_SHELL = bcmshell()
waitSyncd = False
except Exception, e:
syslog.syslog(syslog.LOG_WARNING, "{0}, Retry times({1})".format(str(e),retryCount))
retryCount += 1
time.sleep(5)
_led_init()
led_obj = []
for idx in range(AMOUNT_LED_UP):
led_obj.append(Led(idx, ""))
#syslog.syslog(syslog.LOG_DEBUG, "create object led({0}) successfully".format(idx))
if BOARD_TPYE == "inventec_d7032q28b":
led_obj[idx].write_port_data(PORT_DATA_START_ADDR, PORT_DATA_OFFSET_ADDR)
led_obj[idx].write_port_data(TOTAL_SCAN_BITS_ADDR, TOTAL_SCAN_BITS)
led_obj[idx].write_port_data(SYNC_START_LEN_ADDR, SYNC_S)
led_obj[idx].write_port_data(SYNC_STOP_LEN_ADDR, SYNC_P)
reset_sec = 2
count_down = 0
queue_active = []
port_data = None
while True:
if count_down == 0:
queue_active = []
_update_port_list()
for port in PORT_LIST:
if port["link"] == "up":
queue_active.append(port)
else:
port_data = 0
# redwood bit streaming for CPLD decode is only use led up0
led_obj[0].write_port_data(PORT_DATA_OFFSET_ADDR + port["port_id"], port_data)
count_down = reset_sec
else:
for port in queue_active:
port_data = 0
if BOARD_TPYE == "inventec_d7032q28b":
port_data |= BIT_LINK
addr = 2*(port["offset"]-1)
byte1 = led_obj[port["led_up"]].read_data_ram(addr)
byte2 = led_obj[port["led_up"]].read_data_ram(addr+1)
if byte1&STATUS_RX:
port_data |= BIT_RX
if byte1&STATUS_TX:
port_data |= BIT_TX
if port["speed"] == SPEED_100G:
port_data |= BIT_SPEED0
port_data |= BIT_SPEED1
elif port["speed"] == SPEED_40G:
port_data |= BIT_SPEED1
elif port["speed"] == SPEED_25G:
port_data |= BIT_SPEED0
else:
pass
# redwood bit streaming for CPLD decode is only use led up0
led_obj[0].write_port_data(PORT_DATA_OFFSET_ADDR + port["port_id"], port_data)
continue
elif BOARD_TPYE == "inventec_d7054q28b":
if port["speed"] != SPEED_100G and port["speed"] != SPEED_25G:
port_data |= BIT_SPEED0
led_index = _lookup_led_index(port)
led_obj[port["led_up"]].write_port_data(led_index, port_data)
time.sleep(0.5)
count_down -= 1
syslog.closelog()