DellEMC: Initial commit for S5224F platform support (#8717)
Why I did it Added support for the device S5224F How I did it Implemented the support for the platform S5224F Switch Vendor: DellEMC Switch SKU: S5224F-ON ASIC Vendor: Broadcom SONiC Image: sonic-broadcom.bin How to verify it Verified the show platform/interface commands
This commit is contained in:
parent
b0b0ba828a
commit
c668f2ab5e
@ -0,0 +1,2 @@
|
||||
{%- set default_topo = 't1' %}
|
||||
{%- include 'buffers_config.j2' %}
|
@ -0,0 +1,37 @@
|
||||
|
||||
{%- set default_cable = '5m' %}
|
||||
|
||||
{%- macro generate_buffer_pool_and_profiles() %}
|
||||
"BUFFER_POOL": {
|
||||
"ingress_lossless_pool": {
|
||||
"size": "26531072",
|
||||
"type": "ingress",
|
||||
"mode": "dynamic",
|
||||
"xoff": "6291456"
|
||||
},
|
||||
"egress_lossless_pool": {
|
||||
"size": "32822528",
|
||||
"type": "egress",
|
||||
"mode": "static"
|
||||
}
|
||||
},
|
||||
"BUFFER_PROFILE": {
|
||||
"ingress_lossy_profile": {
|
||||
"pool":"[BUFFER_POOL|ingress_lossless_pool]",
|
||||
"size":"0",
|
||||
"dynamic_th":"3"
|
||||
},
|
||||
"egress_lossless_profile": {
|
||||
"pool":"[BUFFER_POOL|egress_lossless_pool]",
|
||||
"size":"0",
|
||||
"mode": "static",
|
||||
"static_th":"32822528"
|
||||
},
|
||||
"egress_lossy_profile": {
|
||||
"pool":"[BUFFER_POOL|egress_lossless_pool]",
|
||||
"size":"0",
|
||||
"mode": "dynamic",
|
||||
"dynamic_th":"3"
|
||||
}
|
||||
},
|
||||
{%- endmacro %}
|
@ -0,0 +1,37 @@
|
||||
|
||||
{%- set default_cable = '40m' %}
|
||||
|
||||
{%- macro generate_buffer_pool_and_profiles() %}
|
||||
"BUFFER_POOL": {
|
||||
"ingress_lossless_pool": {
|
||||
"size": "26531072",
|
||||
"type": "ingress",
|
||||
"mode": "dynamic",
|
||||
"xoff": "6291456"
|
||||
},
|
||||
"egress_lossless_pool": {
|
||||
"size": "32822528",
|
||||
"type": "egress",
|
||||
"mode": "static"
|
||||
}
|
||||
},
|
||||
"BUFFER_PROFILE": {
|
||||
"ingress_lossy_profile": {
|
||||
"pool":"[BUFFER_POOL|ingress_lossless_pool]",
|
||||
"size":"0",
|
||||
"dynamic_th":"3"
|
||||
},
|
||||
"egress_lossless_profile": {
|
||||
"pool":"[BUFFER_POOL|egress_lossless_pool]",
|
||||
"size":"0",
|
||||
"mode": "static",
|
||||
"static_th":"32822528"
|
||||
},
|
||||
"egress_lossy_profile": {
|
||||
"pool":"[BUFFER_POOL|egress_lossless_pool]",
|
||||
"size":"0",
|
||||
"mode": "dynamic",
|
||||
"dynamic_th":"3"
|
||||
}
|
||||
},
|
||||
{%- endmacro %}
|
BIN
device/dell/x86_64-dellemc_s5224f_c3538-r0/DellEMC-S5224f-P-25G/custom_led.bin
Executable file
BIN
device/dell/x86_64-dellemc_s5224f_c3538-r0/DellEMC-S5224f-P-25G/custom_led.bin
Executable file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,17 @@
|
||||
# PG lossless profiles.
|
||||
# speed cable size xon xoff threshold xon_offset
|
||||
10000 5m 1024 2048 46080 -3 2048
|
||||
25000 5m 1024 2048 65024 -3 2048
|
||||
40000 5m 1024 2048 77056 -3 2048
|
||||
50000 5m 1024 2048 93440 -3 2048
|
||||
100000 5m 1024 2048 162048 -3 2048
|
||||
10000 40m 1024 2048 47360 -3 2048
|
||||
25000 40m 1024 2048 67840 -3 2048
|
||||
40000 40m 1024 2048 81664 -3 2048
|
||||
50000 40m 1024 2048 99072 -3 2048
|
||||
100000 40m 1024 2048 173568 -3 2048
|
||||
10000 300m 1024 2048 57088 -3 2048
|
||||
25000 300m 1024 2048 92672 -3 2048
|
||||
40000 300m 1024 2048 121344 -3 2048
|
||||
50000 300m 1024 2048 148736 -3 2048
|
||||
100000 300m 1024 2048 272640 -3 2048
|
@ -0,0 +1,29 @@
|
||||
# name lanes alias index speed
|
||||
Ethernet0 21 twentyfiveGigE1/1 1 25000
|
||||
Ethernet1 22 twentyfiveGigE1/2 2 25000
|
||||
Ethernet2 23 twentyfiveGigE1/3 3 25000
|
||||
Ethernet3 24 twentyfiveGigE1/4 4 25000
|
||||
Ethernet4 25 twentyfiveGigE1/5 5 25000
|
||||
Ethernet5 26 twentyfiveGigE1/6 6 25000
|
||||
Ethernet6 27 twentyfiveGigE1/7 7 25000
|
||||
Ethernet7 28 twentyfiveGigE1/8 8 25000
|
||||
Ethernet8 29 twentyfiveGigE1/9 9 25000
|
||||
Ethernet9 30 twentyfiveGigE1/10 10 25000
|
||||
Ethernet10 31 twentyfiveGigE1/11 11 25000
|
||||
Ethernet11 32 twentyfiveGigE1/12 12 25000
|
||||
Ethernet12 49 twentyfiveGigE1/13 13 25000
|
||||
Ethernet13 50 twentyfiveGigE1/14 14 25000
|
||||
Ethernet14 51 twentyfiveGigE1/15 15 25000
|
||||
Ethernet15 52 twentyfiveGigE1/16 16 25000
|
||||
Ethernet16 53 twentyfiveGigE1/17 17 25000
|
||||
Ethernet17 54 twentyfiveGigE1/18 18 25000
|
||||
Ethernet18 55 twentyfiveGigE1/19 19 25000
|
||||
Ethernet19 56 twentyfiveGigE1/20 20 25000
|
||||
Ethernet20 57 twentyfiveGigE1/21 21 25000
|
||||
Ethernet21 58 twentyfiveGigE1/22 22 25000
|
||||
Ethernet22 59 twentyfiveGigE1/23 23 25000
|
||||
Ethernet23 60 twentyfiveGigE1/24 24 25000
|
||||
Ethernet24 33,34,35,36 hundredGigE1/25 25 100000
|
||||
Ethernet28 37,38,39,40 hundredGigE1/26 26 100000
|
||||
Ethernet32 41,42,43,44 hundredGigE1/27 27 100000
|
||||
Ethernet36 45,46,47,48 hundredGigE1/28 28 100000
|
@ -0,0 +1 @@
|
||||
{%- include 'qos_config.j2' %}
|
@ -0,0 +1 @@
|
||||
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5224f-25g.config.bcm
|
@ -0,0 +1,2 @@
|
||||
m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
|
||||
m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin
|
@ -0,0 +1,237 @@
|
||||
os=unix
|
||||
portmap_1.0=21:25
|
||||
portmap_2.0=22:25
|
||||
portmap_3.0=23:25
|
||||
portmap_4.0=24:25
|
||||
portmap_5.0=25:25
|
||||
portmap_6.0=26:25
|
||||
portmap_7.0=27:25
|
||||
portmap_8.0=28:25
|
||||
portmap_9.0=29:25
|
||||
portmap_10.0=30:25
|
||||
portmap_11.0=31:25
|
||||
portmap_12.0=32:25
|
||||
portmap_13.0=33:100
|
||||
portmap_17.0=37:100
|
||||
portmap_47.0=41:100
|
||||
portmap_51.0=45:100
|
||||
portmap_35.0=49:25
|
||||
portmap_36.0=50:25
|
||||
portmap_37.0=51:25
|
||||
portmap_38.0=52:25
|
||||
portmap_39.0=53:25
|
||||
portmap_40.0=54:25
|
||||
portmap_41.0=55:25
|
||||
portmap_42.0=56:25
|
||||
portmap_43.0=57:25
|
||||
portmap_44.0=58:25
|
||||
portmap_45.0=59:25
|
||||
portmap_46.0=60:25
|
||||
phy_chain_tx_lane_map_physical{21.0}=0x0123
|
||||
phy_chain_rx_lane_map_physical{21.0}=0x1032
|
||||
phy_chain_tx_lane_map_physical{25.0}=0x0123
|
||||
phy_chain_rx_lane_map_physical{25.0}=0x1032
|
||||
phy_chain_tx_lane_map_physical{29.0}=0x0123
|
||||
phy_chain_rx_lane_map_physical{29.0}=0x1032
|
||||
phy_chain_tx_lane_map_physical{33.0}=0x0132
|
||||
phy_chain_rx_lane_map_physical{33.0}=0x1302
|
||||
phy_chain_tx_lane_map_physical{37.0}=0x2310
|
||||
phy_chain_rx_lane_map_physical{37.0}=0x3201
|
||||
phy_chain_tx_lane_map_physical{41.0}=0x3210
|
||||
phy_chain_rx_lane_map_physical{41.0}=0x1032
|
||||
phy_chain_tx_lane_map_physical{45.0}=0x2031
|
||||
phy_chain_rx_lane_map_physical{45.0}=0x1320
|
||||
phy_chain_tx_lane_map_physical{49.0}=0x3210
|
||||
phy_chain_rx_lane_map_physical{49.0}=0x2301
|
||||
phy_chain_tx_lane_map_physical{53.0}=0x3210
|
||||
phy_chain_rx_lane_map_physical{53.0}=0x2301
|
||||
phy_chain_tx_lane_map_physical{57.0}=0x3210
|
||||
phy_chain_rx_lane_map_physical{57.0}=0x2301
|
||||
phy_chain_tx_polarity_flip_physical{21.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{21.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{22.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{22.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{23.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{23.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{24.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{24.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{25.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{25.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{26.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{26.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{27.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{27.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{28.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{28.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{29.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{29.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{30.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{30.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{31.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{31.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{32.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{32.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{33.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{33.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{34.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{34.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{35.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{35.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{36.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{36.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{37.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{37.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{38.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{38.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{39.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{39.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{40.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{40.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{41.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{41.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{42.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{42.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{43.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{43.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{44.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{44.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{45.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{45.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{46.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{46.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{47.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{47.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{48.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{48.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{49.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{49.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{50.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{50.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{51.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{51.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{52.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{52.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{53.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{53.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{54.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{54.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{55.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{55.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{56.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{56.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{57.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{57.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{58.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{58.0}=0x0
|
||||
phy_chain_tx_polarity_flip_physical{59.0}=0x0
|
||||
phy_chain_rx_polarity_flip_physical{59.0}=0x1
|
||||
phy_chain_tx_polarity_flip_physical{60.0}=0x1
|
||||
phy_chain_rx_polarity_flip_physical{60.0}=0x0
|
||||
dport_map_port_1=1
|
||||
dport_map_port_2=2
|
||||
dport_map_port_3=3
|
||||
dport_map_port_4=4
|
||||
dport_map_port_5=5
|
||||
dport_map_port_6=6
|
||||
dport_map_port_7=7
|
||||
dport_map_port_8=8
|
||||
dport_map_port_9=9
|
||||
dport_map_port_10=10
|
||||
dport_map_port_11=11
|
||||
dport_map_port_12=12
|
||||
dport_map_port_35=13
|
||||
dport_map_port_36=14
|
||||
dport_map_port_37=15
|
||||
dport_map_port_38=16
|
||||
dport_map_port_39=17
|
||||
dport_map_port_40=18
|
||||
dport_map_port_41=19
|
||||
dport_map_port_42=20
|
||||
dport_map_port_43=21
|
||||
dport_map_port_44=22
|
||||
dport_map_port_45=23
|
||||
dport_map_port_46=24
|
||||
dport_map_port_13=25
|
||||
dport_map_port_14=26
|
||||
dport_map_port_15=27
|
||||
dport_map_port_16=28
|
||||
dport_map_port_17=29
|
||||
dport_map_port_18=30
|
||||
dport_map_port_19=31
|
||||
dport_map_port_20=32
|
||||
dport_map_port_47=33
|
||||
dport_map_port_48=34
|
||||
dport_map_port_49=35
|
||||
dport_map_port_50=36
|
||||
dport_map_port_51=37
|
||||
dport_map_port_52=38
|
||||
dport_map_port_53=39
|
||||
dport_map_port_54=40
|
||||
|
||||
dpp_clock_ratio=2:3
|
||||
oversubscribe_mode=1
|
||||
core_clock_frequency=1525
|
||||
pbmp_oversubscribe=0x7fff9fffffffffffffffe
|
||||
pbmp_xport_xe=0x7fff9fffffffffffffffe
|
||||
port_flex_enable=1
|
||||
phy_an_c73=3
|
||||
|
||||
l2xmsg_mode=1
|
||||
|
||||
#Need for mac learn scale
|
||||
l2xmsg_hostbuf_size=16384
|
||||
module_64ports=0
|
||||
|
||||
#Interrupts and Parity
|
||||
max_vp_lags=0
|
||||
|
||||
schan_intr_enable=0
|
||||
tdma_timeout_usec=5000000
|
||||
|
||||
# Following added by BRCM
|
||||
stable_size=0x5500000
|
||||
|
||||
#Default L3 profile
|
||||
l2_mem_entries=32768
|
||||
l3_alpm_enable=2
|
||||
l3_alpm_ipv6_128b_bkt_rsvd=1
|
||||
|
||||
#check correct value
|
||||
l2_mem_entries=40960
|
||||
l3_mem_entries=40960
|
||||
|
||||
#Tunnels
|
||||
use_all_splithorizon_groups=1
|
||||
sai_tunnel_support=1
|
||||
bcm_tunnel_term_compatible_mode=1
|
||||
|
||||
ptp_ts_pll_fref=50000000
|
||||
ptp_bs_fref_0=50000000
|
||||
ptp_bs_fref_1=50000000
|
||||
|
||||
#RIOT Enable
|
||||
riot_enable=1
|
||||
riot_overlay_l3_intf_mem_size=8192
|
||||
riot_overlay_l3_egress_mem_size=32768
|
||||
l3_ecmp_levels=2
|
||||
riot_overlay_ecmp_resilient_hash_size=16384
|
||||
|
||||
sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc
|
||||
|
||||
#New Additions
|
||||
pfc_deadlock_seq_control=1
|
||||
|
||||
#Common configs from broadcom/x86_64-broadcom_common/x86_64-broadcom_b77/broadcom-sonic-td3.config.bcm (Lower version of Td3 (0xb771))
|
||||
mem_cache_enable=0
|
||||
ifp_inports_support_enable=1
|
||||
ipv6_lpm_128b_enable=0x1
|
||||
l3_max_ecmp_mode=1
|
||||
lpm_scaling_enable=0
|
||||
bcm_num_cos=10
|
||||
default_cpu_tx_queue=9
|
||||
mmu_lossless=0
|
||||
host_as_route_disable=1
|
||||
sai_eapp_config_file=/etc/broadcom/eapps_cfg.json
|
||||
sai_fast_convergence_support=1
|
||||
flow_init_mode=1
|
||||
sai_load_hw_config=/usr/lib/cancun/
|
1
device/dell/x86_64-dellemc_s5224f_c3538-r0/default_sku
Normal file
1
device/dell/x86_64-dellemc_s5224f_c3538-r0/default_sku
Normal file
@ -0,0 +1 @@
|
||||
DellEMC-S5224f-P-25G t1
|
@ -0,0 +1,2 @@
|
||||
CONSOLE_PORT=0x3f8
|
||||
CONSOLE_DEV=0
|
@ -0,0 +1,6 @@
|
||||
# LED microprocessor initialization for Dell S5224
|
||||
#
|
||||
#
|
||||
#Led0
|
||||
led auto on
|
||||
led start
|
446
device/dell/x86_64-dellemc_s5224f_c3538-r0/media_settings.json
Normal file
446
device/dell/x86_64-dellemc_s5224f_c3538-r0/media_settings.json
Normal file
@ -0,0 +1,446 @@
|
||||
{
|
||||
"GLOBAL_MEDIA_SETTINGS": {
|
||||
"1-24": {
|
||||
"(.*-C6Y7M)|(.*-V250M)|(.*-05CWK6)|(.*-53HVN)|(.*-358VV)|(.*-MV799)|(.*-59970000.)|(.*-P4YPY)|(.*-TCPM2)|(.*-JNPF8)|(.*-27GG5)|(.*-P8T4W)|(.*-JR54Y)|(.*-L56[SQ]F0..-SD-R)|(.*-61676000.)|(.*-74752.*)|(SFP\\+-CR-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x19410a"
|
||||
}
|
||||
},
|
||||
"(.*-58KM3)|(.*-2JVDD)|(.*-26FN3)|(SFP28-CR-((0\\.5)|(1\\.0)|(0\\.0)|(N/A)))": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x19410a"
|
||||
}
|
||||
},
|
||||
"(.*-D0R73)|(.*-YFNDD)|(SFP28-CR-2\\.0)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x19410a"
|
||||
}
|
||||
},
|
||||
"(.*-VXFJY)|(.*-9X8JP)|(.*-7R9N9)|(SFP28-CR-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x19410a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"25-28": {
|
||||
"QSFP\\+-CR-.*": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x18420a",
|
||||
"lane1": "0x18420a",
|
||||
"lane2": "0x18420a",
|
||||
"lane3": "0x18420a"
|
||||
}
|
||||
},
|
||||
"(.*-035KG)|(.*-P7C7N)|(QSFP28-CR-((0\\.5)|(1\\.0)|(0\\.0)|(N/A)))": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x18420a",
|
||||
"lane1": "0x18420a",
|
||||
"lane2": "0x18420a",
|
||||
"lane3": "0x18420a"
|
||||
}
|
||||
},
|
||||
"(.*-76V43)|(QSFP28-CR-2\\.0)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x18420a",
|
||||
"lane1": "0x18420a",
|
||||
"lane2": "0x18420a",
|
||||
"lane3": "0x18420a"
|
||||
}
|
||||
},
|
||||
"(.*-3CC35)|(.*-FN4FC)|(QSFP28-CR-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x18420a",
|
||||
"lane1": "0x18420a",
|
||||
"lane2": "0x18420a",
|
||||
"lane3": "0x18420a"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PORT_MEDIA_SETTINGS": {
|
||||
"1": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x0b3c02"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x14460a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x0b3c02"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x14460a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x0a3b02"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x14460a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x0a3b02"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x14460a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"5": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x0a3b02"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x14460a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"6": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x093a02"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"7": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x083902"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x083902"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073702"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x124909"
|
||||
}
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073702"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x124909"
|
||||
}
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x093a02"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"14": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x083902"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"15": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x083902"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x083902"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"17": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x083902"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"18": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"19": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x083902"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"20": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"21": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"23": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"24": {
|
||||
"(.*-WTRD1)|(.*-RN84N)|(.*-DT87G)|(.*-HMTNW)|(.*-1F80G)|(.*-6K3Y6)|(.*-YJF03)|(.*-P9GND)|(.*-T1KCN)|(.*-1DXKP)|(.*-MT7R2)|(.*-C4DD6)|(.*-8JHPY)|(.*-PGYJT)|(.*-FCBG110SD1C)|(.*-FCCG125SD1C)|(SFP\\+-.*)": {
|
||||
|
||||
"preemphasis": {
|
||||
"lane0": "0x073802"
|
||||
}
|
||||
},
|
||||
"(.*-P7D7R)|(.*-W4GPP)|(.*-07RN7)|(.*-3YWG7)|(.*-5CMT2)|(.*-FTLF8540P4BCL)|(SFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x13470a"
|
||||
}
|
||||
}
|
||||
},
|
||||
"25": {
|
||||
"(.*-14NV5)|(.*-D7P80)|(.*-THPF3)|(.*-X7CCC)|(.*-YKMH7)|(.*-0X9CT)|(.*-05J8P)|(.*-5WGKD)|(.*-XFDRT)|(.*-1002971101)|(QSFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x114b08",
|
||||
"lane1": "0x114b08",
|
||||
"lane2": "0x114b08",
|
||||
"lane3": "0x114b08"
|
||||
}
|
||||
},
|
||||
"QSFP\\+-.*": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x114b08",
|
||||
"lane1": "0x114b08",
|
||||
"lane2": "0x114b08",
|
||||
"lane3": "0x114b08"
|
||||
}
|
||||
}
|
||||
},
|
||||
"26": {
|
||||
"(.*-14NV5)|(.*-D7P80)|(.*-THPF3)|(.*-X7CCC)|(.*-YKMH7)|(.*-0X9CT)|(.*-05J8P)|(.*-5WGKD)|(.*-XFDRT)|(.*-1002971101)|(QSFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x0f4d08",
|
||||
"lane1": "0x0f4d08",
|
||||
"lane2": "0x0f4d08",
|
||||
"lane3": "0x0f4d08"
|
||||
}
|
||||
},
|
||||
"QSFP\\+-.*": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x0f4d08",
|
||||
"lane1": "0x0f4d08",
|
||||
"lane2": "0x0f4d08",
|
||||
"lane3": "0x0f4d08"
|
||||
}
|
||||
}
|
||||
},
|
||||
"27": {
|
||||
"(.*-14NV5)|(.*-D7P80)|(.*-THPF3)|(.*-X7CCC)|(.*-YKMH7)|(.*-0X9CT)|(.*-05J8P)|(.*-5WGKD)|(.*-XFDRT)|(.*-1002971101)|(QSFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x0e4f07",
|
||||
"lane1": "0x0e4f07",
|
||||
"lane2": "0x0e4f07",
|
||||
"lane3": "0x0e4f07"
|
||||
}
|
||||
},
|
||||
"QSFP\\+-.*": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x0e4f07",
|
||||
"lane1": "0x0e4f07",
|
||||
"lane2": "0x0e4f07",
|
||||
"lane3": "0x0e4f07"
|
||||
}
|
||||
}
|
||||
},
|
||||
"28": {
|
||||
"(.*-14NV5)|(.*-D7P80)|(.*-THPF3)|(.*-X7CCC)|(.*-YKMH7)|(.*-0X9CT)|(.*-05J8P)|(.*-5WGKD)|(.*-XFDRT)|(.*-1002971101)|(QSFP28-.*)": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x0f4d08",
|
||||
"lane1": "0x0f4d08",
|
||||
"lane2": "0x0f4d08",
|
||||
"lane3": "0x0f4d08"
|
||||
}
|
||||
},
|
||||
"QSFP\\+-.*": {
|
||||
"preemphasis": {
|
||||
"lane0": "0x0f4d08",
|
||||
"lane1": "0x0f4d08",
|
||||
"lane2": "0x0f4d08",
|
||||
"lane3": "0x0f4d08"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
device/dell/x86_64-dellemc_s5224f_c3538-r0/plugins/eeprom.py
Normal file
32
device/dell/x86_64-dellemc_s5224f_c3538-r0/plugins/eeprom.py
Normal file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# DellEMC S5224f
|
||||
#
|
||||
# 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
|
||||
#############################################################################
|
||||
|
||||
import os.path
|
||||
|
||||
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 = None
|
||||
for b in (0, 1):
|
||||
f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b)
|
||||
if os.path.exists(f):
|
||||
self.eeprom_path = f
|
||||
break
|
||||
if self.eeprom_path is None:
|
||||
return
|
||||
|
||||
super(board, self).__init__(self.eeprom_path, 0, '', True)
|
21
device/dell/x86_64-dellemc_s5224f_c3538-r0/plugins/pcie.yaml
Normal file
21
device/dell/x86_64-dellemc_s5224f_c3538-r0/plugins/pcie.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
- bus: '03'
|
||||
dev: '00'
|
||||
fn: '0'
|
||||
id: '1533'
|
||||
name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev
|
||||
03)'
|
||||
- bus: '02'
|
||||
dev: '00'
|
||||
fn: '0'
|
||||
id: b771
|
||||
name: 'Ethernet controller: Broadcom Limited Device b771 (rev 01)'
|
||||
- bus: '04'
|
||||
dev: '00'
|
||||
fn: '0'
|
||||
id: '7021'
|
||||
name: 'Non-VGA unclassified device: Xilinx Corporation Device 7021'
|
||||
- bus: '00'
|
||||
dev: '14'
|
||||
fn: '0'
|
||||
id: 19c2
|
||||
name: 'SATA controller: Intel Corporation DNV SATA Controller 1 (rev 11)'
|
@ -0,0 +1,97 @@
|
||||
#
|
||||
# psuutil.py
|
||||
# Platform-specific PSU status interface for SONiC
|
||||
#
|
||||
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
S5224F_MAX_PSUS = 2
|
||||
IPMI_PSU_DATA = "docker exec -it pmon ipmitool sdr list"
|
||||
IPMI_PSU_DATA_DOCKER = "ipmitool sdr list"
|
||||
PSU_PRESENCE = "PSU{0}_stat"
|
||||
# Use this for older firmware
|
||||
# PSU_PRESENCE="PSU{0}_prsnt"
|
||||
ipmi_sdr_list = ""
|
||||
|
||||
|
||||
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)
|
||||
|
||||
def isDockerEnv(self):
|
||||
num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker")
|
||||
if num_docker > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# Fetch a BMC register
|
||||
def get_pmc_register(self, reg_name):
|
||||
|
||||
global ipmi_sdr_list
|
||||
ipmi_cmd = IPMI_PSU_DATA
|
||||
dockerenv = self.isDockerEnv()
|
||||
if dockerenv == True:
|
||||
ipmi_cmd = IPMI_PSU_DATA_DOCKER
|
||||
|
||||
status, ipmi_sdr_list = subprocess.getstatusoutput(ipmi_cmd)
|
||||
|
||||
if status:
|
||||
logging.error('Failed to execute:' + ipmi_sdr_list)
|
||||
sys.exit(0)
|
||||
|
||||
for item in ipmi_sdr_list.split("\n"):
|
||||
if reg_name in item:
|
||||
output = item.strip()
|
||||
|
||||
if not output:
|
||||
print('\nFailed to fetch: ' + reg_name + ' sensor ')
|
||||
sys.exit(0)
|
||||
|
||||
output = output.split('|')[1]
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
return output
|
||||
|
||||
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
|
||||
"""
|
||||
S5224F_MAX_PSUS = 2
|
||||
return S5224F_MAX_PSUS
|
||||
|
||||
def get_psu_status(self, index):
|
||||
"""
|
||||
Retrieves the oprational status of power supply unit (PSU) defined
|
||||
by index <index>
|
||||
:param index: An integer, index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is operating properly, False if PSU is\
|
||||
faulty
|
||||
"""
|
||||
# Until psu_status is implemented this is hardcoded temporarily
|
||||
|
||||
status = 1
|
||||
return status
|
||||
|
||||
def get_psu_presence(self, index):
|
||||
"""
|
||||
Retrieves the presence status of power supply unit (PSU) defined
|
||||
by index <index>
|
||||
:param index: An integer, index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is plugged, False if not
|
||||
"""
|
||||
cmd_status, psu_status = subprocess.getstatusoutput('ipmitool raw 0x04 0x2d ' + hex(0x30 + index) + " | awk '{print substr($0,9,1)}'")
|
||||
return 1 if psu_status == '1' else 0
|
||||
|
550
device/dell/x86_64-dellemc_s5224f_c3538-r0/plugins/sfputil.py
Normal file
550
device/dell/x86_64-dellemc_s5224f_c3538-r0/plugins/sfputil.py
Normal file
@ -0,0 +1,550 @@
|
||||
# sfputil.py
|
||||
#
|
||||
# Platform-specific SFP transceiver interface for SONiC
|
||||
#
|
||||
# For S5224F-ON, hardware version X01
|
||||
|
||||
try:
|
||||
import struct
|
||||
import time
|
||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||
from os import *
|
||||
from mmap import *
|
||||
import io
|
||||
from sonic_sfp.sff8436 import sff8436InterfaceId
|
||||
from sonic_sfp.sff8436 import sff8436Dom
|
||||
from sonic_sfp.sff8472 import sff8472Dom
|
||||
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % str(e))
|
||||
|
||||
|
||||
|
||||
#definitions of the offset and width for values in DOM info eeprom
|
||||
QSFP_DOM_REV_OFFSET = 1
|
||||
QSFP_DOM_REV_WIDTH = 1
|
||||
QSFP_TEMPE_OFFSET = 22
|
||||
QSFP_TEMPE_WIDTH = 2
|
||||
QSFP_VOLT_OFFSET = 26
|
||||
QSFP_VOLT_WIDTH = 2
|
||||
QSFP_CHANNL_MON_OFFSET = 34
|
||||
QSFP_CHANNL_MON_WIDTH = 16
|
||||
QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24
|
||||
QSFP_MODULE_THRESHOLD_OFFSET = 128
|
||||
QSFP_MODULE_THRESHOLD_WIDTH = 24
|
||||
QSFP_CHANNL_THRESHOLD_OFFSET = 176
|
||||
QSFP_CHANNL_THRESHOLD_WIDTH = 16
|
||||
QSFP_CHANNL_MON_MASK_OFFSET = 242
|
||||
QSFP_CHANNL_MON_MASK_WIDTH = 4
|
||||
|
||||
SFP_TEMPE_OFFSET = 96
|
||||
SFP_TEMPE_WIDTH = 2
|
||||
SFP_VOLT_OFFSET = 98
|
||||
SFP_VOLT_WIDTH = 2
|
||||
SFP_MODULE_THRESHOLD_OFFSET = 0
|
||||
SFP_MODULE_THRESHOLD_WIDTH = 56
|
||||
|
||||
XCVR_DOM_CAPABILITY_OFFSET = 92
|
||||
XCVR_DOM_CAPABILITY_WIDTH = 1
|
||||
|
||||
|
||||
|
||||
class SfpUtil(SfpUtilBase):
|
||||
"""Platform-specific SfpUtil class"""
|
||||
|
||||
PORT_START = 1
|
||||
PORT_END = 28
|
||||
PORTS_IN_BLOCK = 28
|
||||
|
||||
BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0"
|
||||
|
||||
_port_to_eeprom_mapping = {}
|
||||
|
||||
|
||||
_global_port_pres_dict = {}
|
||||
|
||||
@property
|
||||
def port_start(self):
|
||||
return self.PORT_START
|
||||
|
||||
@property
|
||||
def port_end(self):
|
||||
return self.PORT_END
|
||||
|
||||
@property
|
||||
def qsfp_ports(self):
|
||||
return range(25, self.PORTS_IN_BLOCK + 1)
|
||||
|
||||
@property
|
||||
def port_to_eeprom_mapping(self):
|
||||
return self._port_to_eeprom_mapping
|
||||
|
||||
def pci_mem_read(self, mm, offset):
|
||||
mm.seek(offset)
|
||||
read_data_stream=mm.read(4)
|
||||
reg_val=struct.unpack('I',read_data_stream)
|
||||
mem_val = str(reg_val)[1:-2]
|
||||
# print "reg_val read:%x"%reg_val
|
||||
return mem_val
|
||||
|
||||
def pci_mem_write(self, mm, offset, data):
|
||||
mm.seek(offset)
|
||||
# print "data to write:%x"%data
|
||||
mm.write(struct.pack('I',data))
|
||||
|
||||
def pci_set_value(self, resource, val, offset):
|
||||
fd = open(resource, O_RDWR)
|
||||
mm = mmap(fd, 0)
|
||||
val = self.pci_mem_write(mm, offset, val)
|
||||
mm.close()
|
||||
close(fd)
|
||||
return val
|
||||
|
||||
def pci_get_value(self, resource, offset):
|
||||
fd = open(resource, O_RDWR)
|
||||
mm = mmap(fd, 0)
|
||||
val = self.pci_mem_read(mm, offset)
|
||||
mm.close()
|
||||
close(fd)
|
||||
return val
|
||||
|
||||
def init_global_port_presence(self):
|
||||
for port_num in range(self.port_start, (self.port_end + 1)):
|
||||
presence = self.get_presence(port_num)
|
||||
if(presence):
|
||||
self._global_port_pres_dict[port_num] = '1'
|
||||
else:
|
||||
self._global_port_pres_dict[port_num] = '0'
|
||||
|
||||
def __init__(self):
|
||||
eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
|
||||
|
||||
for x in range(self.port_start, self.port_end + 1):
|
||||
self.port_to_eeprom_mapping[x] = eeprom_path.format(x + 1)
|
||||
self.init_global_port_presence()
|
||||
SfpUtilBase.__init__(self)
|
||||
|
||||
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
|
||||
|
||||
# Port offset starts with 0x4004
|
||||
port_offset = 16388 + ((port_num-1) * 16)
|
||||
|
||||
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
||||
reg_value = int(status)
|
||||
|
||||
# Absence of status throws error
|
||||
if (reg_value == "" ):
|
||||
return False
|
||||
|
||||
# Mask off bit for presence
|
||||
mask = (1 << 0)
|
||||
if (port_num > 24):
|
||||
mask = (1 << 4)
|
||||
|
||||
# ModPrsL is active low
|
||||
if reg_value & mask == 0:
|
||||
return True
|
||||
|
||||
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
|
||||
|
||||
# Port offset starts with 0x4000
|
||||
port_offset = 16384 + ((port_num-1) * 16)
|
||||
|
||||
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
||||
reg_value = int(status)
|
||||
|
||||
# Absence of status throws error
|
||||
if (reg_value == "" ):
|
||||
return False
|
||||
|
||||
# Mask off 4th bit for presence
|
||||
mask = (1 << 6)
|
||||
|
||||
# LPMode is active high
|
||||
if reg_value & mask == 0:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
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
|
||||
|
||||
# Port offset starts with 0x4000
|
||||
port_offset = 16384 + ((port_num-1) * 16)
|
||||
|
||||
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
||||
reg_value = int(status)
|
||||
|
||||
# Absence of status throws error
|
||||
if (reg_value == "" ):
|
||||
return False
|
||||
|
||||
# Mask off 4th bit for presence
|
||||
mask = (1 << 6)
|
||||
|
||||
# LPMode is active high; set or clear the bit accordingly
|
||||
if lpmode is True:
|
||||
reg_value = reg_value | mask
|
||||
else:
|
||||
reg_value = reg_value & ~mask
|
||||
|
||||
# Convert our register value back to a hex string and write back
|
||||
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
|
||||
if status != reg_value:
|
||||
print ("Error: Set LP mode status %d", status)
|
||||
|
||||
return True
|
||||
|
||||
def reset(self, port_num):
|
||||
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
# Port offset starts with 0x4000
|
||||
port_offset = 16384 + ((port_num-1) * 16)
|
||||
|
||||
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
||||
reg_value = int(status)
|
||||
|
||||
# Absence of status throws error
|
||||
if (reg_value == "" ):
|
||||
return False
|
||||
|
||||
# Mask off 4th bit for presence
|
||||
mask = (1 << 6)
|
||||
|
||||
# ResetL is active low
|
||||
reg_value = reg_value & ~mask
|
||||
|
||||
# Convert our register value back to a hex string and write back
|
||||
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
|
||||
if status != reg_value:
|
||||
print ("Error: pci_set_value reset status %d", status)
|
||||
|
||||
# Sleep 1 second to allow it to settle
|
||||
time.sleep(1)
|
||||
|
||||
reg_value = reg_value | mask
|
||||
|
||||
# Convert our register value back to a hex string and write back
|
||||
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
|
||||
if status != reg_value:
|
||||
print ("Error: pci_set_value reset status %d", status)
|
||||
|
||||
return True
|
||||
|
||||
def get_transceiver_change_event(self, timeout=0):
|
||||
port_dict = {}
|
||||
while True:
|
||||
for port_num in range(self.port_start, (self.port_end + 1)):
|
||||
presence = self.get_presence(port_num)
|
||||
if(presence and self._global_port_pres_dict[port_num] == '0'):
|
||||
self._global_port_pres_dict[port_num] = '1'
|
||||
port_dict[port_num] = '1'
|
||||
elif(not presence and
|
||||
self._global_port_pres_dict[port_num] == '1'):
|
||||
self._global_port_pres_dict[port_num] = '0'
|
||||
port_dict[port_num] = '0'
|
||||
|
||||
if(len(port_dict) > 0):
|
||||
return True, port_dict
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
def get_transceiver_dom_info_dict(self, port_num):
|
||||
transceiver_dom_info_dict = {}
|
||||
|
||||
dom_info_dict_keys = ['temperature', 'voltage', 'rx1power',
|
||||
'rx2power', 'rx3power', 'rx4power',
|
||||
'tx1bias', 'tx2bias', 'tx3bias',
|
||||
'tx4bias', 'tx1power', 'tx2power',
|
||||
'tx3power', 'tx4power',
|
||||
]
|
||||
transceiver_dom_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A')
|
||||
|
||||
if port_num in self.qsfp_ports:
|
||||
offset = 0
|
||||
offset_xcvr = 128
|
||||
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
|
||||
if not self._sfp_eeprom_present(file_path, 0):
|
||||
return None
|
||||
|
||||
try:
|
||||
sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0)
|
||||
except IOError:
|
||||
print("Error: reading sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
sfpd_obj = sff8436Dom()
|
||||
if sfpd_obj is None:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
sfpi_obj = sff8436InterfaceId()
|
||||
if sfpi_obj is None:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
# QSFP capability byte parse, through this byte can know whether it support tx_power or not.
|
||||
# TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436,
|
||||
# need to add more code for determining the capability and version compliance
|
||||
# in SFF-8636 dom capability definitions evolving with the versions.
|
||||
qsfp_dom_capability_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH)
|
||||
if qsfp_dom_capability_raw is not None:
|
||||
qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH)
|
||||
if dom_temperature_raw is not None:
|
||||
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH)
|
||||
if dom_voltage_raw is not None:
|
||||
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
qsfp_dom_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH)
|
||||
if qsfp_dom_rev_raw is not None:
|
||||
qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
|
||||
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
|
||||
|
||||
# The tx_power monitoring is only available on QSFP which compliant with SFF-8636
|
||||
# and claimed that it support tx_power with one indicator bit.
|
||||
dom_channel_monitor_data = {}
|
||||
qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value']
|
||||
qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value']
|
||||
if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')):
|
||||
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH)
|
||||
if dom_channel_monitor_raw is not None:
|
||||
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
transceiver_dom_info_dict['tx1power'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx2power'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx3power'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx4power'] = 'N/A'
|
||||
try:
|
||||
sysfsfile_eeprom.close()
|
||||
except IOError:
|
||||
print("Error: closing sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
|
||||
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
|
||||
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value']
|
||||
transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value']
|
||||
transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value']
|
||||
transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value']
|
||||
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value']
|
||||
transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value']
|
||||
transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value']
|
||||
transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value']
|
||||
|
||||
else:
|
||||
offset = 256
|
||||
file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
|
||||
if not self._sfp_eeprom_present(file_path, 0):
|
||||
return None
|
||||
|
||||
try:
|
||||
sysfsfile_eeprom = io.open(file_path,"rb",0)
|
||||
except IOError:
|
||||
print("Error: reading sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
sfpd_obj = sff8472Dom(None,1)
|
||||
if sfpd_obj is None:
|
||||
return None
|
||||
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET),
|
||||
SFP_TEMPE_WIDTH)
|
||||
if dom_temperature_raw is not None:
|
||||
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET),
|
||||
SFP_VOLT_WIDTH)
|
||||
if dom_voltage_raw is not None:
|
||||
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_MODULE_THRESHOLD_OFFSET),
|
||||
SFP_MODULE_THRESHOLD_WIDTH)
|
||||
if dom_channel_monitor_raw is not None:
|
||||
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
try:
|
||||
sysfsfile_eeprom.close()
|
||||
except IOError:
|
||||
print("Error: closing sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
|
||||
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
|
||||
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value']
|
||||
transceiver_dom_info_dict['rx2power'] = 'N/A'
|
||||
transceiver_dom_info_dict['rx3power'] = 'N/A'
|
||||
transceiver_dom_info_dict['rx4power'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value']
|
||||
transceiver_dom_info_dict['tx2bias'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx3bias'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx4bias'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value']
|
||||
transceiver_dom_info_dict['tx2power'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx3power'] = 'N/A'
|
||||
transceiver_dom_info_dict['tx4power'] = 'N/A'
|
||||
|
||||
return transceiver_dom_info_dict
|
||||
|
||||
def get_transceiver_dom_threshold_info_dict(self, port_num):
|
||||
transceiver_dom_threshold_info_dict = {}
|
||||
dom_info_dict_keys = ['temphighalarm', 'temphighwarning',
|
||||
'templowalarm', 'templowwarning',
|
||||
'vcchighalarm', 'vcchighwarning',
|
||||
'vcclowalarm', 'vcclowwarning',
|
||||
'rxpowerhighalarm', 'rxpowerhighwarning',
|
||||
'rxpowerlowalarm', 'rxpowerlowwarning',
|
||||
'txpowerhighalarm', 'txpowerhighwarning',
|
||||
'txpowerlowalarm', 'txpowerlowwarning',
|
||||
'txbiashighalarm', 'txbiashighwarning',
|
||||
'txbiaslowalarm', 'txbiaslowwarning'
|
||||
]
|
||||
transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A')
|
||||
|
||||
if port_num in self.qsfp_ports:
|
||||
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
|
||||
if not self._sfp_eeprom_present(file_path, 0):
|
||||
return None
|
||||
|
||||
try:
|
||||
sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0)
|
||||
except IOError:
|
||||
print("Error: reading sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
sfpd_obj = sff8436Dom()
|
||||
if sfpd_obj is None:
|
||||
return transceiver_dom_threshold_info_dict
|
||||
|
||||
# Dom Threshold data starts from offset 384
|
||||
# Revert offset back to 0 once data is retrieved
|
||||
offset = 384
|
||||
dom_module_threshold_raw = self._read_eeprom_specific_bytes(
|
||||
sysfsfile_eeprom,
|
||||
(offset + QSFP_MODULE_THRESHOLD_OFFSET),
|
||||
QSFP_MODULE_THRESHOLD_WIDTH)
|
||||
if dom_module_threshold_raw is not None:
|
||||
dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_threshold_info_dict
|
||||
|
||||
dom_channel_threshold_raw = self._read_eeprom_specific_bytes(
|
||||
sysfsfile_eeprom,
|
||||
(offset + QSFP_CHANNL_THRESHOLD_OFFSET),
|
||||
QSFP_CHANNL_THRESHOLD_WIDTH)
|
||||
if dom_channel_threshold_raw is not None:
|
||||
dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_threshold_info_dict
|
||||
|
||||
try:
|
||||
sysfsfile_eeprom.close()
|
||||
except IOError:
|
||||
print("Error: closing sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
# Threshold Data
|
||||
transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value']
|
||||
|
||||
else:
|
||||
offset = 256
|
||||
file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
|
||||
if not self._sfp_eeprom_present(file_path, 0):
|
||||
return None
|
||||
|
||||
try:
|
||||
sysfsfile_eeprom = io.open(file_path,"rb",0)
|
||||
except IOError:
|
||||
print("Error: reading sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
sfpd_obj = sff8472Dom(None,1)
|
||||
if sfpd_obj is None:
|
||||
return transceiver_dom_threshold_info_dict
|
||||
|
||||
dom_module_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom,
|
||||
(offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH)
|
||||
|
||||
if dom_module_threshold_raw is not None:
|
||||
dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0)
|
||||
else:
|
||||
return transceiver_dom_threshold_info_dict
|
||||
|
||||
try:
|
||||
sysfsfile_eeprom.close()
|
||||
except IOError:
|
||||
print("Error: closing sysfs file %s" % file_path)
|
||||
return None
|
||||
|
||||
#Threshold Data
|
||||
transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value']
|
||||
transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value']
|
||||
|
||||
return transceiver_dom_threshold_info_dict
|
||||
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"start_ipmievd": true
|
||||
}
|
@ -9,6 +9,7 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR)
|
||||
$(SONIC_ONE_IMAGE)_INSTALLS += $(FLASHROM)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
|
||||
$(DELL_Z9264F_PLATFORM_MODULE) \
|
||||
$(DELL_S5224F_PLATFORM_MODULE) \
|
||||
$(DELL_S5232F_PLATFORM_MODULE) \
|
||||
$(DELL_S5248F_PLATFORM_MODULE) \
|
||||
$(DELL_Z9332F_PLATFORM_MODULE) \
|
||||
|
@ -4,6 +4,7 @@ DELL_S6000_PLATFORM_MODULE_VERSION = 1.1
|
||||
DELL_Z9100_PLATFORM_MODULE_VERSION = 1.1
|
||||
DELL_S6100_PLATFORM_MODULE_VERSION = 1.1
|
||||
DELL_Z9264F_PLATFORM_MODULE_VERSION = 1.1
|
||||
DELL_S5224F_PLATFORM_MODULE_VERSION = 1.1
|
||||
DELL_S5232F_PLATFORM_MODULE_VERSION = 1.1
|
||||
DELL_Z9332F_PLATFORM_MODULE_VERSION = 1.1
|
||||
DELL_S5248F_PLATFORM_MODULE_VERSION = 1.1
|
||||
@ -15,6 +16,7 @@ export DELL_S6000_PLATFORM_MODULE_VERSION
|
||||
export DELL_Z9100_PLATFORM_MODULE_VERSION
|
||||
export DELL_S6100_PLATFORM_MODULE_VERSION
|
||||
export DELL_Z9264F_PLATFORM_MODULE_VERSION
|
||||
export DELL_S5224F_PLATFORM_MODULE_VERSION
|
||||
export DELL_S5232F_PLATFORM_MODULE_VERSION
|
||||
export DELL_Z9332F_PLATFORM_MODULE_VERSION
|
||||
export DELL_S5248F_PLATFORM_MODULE_VERSION
|
||||
@ -41,6 +43,10 @@ DELL_S6000_PLATFORM_MODULE = platform-modules-s6000_$(DELL_S6000_PLATFORM_MODULE
|
||||
$(DELL_S6000_PLATFORM_MODULE)_PLATFORM = x86_64-dell_s6000_s1220-r0
|
||||
$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S6000_PLATFORM_MODULE)))
|
||||
|
||||
DELL_S5224F_PLATFORM_MODULE = platform-modules-s5224f_$(DELL_S5224F_PLATFORM_MODULE_VERSION)_amd64.deb
|
||||
$(DELL_S5224F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5224f_c3538-r0
|
||||
$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5224F_PLATFORM_MODULE)))
|
||||
|
||||
DELL_S5232F_PLATFORM_MODULE = platform-modules-s5232f_$(DELL_S5232F_PLATFORM_MODULE_VERSION)_amd64.deb
|
||||
$(DELL_S5232F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5232f_c3538-r0
|
||||
$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5232F_PLATFORM_MODULE)))
|
||||
|
@ -25,6 +25,11 @@ Architecture: amd64
|
||||
Depends: linux-image-4.19.0-12-2-amd64-unsigned
|
||||
Description: kernel modules for platform devices such as fan, led, sfp
|
||||
|
||||
Package: platform-modules-s5224f
|
||||
Architecture: amd64
|
||||
Depends: linux-image-4.19.0-12-2-amd64-unsigned
|
||||
Description: kernel modules for platform devices such as fan, led, sfp
|
||||
|
||||
Package: platform-modules-s5232f
|
||||
Architecture: amd64
|
||||
Depends: linux-image-4.19.0-12-2-amd64-unsigned
|
||||
|
@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: setup-board
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Should-Start:
|
||||
# Should-Stop:
|
||||
# Default-Start: S
|
||||
# Default-Stop: 0 6
|
||||
# Short-Description: Setup S5224f board.
|
||||
### END INIT INFO
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Setting up board... "
|
||||
|
||||
# /usr/local/bin/iom_power_on.sh
|
||||
/usr/local/bin/s5224f_platform.sh init
|
||||
|
||||
echo "done."
|
||||
;;
|
||||
|
||||
stop)
|
||||
/usr/local/bin/s5224f_platform.sh deinit
|
||||
echo "done."
|
||||
|
||||
;;
|
||||
|
||||
force-reload|restart)
|
||||
echo "Not supported"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: /etc/init.d/platform-modules-s5224f.init {start|stop}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
@ -0,0 +1,13 @@
|
||||
s5224f/scripts/s5224f_platform.sh usr/local/bin
|
||||
s5224f/scripts/check_qsfp.sh usr/local/bin
|
||||
s5224f/scripts/platform_sensors.py usr/local/bin
|
||||
s5224f/scripts/sensors usr/bin
|
||||
s5224f/scripts/pcisysfs.py usr/bin
|
||||
s5224f/scripts/qsfp_irq_enable.py usr/bin
|
||||
s5224f/cfg/s5224f-modules.conf etc/modules-load.d
|
||||
s5224f/cfg/s5224f-params.conf etc/modprobe.d
|
||||
s5224f/systemd/platform-modules-s5224f.service etc/systemd/system
|
||||
s5224f/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dellemc_s5224f_c3538-r0
|
||||
common/platform_reboot usr/share/sonic/device/x86_64-dellemc_s5224f_c3538-r0
|
||||
common/fw-updater usr/local/bin
|
||||
common/onie_mode_set usr/local/bin
|
@ -0,0 +1,10 @@
|
||||
# postinst script for S5224f
|
||||
|
||||
# Enable Dell-S5224f-platform-service
|
||||
depmod -a
|
||||
systemctl enable platform-modules-s5224f.service
|
||||
systemctl start platform-modules-s5224f.service
|
||||
|
||||
|
||||
#DEBHELPER#
|
||||
|
@ -5,7 +5,7 @@ export INSTALL_MOD_DIR:=extra
|
||||
KVERSION ?= $(shell uname -r)
|
||||
KERNEL_SRC := /lib/modules/$(KVERSION)
|
||||
MOD_SRC_DIR:= $(shell pwd)
|
||||
MODULE_DIRS:= s6000 z9100 s6100 z9264f s5232f s5248f z9332f s5296f n3248pxe n3248te
|
||||
MODULE_DIRS:= s6000 z9100 s6100 z9264f s5224f s5232f s5248f z9332f s5296f n3248pxe n3248te
|
||||
COMMON_DIR := common
|
||||
|
||||
%:
|
||||
@ -39,6 +39,11 @@ override_dh_auto_build:
|
||||
python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
|
||||
python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
|
||||
cd $(MOD_SRC_DIR); \
|
||||
elif [ $$mod = "s5224f" ]; then \
|
||||
cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \
|
||||
cd $(MOD_SRC_DIR)/$${mod}; \
|
||||
python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
|
||||
cd $(MOD_SRC_DIR); \
|
||||
elif [ $$mod = "s5232f" ]; then \
|
||||
cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \
|
||||
cd $(MOD_SRC_DIR)/$${mod}; \
|
||||
@ -114,6 +119,11 @@ override_dh_clean:
|
||||
rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \
|
||||
rm -rf $(MOD_SRC_DIR)/$${mod}/build; \
|
||||
rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \
|
||||
elif [ $$mod = "s5224f" ]; then \
|
||||
rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \
|
||||
rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \
|
||||
rm -rf $(MOD_SRC_DIR)/$${mod}/build; \
|
||||
rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \
|
||||
elif [ $$mod = "s5232f" ]; then \
|
||||
rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \
|
||||
rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \
|
||||
|
@ -0,0 +1,19 @@
|
||||
# /etc/modules: kernel modules to load at boot time.
|
||||
#
|
||||
# This file contains the names of kernel modules that should be loaded
|
||||
# at boot time, one per line. Lines beginning with "#" are ignored.
|
||||
|
||||
i2c-i801
|
||||
i2c-isch
|
||||
i2c-ismt
|
||||
i2c-dev
|
||||
i2c-mux
|
||||
i2c-smbus
|
||||
|
||||
i2c-mux-gpio
|
||||
i2c-mux-pca954x
|
||||
|
||||
ipmi_devintf
|
||||
ipmi_si
|
||||
dell_s5224f_fpga_ocores
|
||||
i2c_ocores
|
@ -0,0 +1 @@
|
||||
options ipmi_si kipmid_max_busy_us=1000
|
@ -0,0 +1,2 @@
|
||||
obj-m := dell_s5224f_fpga_ocores.o
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,3 @@
|
||||
# Temporary dummy file for s5224f.
|
||||
# Will be updated soon.
|
||||
|
@ -0,0 +1,102 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright (c) 2015 Dell Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
|
||||
# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
#
|
||||
# See the Apache Version 2.0 License for specific language governing
|
||||
# permissions and limitations under the License.
|
||||
|
||||
import struct
|
||||
import sys
|
||||
import getopt
|
||||
from os import *
|
||||
from mmap import *
|
||||
|
||||
def usage():
|
||||
''' This is the Usage Method '''
|
||||
|
||||
print '\t\t pcisysfs.py --get --offset <offset> --res <resource>'
|
||||
print '\t\t pcisysfs.py --set --val <val> --offset <offset> --res <resource>'
|
||||
sys.exit(1)
|
||||
|
||||
def pci_mem_read(mm,offset):
|
||||
mm.seek(offset)
|
||||
read_data_stream=mm.read(4)
|
||||
print ""
|
||||
reg_val=struct.unpack('I',read_data_stream)
|
||||
print "reg_val read:%x"%reg_val
|
||||
return reg_val
|
||||
|
||||
def pci_mem_write(mm,offset,data):
|
||||
mm.seek(offset)
|
||||
print "data to write:%x"%data
|
||||
mm.write(struct.pack('I',data))
|
||||
|
||||
def pci_set_value(resource,val,offset):
|
||||
fd=open(resource,O_RDWR)
|
||||
mm=mmap(fd,0)
|
||||
pci_mem_write(mm,offset,val)
|
||||
|
||||
def pci_get_value(resource,offset):
|
||||
fd=open(resource,O_RDWR)
|
||||
mm=mmap(fd,0)
|
||||
pci_mem_read(mm,offset)
|
||||
|
||||
def main(argv):
|
||||
|
||||
''' The main function will read the user input from the
|
||||
command line argument and process the request '''
|
||||
|
||||
opts = ''
|
||||
val = ''
|
||||
choice = ''
|
||||
resource = ''
|
||||
offset = ''
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(argv, "hgsv:" , \
|
||||
["val=","res=","offset=","help", "get", "set"])
|
||||
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
|
||||
for opt,arg in opts:
|
||||
|
||||
if opt in ('-h','--help'):
|
||||
choice = 'help'
|
||||
|
||||
elif opt in ('-g', '--get'):
|
||||
choice = 'get'
|
||||
|
||||
elif opt in ('-s', '--set'):
|
||||
choice = 'set'
|
||||
|
||||
elif opt == '--res':
|
||||
resource = arg
|
||||
|
||||
elif opt == '--val':
|
||||
val = int(arg,16)
|
||||
|
||||
elif opt == '--offset':
|
||||
offset = int(arg,16)
|
||||
|
||||
if choice == 'set' and val != '' and offset !='' and resource !='':
|
||||
pci_set_value(resource,val,offset)
|
||||
|
||||
elif choice == 'get' and offset != '' and resource !='':
|
||||
pci_get_value(resource,offset)
|
||||
|
||||
else:
|
||||
usage()
|
||||
|
||||
#Calling the main method
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
|
@ -0,0 +1,321 @@
|
||||
#!/usr/bin/python
|
||||
# On S5224F, the BaseBoard Management Controller is an
|
||||
# autonomous subsystem provides monitoring and management
|
||||
# facility independent of the host CPU. IPMI standard
|
||||
# protocol is used with ipmitool to fetch sensor details.
|
||||
# Current script support X00 board only. X01 support will
|
||||
# be added soon. This provies support for the
|
||||
# following objects:
|
||||
# * Onboard temperature sensors
|
||||
# * FAN trays
|
||||
# * PSU
|
||||
|
||||
|
||||
import sys
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
S5224F_MAX_FAN_TRAYS = 4
|
||||
S5224F_MAX_PSUS = 2
|
||||
IPMI_SENSOR_DATA = "ipmitool sdr list"
|
||||
IPMI_SENSOR_DUMP = "/tmp/sdr"
|
||||
|
||||
PSU_PRESENCE = "PSU{0}_stat"
|
||||
# Use this for older firmware
|
||||
# PSU_PRESENCE="PSU{0}_prsnt"
|
||||
|
||||
IPMI_FAN_PRESENCE = "ipmitool sensor get FAN{0}_prsnt"
|
||||
IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x31 | awk '{print substr($0,9,1)}'"
|
||||
IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x32 | awk '{print substr($0,9,1)}'"
|
||||
IPMI_RAW_STORAGE_READ = "ipmitool raw 0x0a 0x11 {0} 0 0 0xa0"
|
||||
IPMI_FRU = "ipmitool fru"
|
||||
ipmi_sdr_list = ""
|
||||
|
||||
# Dump sensor registers
|
||||
|
||||
|
||||
def ipmi_sensor_dump():
|
||||
|
||||
global ipmi_sdr_list
|
||||
ipmi_cmd = IPMI_SENSOR_DATA
|
||||
status, ipmi_sdr_list = subprocess.getstatusoutput(ipmi_cmd)
|
||||
|
||||
if status:
|
||||
logging.error('Failed to execute:' + ipmi_sdr_list)
|
||||
sys.exit(0)
|
||||
|
||||
# Fetch a Fan Status
|
||||
|
||||
def get_fan_status(fan_id):
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_FAN_PRESENCE.format(fan_id))
|
||||
if ret_status:
|
||||
logging.error('Failed to execute : %s'%IPMI_FAN_PRESENCE.format(fan_id))
|
||||
sys.exit(0)
|
||||
return(' ' + ipmi_cmd_ret.splitlines()[5].strip(' ').strip('[]'))
|
||||
|
||||
# Fetch a BMC register
|
||||
|
||||
|
||||
def get_pmc_register(reg_name):
|
||||
|
||||
output = None
|
||||
for item in ipmi_sdr_list.split("\n"):
|
||||
if reg_name in item:
|
||||
output = item.strip()
|
||||
|
||||
if output is None:
|
||||
print('\nFailed to fetch: ' + reg_name + ' sensor ')
|
||||
sys.exit(0)
|
||||
|
||||
output = output.split('|')[1]
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
return output
|
||||
|
||||
#Fetch FRU Data for given fruid
|
||||
def get_psu_airflow(psu_id):
|
||||
fru_id = 'PSU' + str(psu_id) + '_fru'
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_FRU)
|
||||
if ret_status:
|
||||
logging.error('Failed to execute ipmitool: '+ IPMI_FRU)
|
||||
sys.exit(0)
|
||||
found_fru = False
|
||||
for line in ipmi_cmd_ret.splitlines():
|
||||
if line.startswith('FRU Device Description') and fru_id in line.split(':')[1] :
|
||||
found_fru = True
|
||||
if found_fru and line.startswith(' Board Product '):
|
||||
return 'Intake' if 'PS/IO' in line else 'Exhaust'
|
||||
return ''
|
||||
|
||||
# Fetch FRU on given offset
|
||||
def fetch_raw_fru(dev_id, offset):
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_RAW_STORAGE_READ.format(dev_id))
|
||||
if ret_status:
|
||||
logging.error('Failed to execute ipmitool :' + IPMI_RAW_STORAGE_READ.format(dev_id))
|
||||
sys.exit(0)
|
||||
return int((ipmi_cmd_ret.splitlines()[int(offset/16)]).split(' ')[(int(offset%16)+1)])
|
||||
|
||||
def get_fan_airflow(fan_id):
|
||||
Airflow_Direction = ['Exhaust', 'Intake']
|
||||
return Airflow_Direction[fetch_raw_fru(fan_id+2, 0x46)]
|
||||
|
||||
# Print the information for temperature sensors
|
||||
|
||||
|
||||
def print_temperature_sensors():
|
||||
|
||||
print("\nOnboard Temperature Sensors:")
|
||||
|
||||
print (' PT_Left_temp: ',\
|
||||
(get_pmc_register('PT_Left_temp')))
|
||||
print (' PT_Mid_temp: ',\
|
||||
(get_pmc_register('PT_Mid_temp')))
|
||||
print (' PT_Right_temp: ',\
|
||||
(get_pmc_register('PT_Right_temp')))
|
||||
print (' Broadcom Temp: ',\
|
||||
(get_pmc_register('NPU_Near_temp')))
|
||||
print (' Inlet Airflow Temp: ',\
|
||||
(get_pmc_register('ILET_AF_temp')))
|
||||
print (' CPU Temp: ',\
|
||||
(get_pmc_register('CPU_temp')))
|
||||
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput('echo 0 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us')
|
||||
if ret_status:
|
||||
logging.error("platform_sensors: Failed to set kipmid_max_busy_us to 0")
|
||||
ipmi_sensor_dump()
|
||||
|
||||
print_temperature_sensors()
|
||||
|
||||
# Print the information for 1 Fan Tray
|
||||
|
||||
|
||||
def print_fan_tray(tray):
|
||||
|
||||
Fan_Status = [' Normal', ' Abnormal']
|
||||
print (' Fan Tray ' + str(tray) + ':')
|
||||
|
||||
if (tray == 1):
|
||||
|
||||
fan1_status = int(get_pmc_register('FAN1_Front_stat'), 16)
|
||||
fan2_status = int(get_pmc_register('FAN1_Rear_stat'), 16)
|
||||
|
||||
print (' Fan1 Speed: ',\
|
||||
get_pmc_register('FAN1_Front_rpm'))
|
||||
print (' Fan2 Speed: ',\
|
||||
get_pmc_register('FAN1_Rear_rpm'))
|
||||
print (' Fan1 State: ',\
|
||||
Fan_Status[fan1_status])
|
||||
print (' Fan2 State: ',\
|
||||
Fan_Status[fan2_status])
|
||||
|
||||
elif (tray == 2):
|
||||
|
||||
fan1_status = int(get_pmc_register('FAN2_Front_stat'), 16)
|
||||
fan2_status = int(get_pmc_register('FAN2_Rear_stat'), 16)
|
||||
|
||||
print (' Fan1 Speed: ',\
|
||||
get_pmc_register('FAN2_Front_rpm'))
|
||||
print (' Fan2 Speed: ',\
|
||||
get_pmc_register('FAN2_Rear_rpm'))
|
||||
print (' Fan1 State: ',\
|
||||
Fan_Status[fan1_status])
|
||||
print (' Fan2 State: ',\
|
||||
Fan_Status[fan2_status])
|
||||
|
||||
elif (tray == 3):
|
||||
|
||||
fan1_status = int(get_pmc_register('FAN3_Front_stat'), 16)
|
||||
fan2_status = int(get_pmc_register('FAN3_Rear_stat'), 16)
|
||||
|
||||
print (' Fan1 Speed: ',\
|
||||
get_pmc_register('FAN3_Front_rpm'))
|
||||
print (' Fan2 Speed: ',\
|
||||
get_pmc_register('FAN3_Rear_rpm'))
|
||||
print (' Fan1 State: ',\
|
||||
Fan_Status[fan1_status])
|
||||
print (' Fan2 State: ',\
|
||||
Fan_Status[fan2_status])
|
||||
|
||||
elif (tray == 4):
|
||||
|
||||
fan1_status = int(get_pmc_register('FAN4_Front_stat'), 16)
|
||||
fan2_status = int(get_pmc_register('FAN4_Rear_stat'), 16)
|
||||
|
||||
print (' Fan1 Speed: ',\
|
||||
get_pmc_register('FAN4_Front_rpm'))
|
||||
print (' Fan2 Speed: ',\
|
||||
get_pmc_register('FAN4_Rear_rpm'))
|
||||
print (' Fan1 State: ',\
|
||||
Fan_Status[fan1_status])
|
||||
print (' Fan2 State: ',\
|
||||
Fan_Status[fan2_status])
|
||||
print (' Airflow: ',\
|
||||
get_fan_airflow(tray))
|
||||
|
||||
|
||||
print('\nFan Trays:')
|
||||
|
||||
for tray in range(1, S5224F_MAX_FAN_TRAYS + 1):
|
||||
if (get_fan_status(tray) == ' Present'):
|
||||
print_fan_tray(tray)
|
||||
else:
|
||||
print (' Fan Tray %d:' % (tray))
|
||||
print (' Fan State: Not present')
|
||||
|
||||
def get_psu_presence(index):
|
||||
"""
|
||||
Retrieves the presence status of power supply unit (PSU) defined
|
||||
by index <index>
|
||||
:param index: An integer, index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is plugged, False if not
|
||||
"""
|
||||
ret_status = 1
|
||||
|
||||
if index == 1:
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
|
||||
elif index == 2:
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
|
||||
|
||||
if ret_status:
|
||||
logging.error('Failed to execute ipmitool :' + IPMI_PSU1_DATA_DOCKER)
|
||||
sys.exit(0)
|
||||
|
||||
psu_status = ipmi_cmd_ret
|
||||
return (int(psu_status, 16) & 1)
|
||||
|
||||
def get_psu_status(index):
|
||||
"""
|
||||
Retrieves the presence status of power supply unit (PSU) defined
|
||||
by index <index>
|
||||
:param index: An integer, index of the PSU of which to query status
|
||||
:return: Boolean, True if PSU is plugged, False if not
|
||||
"""
|
||||
ret_status = 1
|
||||
ipmi_cmd_ret = 'f'
|
||||
|
||||
if index == 1:
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
|
||||
elif index == 2:
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
|
||||
|
||||
if ret_status:
|
||||
logging.error('Failed to execute ipmitool : ' + IPMI_PSU2_DATA_DOCKER)
|
||||
sys.exit(0)
|
||||
|
||||
psu_status = ipmi_cmd_ret
|
||||
|
||||
return (not int(psu_status, 16) > 1)
|
||||
|
||||
|
||||
# Print the information for PSU1, PSU2
|
||||
def print_psu(psu):
|
||||
|
||||
# PSU FAN details
|
||||
if (psu == 1):
|
||||
|
||||
print (' PSU1:')
|
||||
print (' FAN Normal Temperature: ',\
|
||||
get_pmc_register('PSU1_temp'))
|
||||
print (' FAN AirFlow Temperature: ',\
|
||||
get_pmc_register('PSU1_AF_temp'))
|
||||
print (' FAN RPM: ',\
|
||||
get_pmc_register('PSU1_rpm'))
|
||||
|
||||
# PSU input & output monitors
|
||||
print (' Input Voltage: ',\
|
||||
get_pmc_register('PSU1_In_volt'))
|
||||
print (' Output Voltage: ',\
|
||||
get_pmc_register('PSU1_Out_volt'))
|
||||
print (' Input Power: ',\
|
||||
get_pmc_register('PSU1_In_watt'))
|
||||
print (' Output Power: ',\
|
||||
get_pmc_register('PSU1_Out_watt'))
|
||||
print (' Input Current: ',\
|
||||
get_pmc_register('PSU1_In_amp'))
|
||||
print (' Output Current: ',\
|
||||
get_pmc_register('PSU1_Out_amp'))
|
||||
|
||||
else:
|
||||
|
||||
print (' PSU2:')
|
||||
print (' FAN Normal Temperature: ',\
|
||||
get_pmc_register('PSU2_temp'))
|
||||
print (' FAN AirFlow Temperature: ',\
|
||||
get_pmc_register('PSU2_AF_temp'))
|
||||
print (' FAN RPM: ',\
|
||||
get_pmc_register('PSU2_rpm'))
|
||||
|
||||
# PSU input & output monitors
|
||||
print (' Input Voltage: ',\
|
||||
get_pmc_register('PSU2_In_volt'))
|
||||
print (' Output Voltage: ',\
|
||||
get_pmc_register('PSU2_Out_volt'))
|
||||
print (' Input Power: ',\
|
||||
get_pmc_register('PSU2_In_watt'))
|
||||
print (' Output Power: ',\
|
||||
get_pmc_register('PSU2_Out_watt'))
|
||||
print (' Input Current: ',\
|
||||
get_pmc_register('PSU2_In_amp'))
|
||||
print (' Output Current: ',\
|
||||
get_pmc_register('PSU2_Out_amp'))
|
||||
print (' Airflow: ',\
|
||||
get_psu_airflow(psu))
|
||||
|
||||
|
||||
print('\nPSUs:')
|
||||
for psu in range(1, S5224F_MAX_PSUS + 1):
|
||||
if not get_psu_presence(psu):
|
||||
print (' PSU%d:' % (psu))
|
||||
print (' Status: Not present')
|
||||
elif not get_psu_status(psu) :
|
||||
print (' PSU%d:' % (psu))
|
||||
print (' Status: Not OK')
|
||||
else:
|
||||
print_psu(psu)
|
||||
|
||||
print ('\n Total Power: ',\
|
||||
get_pmc_register('PSU_Total_watt'))
|
||||
|
||||
ret_status, ipmi_cmd_ret = subprocess.getstatusoutput('echo 1000 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us')
|
||||
if ret_status:
|
||||
logging.error("platform_sensors: Failed to set kipmid_max_busy_us to 1000")
|
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# No IRQ support for S5224F
|
202
platform/broadcom/sonic-platform-modules-dell/s5224f/scripts/s5224f_platform.sh
Executable file
202
platform/broadcom/sonic-platform-modules-dell/s5224f/scripts/s5224f_platform.sh
Executable file
@ -0,0 +1,202 @@
|
||||
#!/bin/bash
|
||||
|
||||
init_devnum() {
|
||||
found=0
|
||||
for devnum in 0 1; do
|
||||
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
|
||||
# iSMT adapter can be at either dffd0000 or dfff0000
|
||||
if [[ $devname == 'SMBus iSMT adapter at '* ]]; then
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
[ $found -eq 0 ] && echo "cannot find iSMT" && exit 1
|
||||
}
|
||||
|
||||
# Attach/Detach syseeprom on CPU board
|
||||
sys_eeprom() {
|
||||
b=''
|
||||
for bb in 0 1; do
|
||||
if [ "$(cat /sys/bus/i2c/devices/i2c-${bb}/name)" = 'SMBus iSMT adapter at dff9f000' ]; then
|
||||
b=$bb
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$b" = '' ]; then
|
||||
echo "s5224f_platform: sys_eeprom : cannot find I2C bus!"
|
||||
return
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
"new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-${b}/$1
|
||||
;;
|
||||
"delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-${b}/$1
|
||||
;;
|
||||
*) echo "s5224f_platform: sys_eeprom : invalid command !"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
#Attach/Detach the MUX connecting all SFP28s/QSFP28s
|
||||
switch_board_qsfp_mux() {
|
||||
case $1 in
|
||||
"new_device")
|
||||
for ((i=603;i<=606;i++));
|
||||
do
|
||||
echo "Attaching PCA9548 @ 0x74"
|
||||
echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$i/$1
|
||||
done
|
||||
|
||||
;;
|
||||
"delete_device")
|
||||
for ((i=603;i<=606;i++));
|
||||
do
|
||||
echo "Detaching PCA9548 @ 0x74"
|
||||
echo 0x74 > /sys/bus/i2c/devices/i2c-$i/$1
|
||||
done
|
||||
|
||||
;;
|
||||
*) echo "s5224f_platform: switch_board_qsfp_mux: invalid command !"
|
||||
;;
|
||||
esac
|
||||
sleep 2
|
||||
}
|
||||
|
||||
#Attach/Detach 24 instances of EEPROM driver SFP28 ports. Use optoe2 (for dual address devices)
|
||||
#Attach/Detach 4 instances of EEPROM driver QSFP28 ports. Use optoe1 (for single address devices)
|
||||
#eeprom can dump data using below command
|
||||
switch_board_qsfp() {
|
||||
case $1 in
|
||||
"new_device")
|
||||
for ((i=2;i<=25;i++));
|
||||
do
|
||||
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
|
||||
done
|
||||
for ((i=26;i<=29;i++));
|
||||
do
|
||||
echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
|
||||
done
|
||||
;;
|
||||
|
||||
"delete_device")
|
||||
for ((i=2;i<=29;i++));
|
||||
do
|
||||
echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
|
||||
done
|
||||
;;
|
||||
|
||||
*) echo "s5224f_platform: switch_board_qsfp: invalid command !"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
#Modsel 4 ports to applicable QSFP28 type modules
|
||||
#This enables the adapter to respond for i2c commands
|
||||
switch_board_modsel() {
|
||||
resource="/sys/bus/pci/devices/0000:04:00.0/resource0"
|
||||
for ((i=1;i<=28;i++));
|
||||
do
|
||||
port_addr=$(( 16384 + ((i - 1) * 16)))
|
||||
hex=$( printf "0x%x" $port_addr )
|
||||
python /usr/bin/pcisysfs.py --set --offset $hex --val 0x10 --res $resource > /dev/null 2>&1
|
||||
done
|
||||
}
|
||||
|
||||
platform_firmware_versions() {
|
||||
FIRMWARE_VERSION_FILE=/var/log/firmware_versions
|
||||
rm -rf ${FIRMWARE_VERSION_FILE}
|
||||
echo "BIOS: `dmidecode -s system-version `" > $FIRMWARE_VERSION_FILE
|
||||
## Get FPGA version
|
||||
r=`/usr/bin/pcisysfs.py --get --offset 0x00 --res /sys/bus/pci/devices/0000\:04\:00.0/resource0 | sed '1d; s/.*\(....\)$/\1/; s/\(..\{1\}\)/\1./'`
|
||||
r_min=$(echo $r | sed 's/.*\(..\)$/0x\1/')
|
||||
r_maj=$(echo $r | sed 's/^\(..\).*/0x\1/')
|
||||
echo "FPGA: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
|
||||
|
||||
## Get BMC Firmware Revision
|
||||
r=`cat /sys/class/ipmi/ipmi0/device/bmc/firmware_revision`
|
||||
echo "BMC: $r" >> $FIRMWARE_VERSION_FILE
|
||||
|
||||
#System CPLD 0x31 on i2c bus 601 ( physical FPGA I2C-2)
|
||||
r_min=`/usr/sbin/i2cget -y 601 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'`
|
||||
r_maj=`/usr/sbin/i2cget -y 601 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'`
|
||||
echo "System CPLD: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
|
||||
|
||||
#Slave CPLD 1 0x30 on i2c bus 600 ( physical FPGA I2C-1)
|
||||
r_min=`/usr/sbin/i2cget -y 600 0x30 0x0 | sed ' s/.*\(0x..\)$/\1/'`
|
||||
r_maj=`/usr/sbin/i2cget -y 600 0x30 0x1 | sed ' s/.*\(0x..\)$/\1/'`
|
||||
echo "Slave CPLD 1: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
|
||||
|
||||
#Slave CPLD 2 0x31 on i2c bus 600 ( physical FPGA I2C-1)
|
||||
r_min=`/usr/sbin/i2cget -y 600 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'`
|
||||
r_maj=`/usr/sbin/i2cget -y 600 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'`
|
||||
echo "Slave CPLD 2: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
|
||||
|
||||
}
|
||||
|
||||
install_python_api_package() {
|
||||
device="/usr/share/sonic/device"
|
||||
platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform)
|
||||
|
||||
rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl)
|
||||
}
|
||||
|
||||
remove_python_api_package() {
|
||||
rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null)
|
||||
fi
|
||||
}
|
||||
|
||||
get_reboot_cause() {
|
||||
REBOOT_REASON_FILE="/host/reboot-cause/platform/reboot_reason"
|
||||
resource="/sys/bus/pci/devices/0000:04:00.0/resource0"
|
||||
|
||||
mkdir -p $(dirname $REBOOT_REASON_FILE)
|
||||
|
||||
# Handle First Boot into software version with reboot cause determination support
|
||||
if [[ ! -e $REBOOT_REASON_FILE ]]; then
|
||||
echo "0" > $REBOOT_REASON_FILE
|
||||
else
|
||||
/usr/bin/pcisysfs.py --get --offset 0x18 --res $resource | sed '1d; s/.*:\(.*\)$/\1/;' > $REBOOT_REASON_FILE
|
||||
fi
|
||||
/usr/bin/pcisysfs.py --set --val 0x0 --offset 0x18 --res $resource
|
||||
}
|
||||
|
||||
#This enables the led control for CPU and default states
|
||||
switch_board_led_default() {
|
||||
resource="/sys/bus/pci/devices/0000:04:00.0/resource0"
|
||||
python /usr/bin/pcisysfs.py --set --offset 0x24 --val 0x194 --res $resource > /dev/null 2>&1
|
||||
}
|
||||
init_devnum
|
||||
|
||||
if [ "$1" == "init" ]; then
|
||||
modprobe i2c-dev
|
||||
modprobe i2c-mux-pca954x force_deselect_on_exit=1
|
||||
modprobe ipmi_devintf
|
||||
modprobe ipmi_si kipmid_max_busy_us=1000
|
||||
modprobe i2c_ocores
|
||||
modprobe dell_s5224f_fpga_ocores
|
||||
sys_eeprom "new_device"
|
||||
get_reboot_cause
|
||||
switch_board_qsfp_mux "new_device"
|
||||
switch_board_qsfp "new_device"
|
||||
switch_board_modsel
|
||||
switch_board_led_default
|
||||
install_python_api_package
|
||||
#python /usr/bin/qsfp_irq_enable.py
|
||||
platform_firmware_versions
|
||||
|
||||
elif [ "$1" == "deinit" ]; then
|
||||
sys_eeprom "delete_device"
|
||||
switch_board_qsfp "delete_device"
|
||||
switch_board_qsfp_mux "delete_device"
|
||||
|
||||
modprobe -r i2c-mux-pca954x
|
||||
modprobe -r i2c-dev
|
||||
remove_python_api_package
|
||||
modprobe -r ipmi_devintf
|
||||
modprobe -r ipmi_si
|
||||
else
|
||||
echo "s5224f_platform : Invalid option !"
|
||||
fi
|
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
docker exec -i pmon sensors "$@"
|
||||
docker exec -i pmon /usr/bin/platform_sensors.py "$@"
|
||||
|
||||
#To probe sensors not part of lm-sensors
|
||||
#if [ -r /usr/local/bin/platform_sensors.py ]; then
|
||||
# python /usr/local/bin/platform_sensors.py
|
||||
#fi
|
1
platform/broadcom/sonic-platform-modules-dell/s5224f/setup.py
Symbolic link
1
platform/broadcom/sonic-platform-modules-dell/s5224f/setup.py
Symbolic link
@ -0,0 +1 @@
|
||||
../s6100/setup.py
|
@ -0,0 +1,3 @@
|
||||
__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "thermal", "psu", "fan", "fan_drawer", "watchdog"]
|
||||
from sonic_platform import *
|
||||
|
@ -0,0 +1,340 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# DELLEMC S5224F
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the platform information
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
try:
|
||||
import time
|
||||
import sys
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.sfp import Sfp
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
from sonic_platform.component import Component
|
||||
from sonic_platform.psu import Psu
|
||||
from sonic_platform.thermal import Thermal
|
||||
from sonic_platform.watchdog import Watchdog
|
||||
from sonic_platform.fan import Fan
|
||||
from sonic_platform.fan_drawer import FanDrawer
|
||||
from sonic_platform.hwaccess import pci_get_value, pci_set_value
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
MAX_S5224F_COMPONENT = 5
|
||||
MAX_S5224F_FANTRAY =4
|
||||
MAX_S5224F_FAN = 2
|
||||
MAX_S5224F_PSU = 2
|
||||
MAX_S5224F_THERMAL = 8
|
||||
SYSTEM_LED_REG = 0x24
|
||||
SYSTEM_BEACON_LED_SET = 0x8
|
||||
SYSTEM_BEACON_LED_CLEAR = 0xFFFFFFF7
|
||||
|
||||
media_part_num_list = set([ \
|
||||
"8T47V","XTY28","MHVPK","GF76J","J6FGD","F1KMV","9DN5J","H4DHD","6MCNV","0WRX0","X7F70","5R2PT","WTRD1","WTRD1","WTRD1","WTRD1","5250G","WTRD1","C5RNH","C5RNH","FTLX8571D3BCL-FC",
|
||||
"C5RNH","5250G","N8TDR","7D64H","7D64H","RN84N","RN84N","HMTNW","6K3Y6","6K3Y6","TY5FM","50M0R","PGYJT","WP2PP","85Y13","1HCGH","FP9R1","FYD0M","C6Y7M","C6Y7M","V250M","V250M",
|
||||
"5CWK6","5CWK6","53HVN","53HVN","358VV","358VV","MV799","MV799","YJF03","P9GND","T1KCN","1DXKP","MT7R2","K0T7R","W5G04","7TCDN","7TCDN","7TCDN","7TCDN","7TCDN","V3XJK","0MV31",
|
||||
"5FVP7","N6KM9","C41MF","77KC3","XW7J0","V4NJV","2XJHY","H93DH","H93DH","F8CG0","F8CG0","F8CG0","119N6","WFMF5","794RX","288F6","1M31V","1M31V","5NP8R","5NP8R","4TC09","4TC09",
|
||||
"FC6KV","FC6KV","J90VN","J90VN","05RH0","05RH0","YDN52","0C2YV","YDN52","0C2YV","9JT65","D7M6H","6GW14","FYVFW","0VF5H","P4YPY","P4YPY","TCPM2","TCPM2","JNPF8","JNPF8","27GG5",
|
||||
"27GG5","P8T4W","P8T4W","JR54Y","M6N0J","XJYD0","K44H9","035KG","P7C7N","76V43","3CC35","FN4FC","26FN3","YFNDD","YFNDD","7R9N9","035KG","P7C7N","76V43","3CC35","PLRXPLSCS43811",
|
||||
"FN4FC","26FN3","YFNDD","YFNDD","7R9N9","G86YJ","V407F","V407F","9KH6T","G86YJ","V407F","9KH6T","2JVDD","D0R73","VXFJY","9X8JP","2JVDD","D0R73","VXFJY","9X8JP","2JVDD","D0R73","VXFJY",
|
||||
"9X8JP","GMFC5","GMFC5","GMFC5","D7P80","3MFXG","3MFXG","0GWXJ","THPF3","THPF3","THPF3","THPF3","THPF3","PJ62G","3XCX1","JJYKG","RRRTK","16K56","86JM2","K5R6C","7MG2C","WTPPN","9HTT2",
|
||||
"NKM4F","VXGGG","JC9W6","6MR8M","RP3GV","M5PPJ","XKY55","TKCXT","05J8P","5WGKD","XFDRT","NW8DM","YPKH3","5WGKD","XFDRT","NW8DM","YPKH3","71XXK","MVCX6","0XYP6","HPPVW","3GHRT","71XXK",
|
||||
"MVCX6","0XYP6","HPPVW","3GHRT","2X5T6","135V2","KD5MV","2X5T6","KD5MV","HHFK0","3YWG7","5CMT2","RCVP5","X5DH4","HHFK0","3YWG7","5CMT2","RCVP5","X5DH4","3YWG7","5CMT2","RCVP5","X5DH4",
|
||||
"4WJ41","4WJ41","14NV5","14NV5","14NV5","4WGYD","YKMH7","X7CCC","X7CCC","0X9CT","0CY8V","P7D7R","W4GPP","W4GPP","W4GPP","HHHCHC","07RN7","07RN7","0YR96","0YR96","JCYM9","FTLX8571D3BCL",
|
||||
"DDW0X","VPFDJ","229KM","9FC7D","DDW0X","VPFDJ","6FMR5","J7K20","N3K9W","6FMR5","8R4VM","7VN5T","D9YM8","8R4VM","VYXPW","87TPX","WY6FK","VYXPW","87TPX","WY6FK","WG8C4","N8K82","2DV6Y",
|
||||
"77C3C","RC0HM","77C3C","RC0HM","JHXTN","3P3PG","92YVM","4VX5M","4VX5M","6RRGD","W4JWV","22V6R","XR11M","9GMDY","JMCWK","TP2F0","6MGDY","78RHK", "C0TP5","0WDNV","FCLF8522P2BTL"\
|
||||
])
|
||||
|
||||
class Chassis(ChassisBase):
|
||||
"""
|
||||
DELLEMC Platform-specific Chassis class
|
||||
"""
|
||||
|
||||
REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason"
|
||||
OIR_FD_PATH = "/sys/bus/pci/devices/0000:04:00.0/port_msi"
|
||||
|
||||
_global_port_pres_dict = {}
|
||||
|
||||
def __init__(self):
|
||||
ChassisBase.__init__(self)
|
||||
# sfp.py will read eeprom contents and retrive the eeprom data.
|
||||
# We pass the eeprom path from chassis.py
|
||||
self.PORT_START = 1
|
||||
self.PORT_END = 28
|
||||
self.SFP28_PORT_END = 24
|
||||
|
||||
PORTS_IN_BLOCK = (self.PORT_END + 1)
|
||||
_sfp_port = range(1, self.SFP28_PORT_END + 1)
|
||||
eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
|
||||
|
||||
for index in range(self.PORT_START, PORTS_IN_BLOCK):
|
||||
port_num = index + 1
|
||||
eeprom_path = eeprom_base.format(port_num)
|
||||
if index not in _sfp_port:
|
||||
sfp_node = Sfp(index, 'QSFP', eeprom_path)
|
||||
else:
|
||||
sfp_node = Sfp(index, 'SFP', eeprom_path)
|
||||
self._sfp_list.append(sfp_node)
|
||||
|
||||
self._eeprom = Eeprom()
|
||||
self._watchdog = Watchdog()
|
||||
self._num_sfps = self.PORT_END
|
||||
self._num_fans = MAX_S5224F_FAN * MAX_S5224F_FANTRAY
|
||||
|
||||
for i in range(MAX_S5224F_THERMAL):
|
||||
thermal = Thermal(i)
|
||||
self._thermal_list.append(thermal)
|
||||
|
||||
for i in range(MAX_S5224F_COMPONENT):
|
||||
component = Component(i)
|
||||
self._component_list.append(component)
|
||||
|
||||
for i in range(MAX_S5224F_PSU):
|
||||
psu = Psu(i)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
for i in range(MAX_S5224F_FANTRAY):
|
||||
for j in range(MAX_S5224F_FAN):
|
||||
fan = Fan(i,j)
|
||||
self._fan_list.append(fan)
|
||||
|
||||
for i in range(MAX_S5224F_FANTRAY):
|
||||
fandrawer = FanDrawer(i)
|
||||
self._fan_drawer_list.append(fandrawer)
|
||||
self._fan_list.extend(fandrawer._fan_list)
|
||||
|
||||
for port_num in range(self.PORT_START, (self.PORT_END + 1)):
|
||||
# sfp get uses zero-indexing, but port numbers start from 1
|
||||
presence = self.get_sfp(port_num-1).get_presence()
|
||||
if presence:
|
||||
self._global_port_pres_dict[port_num] = '1'
|
||||
else:
|
||||
self._global_port_pres_dict[port_num] = '0'
|
||||
|
||||
# check for this event change for sfp / do we need to handle timeout/sleep
|
||||
|
||||
def get_change_event(self, timeout=0):
|
||||
"""
|
||||
Returns a nested dictionary containing all devices which have
|
||||
experienced a change at chassis level
|
||||
"""
|
||||
start_ms = time.time() * 1000
|
||||
port_dict = {}
|
||||
change_dict = {}
|
||||
change_dict['sfp'] = port_dict
|
||||
while True:
|
||||
time.sleep(0.5)
|
||||
for port_num in range(self.PORT_START, (self.PORT_END + 1)):
|
||||
presence = self.get_sfp(port_num-1).get_presence()
|
||||
if(presence and self._global_port_pres_dict[port_num] == '0'):
|
||||
self._global_port_pres_dict[port_num] = '1'
|
||||
port_dict[port_num] = '1'
|
||||
elif(not presence and
|
||||
self._global_port_pres_dict[port_num] == '1'):
|
||||
self._global_port_pres_dict[port_num] = '0'
|
||||
port_dict[port_num] = '0'
|
||||
|
||||
if(len(port_dict) > 0):
|
||||
return True, change_dict
|
||||
|
||||
if timeout:
|
||||
now_ms = time.time() * 1000
|
||||
if (now_ms - start_ms >= timeout):
|
||||
return True, change_dict
|
||||
|
||||
|
||||
def get_sfp(self, index):
|
||||
"""
|
||||
Retrieves sfp represented by (0-based) index <index>
|
||||
|
||||
Args:
|
||||
index: An integer, the index (0-based) of the sfp to retrieve.
|
||||
The index should be the sequence of a physical port in a chassis,
|
||||
starting from 0.
|
||||
For example, 0 for Ethernet0, 1 for Ethernet4 and so on.
|
||||
|
||||
Returns:
|
||||
An object dervied from SfpBase representing the specified sfp
|
||||
"""
|
||||
sfp = None
|
||||
|
||||
try:
|
||||
# The index will start from 0
|
||||
sfp = self._sfp_list[index-1]
|
||||
except IndexError:
|
||||
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
|
||||
index, len(self._sfp_list)))
|
||||
return sfp
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the chassis
|
||||
Returns:
|
||||
string: The name of the chassis
|
||||
"""
|
||||
return self._eeprom.modelstr()
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the chassis
|
||||
Returns:
|
||||
bool: True if chassis is present, False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the model number (or part number) of the chassis
|
||||
Returns:
|
||||
string: Model/part number of chassis
|
||||
"""
|
||||
return self._eeprom.part_number_str()
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the chassis (Service tag)
|
||||
Returns:
|
||||
string: Serial number of chassis
|
||||
"""
|
||||
return self._eeprom.serial_str()
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the chassis
|
||||
Returns:
|
||||
bool: A boolean value, True if chassis is operating properly
|
||||
False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_base_mac(self):
|
||||
"""
|
||||
Retrieves the base MAC address for the chassis
|
||||
Returns:
|
||||
A string containing the MAC address in the format
|
||||
'XX:XX:XX:XX:XX:XX'
|
||||
"""
|
||||
return self._eeprom.base_mac_addr('')
|
||||
|
||||
def get_serial_number(self):
|
||||
"""
|
||||
Retrieves the hardware serial number for the chassis
|
||||
Returns:
|
||||
A string containing the hardware serial number for this chassis.
|
||||
"""
|
||||
return self._eeprom.serial_number_str()
|
||||
|
||||
def get_system_eeprom_info(self):
|
||||
"""
|
||||
Retrieves the full content of system EEPROM information for the chassis
|
||||
Returns:
|
||||
A dictionary where keys are the type code defined in
|
||||
OCP ONIE TlvInfo EEPROM format and values are their corresponding
|
||||
values.
|
||||
"""
|
||||
return self._eeprom.system_eeprom_info()
|
||||
|
||||
def get_eeprom(self):
|
||||
"""
|
||||
Retrieves the Sys Eeprom instance for the chassis.
|
||||
Returns :
|
||||
The instance of the Sys Eeprom
|
||||
"""
|
||||
return self._eeprom
|
||||
|
||||
def get_num_fans(self):
|
||||
"""
|
||||
Retrives the number of Fans on the chassis.
|
||||
Returns :
|
||||
An integer represents the number of Fans on the chassis.
|
||||
"""
|
||||
return self._num_fans
|
||||
|
||||
def get_num_sfps(self):
|
||||
"""
|
||||
Retrives the numnber of Media on the chassis.
|
||||
Returns:
|
||||
An integer represences the number of SFPs on the chassis.
|
||||
"""
|
||||
return self._num_sfps
|
||||
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.
|
||||
"""
|
||||
try:
|
||||
with open(self.REBOOT_CAUSE_PATH) as fd:
|
||||
reboot_cause = int(fd.read(), 16)
|
||||
except EnvironmentError:
|
||||
return (self.REBOOT_CAUSE_NON_HARDWARE, None)
|
||||
|
||||
if reboot_cause & 0x1:
|
||||
return (self.REBOOT_CAUSE_POWER_LOSS, None)
|
||||
elif reboot_cause & 0x2:
|
||||
return (self.REBOOT_CAUSE_NON_HARDWARE, None)
|
||||
elif reboot_cause & 0x4:
|
||||
return (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown")
|
||||
elif reboot_cause & 0x8:
|
||||
return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None)
|
||||
elif reboot_cause & 0x10:
|
||||
return (self.REBOOT_CAUSE_WATCHDOG, None)
|
||||
elif reboot_cause & 0x20:
|
||||
return (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown")
|
||||
elif reboot_cause & 0x40:
|
||||
return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown")
|
||||
elif reboot_cause & 0x80:
|
||||
return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown")
|
||||
elif reboot_cause & 0x100:
|
||||
return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Cold Reboot")
|
||||
else:
|
||||
return (self.REBOOT_CAUSE_NON_HARDWARE, None)
|
||||
|
||||
def get_qualified_media_list(self):
|
||||
return media_part_num_list
|
||||
|
||||
def set_locator_led(self, color):
|
||||
"""
|
||||
Sets the state of the Chassis Locator LED
|
||||
|
||||
Args:
|
||||
color: A string representing the color with which to set the Chassis Locator LED
|
||||
|
||||
Returns:
|
||||
bool: True if the Chassis Locator LED state is set successfully, False if not
|
||||
|
||||
"""
|
||||
resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
|
||||
val = pci_get_value(resource, SYSTEM_LED_REG)
|
||||
if self.LOCATOR_LED_ON == color:
|
||||
val = int(val) | SYSTEM_BEACON_LED_SET
|
||||
elif self.LOCATOR_LED_OFF == color:
|
||||
val = int(val) & SYSTEM_BEACON_LED_CLEAR
|
||||
else:
|
||||
return False
|
||||
pci_set_value(resource, val, SYSTEM_LED_REG)
|
||||
return True
|
||||
|
||||
def get_locator_led(self):
|
||||
"""
|
||||
Gets the state of the Chassis Locator LED
|
||||
|
||||
Returns:
|
||||
LOCATOR_LED_ON or LOCATOR_LED_OFF
|
||||
"""
|
||||
resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
|
||||
val = pci_get_value(resource, SYSTEM_LED_REG)
|
||||
val = int(val) & SYSTEM_BEACON_LED_SET
|
||||
if not val:
|
||||
return self.LOCATOR_LED_OFF
|
||||
else:
|
||||
return self.LOCATOR_LED_ON
|
||||
|
@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# DELLEMC S5224F
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the Components' (e.g., BIOS, CPLD, FPGA, BMC etc.) available in
|
||||
# the platform
|
||||
#
|
||||
########################################################################
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
from sonic_platform_base.component_base import ComponentBase
|
||||
import sonic_platform.hwaccess as hwaccess
|
||||
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
def get_bios_version():
|
||||
return subprocess.check_output(['dmidecode', '-s', 'system-version']).strip()
|
||||
|
||||
def get_fpga_version():
|
||||
val = hwaccess.pci_get_value('/sys/bus/pci/devices/0000:03:00.0/resource0', 0)
|
||||
return '{}.{}'.format((val >> 8) & 0xff, val & 0xff)
|
||||
|
||||
def get_bmc_version():
|
||||
return subprocess.check_output(
|
||||
['cat', '/sys/class/ipmi/ipmi0/device/bmc/firmware_revision']
|
||||
).strip()
|
||||
|
||||
def get_cpld_version(bus, i2caddr):
|
||||
return '{}.{}'.format(hwaccess.i2c_get(bus, i2caddr, 1),
|
||||
hwaccess.i2c_get(bus, i2caddr, 0)
|
||||
)
|
||||
|
||||
def get_cpld0_version():
|
||||
return get_cpld_version(601, 0x31)
|
||||
|
||||
def get_cpld1_version():
|
||||
return get_cpld_version(600, 0x30)
|
||||
|
||||
|
||||
class Component(ComponentBase):
|
||||
"""DellEMC Platform-specific Component class"""
|
||||
|
||||
CHASSIS_COMPONENTS = [
|
||||
['BIOS',
|
||||
'Performs initialization of hardware components during booting',
|
||||
get_bios_version
|
||||
],
|
||||
|
||||
['FPGA',
|
||||
'Used for managing the system LEDs',
|
||||
get_fpga_version
|
||||
],
|
||||
|
||||
['BMC',
|
||||
'Platform management controller for on-board temperature monitoring, in-chassis power, Fan and LED control',
|
||||
get_bmc_version
|
||||
],
|
||||
|
||||
['System CPLD',
|
||||
'Used for managing the CPU power sequence and CPU states',
|
||||
get_cpld0_version
|
||||
],
|
||||
|
||||
['Slave CPLD 1',
|
||||
'Used for managing SFP28/QSFP28 port transceivers (SFP28 1-24, QSFP28 1-4)',
|
||||
get_cpld1_version
|
||||
]
|
||||
]
|
||||
|
||||
def __init__(self, component_index = 0):
|
||||
self.index = component_index
|
||||
self.name = self.CHASSIS_COMPONENTS[self.index][0]
|
||||
self.description = self.CHASSIS_COMPONENTS[self.index][1]
|
||||
self.version = self.CHASSIS_COMPONENTS[self.index][2]()
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the component
|
||||
Returns:
|
||||
A string containing the name of the component
|
||||
"""
|
||||
return self.name
|
||||
|
||||
def get_description(self):
|
||||
"""
|
||||
Retrieves the description of the component
|
||||
Returns:
|
||||
A string containing the description of the component
|
||||
"""
|
||||
return self.description
|
||||
|
||||
def get_firmware_version(self):
|
||||
"""
|
||||
Retrieves the firmware version of the component
|
||||
Returns:
|
||||
A string containing the firmware version of the component
|
||||
"""
|
||||
return self.version
|
||||
|
||||
def install_firmware(self, image_path):
|
||||
"""
|
||||
Installs firmware to the component
|
||||
Args:
|
||||
image_path: A string, path to firmware image
|
||||
Returns:
|
||||
A boolean, True if install was successful, False if not
|
||||
"""
|
||||
return False
|
@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# DellEmc S5224F
|
||||
#
|
||||
# Platform and model specific eeprom subclass, inherits from the base class,
|
||||
# and provides the followings:
|
||||
# - the eeprom format definition
|
||||
# - specific encoder/decoder if there is special need
|
||||
#############################################################################
|
||||
try:
|
||||
import os.path
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self):
|
||||
self.eeprom_path = None
|
||||
for b in (0, 1):
|
||||
f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b)
|
||||
if os.path.exists(f):
|
||||
self.eeprom_path = f
|
||||
break
|
||||
if self.eeprom_path is None:
|
||||
return
|
||||
super(Eeprom, self).__init__(self.eeprom_path, 0, '', True)
|
||||
self.eeprom_tlv_dict = dict()
|
||||
try:
|
||||
self.eeprom_data = self.read_eeprom()
|
||||
except Exception:
|
||||
self.eeprom_data = "N/A"
|
||||
raise RuntimeError("Eeprom is not Programmed")
|
||||
|
||||
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]
|
||||
|
||||
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):
|
||||
"""
|
||||
Returns the serial number
|
||||
"""
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
return results[2].decode('ascii')
|
||||
|
||||
def base_mac_addr(self, e):
|
||||
"""
|
||||
Returns the base mac address found in the system EEPROM
|
||||
"""
|
||||
(is_valid, t) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_MAC_BASE)
|
||||
if not is_valid or t[1] != 6:
|
||||
return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(t)
|
||||
|
||||
return ":".join(["{:02x}".format(T) for T in t[2]]).upper()
|
||||
|
||||
def modelstr(self):
|
||||
"""
|
||||
Returns the Model name
|
||||
"""
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_PRODUCT_NAME)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2].decode('ascii')
|
||||
|
||||
def part_number_str(self):
|
||||
"""
|
||||
Returns the part number
|
||||
"""
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_PART_NUMBER)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2].decode('ascii')
|
||||
|
||||
def serial_str(self):
|
||||
"""
|
||||
Returns the servicetag number
|
||||
"""
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_SERVICE_TAG)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2].decode('ascii')
|
||||
|
||||
def revision_str(self):
|
||||
"""
|
||||
Returns the device revision
|
||||
"""
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_DEVICE_VERSION)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2].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,185 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# DellEMC S5224F
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the Fans' information which are available in the platform.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_base import FanBase
|
||||
from sonic_platform.ipmihelper import IpmiSensor, IpmiFru
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
FAN1_MAX_SPEED_OFFSET = 71
|
||||
FAN2_MAX_SPEED_OFFSET = 73
|
||||
PSU_FAN_MAX_SPEED_OFFSET = 50
|
||||
FAN_DIRECTION_OFFSET = 69
|
||||
PSU_FAN_DIRECTION_OFFSET = 47
|
||||
|
||||
|
||||
class Fan(FanBase):
|
||||
"""DellEMC Platform-specific Fan class"""
|
||||
# { FAN-ID: { Sensor-Name: Sensor-ID } }
|
||||
# System rev X01, BMC firmware rev 1.02
|
||||
FAN_SENSOR_MAPPING = { 1: {"Prsnt": 0x53, "State": 0x57, "Speed": 0x24},
|
||||
2: {"Prsnt": 0x53, "State": 0x5b, "Speed": 0x20},
|
||||
3: {"Prsnt": 0x54, "State": 0x58, "Speed": 0x25},
|
||||
4: {"Prsnt": 0x54, "State": 0x5c, "Speed": 0x21},
|
||||
5: {"Prsnt": 0x55, "State": 0x59, "Speed": 0x26},
|
||||
6: {"Prsnt": 0x55, "State": 0x5d, "Speed": 0x22},
|
||||
7: {"Prsnt": 0x56, "State": 0x5a, "Speed": 0x27},
|
||||
8: {"Prsnt": 0x56, "State": 0x5e, "Speed": 0x23}
|
||||
}
|
||||
PSU_FAN_SENSOR_MAPPING = { 1: {"State": 0x31, "Speed": 0x28},
|
||||
2: {"State": 0x32, "Speed": 0x29} }
|
||||
|
||||
# { FANTRAY-ID: FRU-ID }
|
||||
FAN_FRU_MAPPING = { 1: 3, 2: 4, 3: 5, 4: 6 }
|
||||
PSU_FRU_MAPPING = { 1: 1, 2: 2 }
|
||||
|
||||
def __init__(self, fantray_index=1, fan_index=1, psu_fan=False,
|
||||
dependency=None):
|
||||
FanBase.__init__(self)
|
||||
self.is_psu_fan = psu_fan
|
||||
if not self.is_psu_fan:
|
||||
# API index is starting from 0, DellEMC platform index is
|
||||
# starting from 1
|
||||
self.fantrayindex = fantray_index + 1
|
||||
self.fanindex = fan_index + 1
|
||||
if (self.fanindex == 1):
|
||||
self.max_speed_offset = FAN1_MAX_SPEED_OFFSET
|
||||
else:
|
||||
self.max_speed_offset = FAN2_MAX_SPEED_OFFSET
|
||||
self.fan_direction_offset = FAN_DIRECTION_OFFSET
|
||||
self.index = (self.fantrayindex - 1) * 2 + self.fanindex
|
||||
self.prsnt_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Prsnt"],
|
||||
is_discrete=True)
|
||||
self.state_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["State"],
|
||||
is_discrete=True)
|
||||
self.speed_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Speed"])
|
||||
self.fru = IpmiFru(self.FAN_FRU_MAPPING[self.fantrayindex])
|
||||
else:
|
||||
self.dependency = dependency
|
||||
self.fanindex = fan_index
|
||||
self.state_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["State"],
|
||||
is_discrete=True)
|
||||
self.speed_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["Speed"])
|
||||
self.fru = IpmiFru(self.PSU_FRU_MAPPING[self.fanindex])
|
||||
self.max_speed_offset = PSU_FAN_MAX_SPEED_OFFSET
|
||||
self.fan_direction_offset = PSU_FAN_DIRECTION_OFFSET
|
||||
self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1]
|
||||
self.max_speed = self.max_speed[1] << 8 | self.max_speed[0]
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Returns:
|
||||
String: The name of the device
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
return "PSU{} Fan".format(self.fanindex)
|
||||
else:
|
||||
return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex)
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the part number of the FAN
|
||||
Returns:
|
||||
String: Part number of FAN
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
return None
|
||||
else:
|
||||
return self.fru.get_board_part_number()
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the FAN
|
||||
Returns:
|
||||
String: Serial number of FAN
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
return None
|
||||
else:
|
||||
return self.fru.get_board_serial()
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the FAN
|
||||
Returns:
|
||||
bool: True if fan is present, False if not
|
||||
"""
|
||||
presence = False
|
||||
if self.is_psu_fan:
|
||||
return self.dependency.get_presence()
|
||||
else:
|
||||
is_valid, state = self.prsnt_sensor.get_reading()
|
||||
if is_valid:
|
||||
if (state & 0b1):
|
||||
presence = True
|
||||
return presence
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the FAN
|
||||
Returns:
|
||||
bool: True if FAN is operating properly, False if not
|
||||
"""
|
||||
status = False
|
||||
is_valid, state = self.state_sensor.get_reading()
|
||||
if is_valid:
|
||||
if not state > 1:
|
||||
status = True
|
||||
return status
|
||||
|
||||
def get_direction(self):
|
||||
"""
|
||||
Retrieves the fan airfow direction
|
||||
Returns:
|
||||
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||
depending on fan direction
|
||||
|
||||
Notes:
|
||||
In DellEMC platforms,
|
||||
- Forward/Exhaust : Air flows from Port side to Fan side.
|
||||
- Reverse/Intake : Air flows from Fan side to Port side.
|
||||
"""
|
||||
direction = [self.FAN_DIRECTION_EXHAUST, self.FAN_DIRECTION_INTAKE]
|
||||
fan_status = self.get_presence()
|
||||
if not fan_status:
|
||||
return None
|
||||
is_valid, fan_direction = self.fru.get_fru_data(self.fan_direction_offset)
|
||||
if is_valid and fan_direction[0] < len(direction):
|
||||
return direction[fan_direction[0]]
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Retrieves the speed of the fan
|
||||
Returns:
|
||||
int: percentage of the max fan speed
|
||||
"""
|
||||
if self.max_speed == 0:
|
||||
self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1]
|
||||
self.max_speed = self.max_speed[1] << 8 | self.max_speed[0]
|
||||
is_valid, fan_speed = self.speed_sensor.get_reading()
|
||||
if not is_valid or self.max_speed == 0:
|
||||
return None
|
||||
else:
|
||||
speed = (100 * fan_speed)//self.max_speed
|
||||
return speed
|
||||
|
||||
def get_speed_rpm(self):
|
||||
"""
|
||||
Retrieves the speed of the fan
|
||||
Returns:
|
||||
int: percentage of the max fan speed
|
||||
"""
|
||||
fan_speed = 0
|
||||
is_valid, fan_speed = self.speed_sensor.get_reading()
|
||||
return fan_speed if is_valid else None
|
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# DellEMC S5224F
|
||||
#
|
||||
# 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 sonic_platform.fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
S5224F_FANS_PER_FANTRAY = 2
|
||||
|
||||
|
||||
class FanDrawer(FanDrawerBase):
|
||||
"""DellEMC Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fantray_index):
|
||||
|
||||
FanDrawerBase.__init__(self)
|
||||
# FanTray is 1-based in DellEMC platforms
|
||||
self.fantrayindex = fantray_index + 1
|
||||
for i in range(S5224F_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 @@
|
||||
../../common/sonic_platform/hwaccess.py
|
@ -0,0 +1,269 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
########################################################################
|
||||
# DellEMC
|
||||
#
|
||||
# Module contains implementation of IpmiSensor and IpmiFru classes that
|
||||
# provide Sensor's and FRU's information respectively.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
# IPMI Request Network Function Codes
|
||||
NetFn_SensorEvent = 0x04
|
||||
NetFn_Storage = 0x0A
|
||||
|
||||
# IPMI Sensor Device Commands
|
||||
Cmd_GetSensorReadingFactors = 0x23
|
||||
Cmd_GetSensorThreshold = 0x27
|
||||
Cmd_GetSensorReading = 0x2D
|
||||
|
||||
# IPMI FRU Device Commands
|
||||
Cmd_ReadFRUData = 0x11
|
||||
|
||||
def get_ipmitool_raw_output(args):
|
||||
"""
|
||||
Returns a list the elements of which are the individual bytes of
|
||||
ipmitool raw <cmd> command output.
|
||||
"""
|
||||
result_bytes = list()
|
||||
result = ""
|
||||
command = "ipmitool raw {}".format(args)
|
||||
try:
|
||||
proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE,
|
||||
universal_newlines=True, stderr=subprocess.STDOUT)
|
||||
stdout = proc.communicate()[0]
|
||||
proc.wait()
|
||||
if not proc.returncode:
|
||||
result = stdout.rstrip('\n')
|
||||
except EnvironmentError:
|
||||
pass
|
||||
|
||||
for i in result.split():
|
||||
result_bytes.append(int(i, 16))
|
||||
|
||||
return result_bytes
|
||||
|
||||
class IpmiSensor(object):
|
||||
|
||||
# Sensor Threshold types and their respective bit masks
|
||||
THRESHOLD_BIT_MASK = {
|
||||
"LowerNonCritical" : 0,
|
||||
"LowerCritical" : 1,
|
||||
"LowerNonRecoverable" : 2,
|
||||
"UpperNonCritical" : 3,
|
||||
"UpperCritical" : 4,
|
||||
"UpperNonRecoverable" : 5
|
||||
}
|
||||
|
||||
def __init__(self, sensor_id, is_discrete=False):
|
||||
self.id = sensor_id
|
||||
self.is_discrete = is_discrete
|
||||
|
||||
def _get_converted_sensor_reading(self, raw_value):
|
||||
"""
|
||||
Returns a 2 element tuple(bool, int) in which first element
|
||||
provides the validity of the reading and the second element is
|
||||
the converted sensor reading
|
||||
"""
|
||||
# Get Sensor Reading Factors
|
||||
cmd_args = "{} {} {} {}".format(NetFn_SensorEvent,
|
||||
Cmd_GetSensorReadingFactors,
|
||||
self.id, raw_value)
|
||||
factors = get_ipmitool_raw_output(cmd_args)
|
||||
|
||||
if len(factors) != 7:
|
||||
return False, 0
|
||||
|
||||
# Compute Twos complement
|
||||
def get_twos_complement(val, bits):
|
||||
if val & (1 << (bits - 1)):
|
||||
val = val - (1 << bits)
|
||||
return val
|
||||
|
||||
# Calculate actual sensor value from the raw sensor value
|
||||
# using the sensor reading factors.
|
||||
M = get_twos_complement(((factors[2] & 0xC0) << 8) | factors[1], 10)
|
||||
B = get_twos_complement(((factors[4] & 0xC0) << 8) | factors[3], 10)
|
||||
R_exp = get_twos_complement((factors[6] & 0xF0) >> 4, 4)
|
||||
B_exp = get_twos_complement(factors[6] & 0x0F, 4)
|
||||
|
||||
converted_reading = ((M * raw_value) + (B * 10**B_exp)) * 10**R_exp
|
||||
|
||||
return True, converted_reading
|
||||
|
||||
def get_reading(self):
|
||||
"""
|
||||
For Threshold sensors, returns the sensor reading.
|
||||
For Discrete sensors, returns the state value.
|
||||
|
||||
Returns:
|
||||
A tuple (bool, int) where the first element provides the
|
||||
validity of the reading and the second element provides the
|
||||
sensor reading/state value.
|
||||
"""
|
||||
# Get Sensor Reading
|
||||
cmd_args = "{} {} {}".format(NetFn_SensorEvent, Cmd_GetSensorReading,
|
||||
self.id)
|
||||
output = get_ipmitool_raw_output(cmd_args)
|
||||
if len(output) != 4:
|
||||
return False, 0
|
||||
|
||||
# Check reading/state unavailable
|
||||
if output[1] & 0x20:
|
||||
return False, 0
|
||||
|
||||
if self.is_discrete:
|
||||
state = ((output[3] & 0x7F) << 8) | output[2]
|
||||
return True, state
|
||||
else:
|
||||
return self._get_converted_sensor_reading(output[0])
|
||||
|
||||
def get_threshold(self, threshold_type):
|
||||
"""
|
||||
Returns the sensor's threshold value for a given threshold type.
|
||||
|
||||
Args:
|
||||
threshold_type (str) - one of the below mentioned
|
||||
threshold type strings
|
||||
|
||||
"LowerNonCritical"
|
||||
"LowerCritical"
|
||||
"LowerNonRecoverable"
|
||||
"UpperNonCritical"
|
||||
"UpperCritical"
|
||||
"UpperNonRecoverable"
|
||||
Returns:
|
||||
A tuple (bool, int) where the first element provides the
|
||||
validity of that threshold and second element provides the
|
||||
threshold value.
|
||||
"""
|
||||
# Thresholds are not valid for discrete sensors
|
||||
if self.is_discrete:
|
||||
raise TypeError("Threshold is not applicable for Discrete Sensor")
|
||||
|
||||
if threshold_type not in list(self.THRESHOLD_BIT_MASK.keys()):
|
||||
raise ValueError("Invalid threshold type {} provided. Valid types "
|
||||
"are {}".format(threshold_type,
|
||||
list(self.THRESHOLD_BIT_MASK.keys())))
|
||||
|
||||
bit_mask = self.THRESHOLD_BIT_MASK[threshold_type]
|
||||
|
||||
# Get Sensor Threshold
|
||||
cmd_args = "{} {} {}".format(NetFn_SensorEvent, Cmd_GetSensorThreshold,
|
||||
self.id)
|
||||
thresholds = get_ipmitool_raw_output(cmd_args)
|
||||
if len(thresholds) != 7:
|
||||
return False, 0
|
||||
|
||||
valid_thresholds = thresholds.pop(0)
|
||||
# Check whether particular threshold is readable
|
||||
if valid_thresholds & (1 << bit_mask):
|
||||
return self._get_converted_sensor_reading(thresholds[bit_mask])
|
||||
else:
|
||||
return False, 0
|
||||
|
||||
class IpmiFru(object):
|
||||
|
||||
def __init__(self, fru_id):
|
||||
self.id = fru_id
|
||||
|
||||
def _get_ipmitool_fru_print(self):
|
||||
result = ""
|
||||
command = "ipmitool fru print {}".format(self.id)
|
||||
try:
|
||||
proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE,
|
||||
universal_newlines=True, stderr=subprocess.STDOUT)
|
||||
stdout = proc.communicate()[0]
|
||||
proc.wait()
|
||||
if not proc.returncode:
|
||||
result = stdout.rstrip('\n')
|
||||
except EnvironmentError:
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
def _get_from_fru(self, info):
|
||||
"""
|
||||
Returns a string containing the info from FRU
|
||||
"""
|
||||
fru_output = self._get_ipmitool_fru_print()
|
||||
if not fru_output:
|
||||
return "NA"
|
||||
|
||||
info_req = re.search(r"%s\s*:(.*)" % info, fru_output)
|
||||
if not info_req:
|
||||
return "NA"
|
||||
|
||||
return info_req.group(1).strip()
|
||||
|
||||
def get_board_serial(self):
|
||||
"""
|
||||
Returns a string containing the Serial Number of the device.
|
||||
"""
|
||||
return self._get_from_fru('Board Serial')
|
||||
|
||||
def get_board_part_number(self):
|
||||
"""
|
||||
Returns a string containing the Part Number of the device.
|
||||
"""
|
||||
return self._get_from_fru('Board Part Number')
|
||||
|
||||
def get_board_mfr_id(self):
|
||||
"""
|
||||
Returns a string containing the manufacturer id of the FRU.
|
||||
"""
|
||||
return self._get_from_fru('Board Mfg')
|
||||
|
||||
def get_board_product(self):
|
||||
"""
|
||||
Returns a string containing the manufacturer id of the FRU.
|
||||
"""
|
||||
return self._get_from_fru('Board Product')
|
||||
|
||||
def get_fru_data(self, offset, count=1):
|
||||
"""
|
||||
Reads and returns the FRU data at the provided offset.
|
||||
|
||||
Args:
|
||||
offset (int) - FRU offset to read
|
||||
count (int) - Number of bytes to read [optional, default = 1]
|
||||
Returns:
|
||||
A tuple (bool, list(int)) where the first element provides
|
||||
the validity of the data read and the second element is a
|
||||
list, the elements of which are the individual bytes of the
|
||||
FRU data read.
|
||||
"""
|
||||
result_bytes = list()
|
||||
is_valid = True
|
||||
result = ""
|
||||
|
||||
offset_LSB = offset & 0xFF
|
||||
offset_MSB = offset & 0xFF00
|
||||
command = "ipmitool raw {} {} {} {} {} {}".format(NetFn_Storage,
|
||||
Cmd_ReadFRUData,
|
||||
self.id, offset_LSB,
|
||||
offset_MSB, count)
|
||||
try:
|
||||
proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE,
|
||||
universal_newlines=True, stderr=subprocess.STDOUT)
|
||||
stdout = proc.communicate()[0]
|
||||
proc.wait()
|
||||
if not proc.returncode:
|
||||
result = stdout.rstrip('\n')
|
||||
except EnvironmentError:
|
||||
is_valid = False
|
||||
|
||||
if (not result) or (not is_valid):
|
||||
return False, result_bytes
|
||||
|
||||
for i in result.split():
|
||||
result_bytes.append(int(i, 16))
|
||||
|
||||
read_count = result_bytes.pop(0)
|
||||
if read_count != count:
|
||||
return False, result_bytes
|
||||
else:
|
||||
return True, result_bytes
|
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# DellEMC S5224F
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the platform information
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
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):
|
||||
"""
|
||||
DELLEMC Platform-specific class
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
PlatformBase.__init__(self)
|
||||
self._chassis = Chassis()
|
@ -0,0 +1,230 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# DellEMC S5224F
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the PSUs' information which are available in the platform
|
||||
#
|
||||
########################################################################
|
||||
|
||||
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_platform.ipmihelper import IpmiSensor, IpmiFru
|
||||
from sonic_platform.fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Psu(PsuBase):
|
||||
"""DellEMC Platform-specific PSU class"""
|
||||
|
||||
# { PSU-ID: { Sensor-Name: Sensor-ID } }
|
||||
SENSOR_MAPPING = { 1: { "State": 0x31, "Current": 0x39,
|
||||
"Power": 0x37, "Voltage": 0x38,
|
||||
"InCurrent": 0x36, "InPower": 0x34,
|
||||
"InVoltage": 0x35 },
|
||||
2: { "State": 0x32, "Current": 0x3F,
|
||||
"Power": 0x3D, "Voltage": 0x3E,
|
||||
"InCurrent": 0x3C, "InPower": 0x3A,
|
||||
"InVoltage": 0x3B } }
|
||||
# ( PSU-ID: FRU-ID }
|
||||
FRU_MAPPING = { 1: 1, 2: 2 }
|
||||
|
||||
def __init__(self, psu_index):
|
||||
PsuBase.__init__(self)
|
||||
# PSU is 1-based in DellEMC platforms
|
||||
self.index = psu_index + 1
|
||||
self.state_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["State"],
|
||||
is_discrete=True)
|
||||
self.voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Voltage"])
|
||||
self.current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Current"])
|
||||
self.power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Power"])
|
||||
self.input_voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["InVoltage"])
|
||||
self.input_current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["InCurrent"])
|
||||
self.input_power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["InPower"])
|
||||
self.fru = IpmiFru(self.FRU_MAPPING[self.index])
|
||||
|
||||
self._fan_list.append(Fan(fan_index=self.index, psu_fan=True,
|
||||
dependency=self))
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
return "PSU{}".format(self.index)
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the Power Supply Unit (PSU)
|
||||
|
||||
Returns:
|
||||
bool: True if PSU is present, False if not
|
||||
"""
|
||||
presence = False
|
||||
is_valid, state = self.state_sensor.get_reading()
|
||||
if is_valid:
|
||||
if (state & 0b1):
|
||||
presence = True
|
||||
|
||||
return presence
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the part number of the PSU
|
||||
|
||||
Returns:
|
||||
string: Part number of PSU
|
||||
"""
|
||||
return self.fru.get_board_part_number()
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the PSU
|
||||
|
||||
Returns:
|
||||
string: Serial number of PSU
|
||||
"""
|
||||
return self.fru.get_board_serial()
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the PSU
|
||||
|
||||
Returns:
|
||||
bool: True if PSU is operating properly, False if not
|
||||
"""
|
||||
status = False
|
||||
is_valid, state = self.state_sensor.get_reading()
|
||||
if is_valid:
|
||||
if (state == 0x01):
|
||||
status = True
|
||||
|
||||
return status
|
||||
|
||||
def get_voltage(self):
|
||||
"""
|
||||
Retrieves current PSU voltage output
|
||||
|
||||
Returns:
|
||||
A float number, the output voltage in volts,
|
||||
e.g. 12.1
|
||||
"""
|
||||
is_valid, voltage = self.voltage_sensor.get_reading()
|
||||
if not is_valid:
|
||||
return None
|
||||
|
||||
return "{:.1f}".format(voltage)
|
||||
|
||||
def get_current(self):
|
||||
"""
|
||||
Retrieves present electric current supplied by PSU
|
||||
|
||||
Returns:
|
||||
A float number, electric current in amperes,
|
||||
e.g. 15.4
|
||||
"""
|
||||
is_valid, current = self.current_sensor.get_reading()
|
||||
if not is_valid:
|
||||
return None
|
||||
|
||||
return "{:.1f}".format(current)
|
||||
|
||||
def get_power(self):
|
||||
"""
|
||||
Retrieves current energy supplied by PSU
|
||||
|
||||
Returns:
|
||||
A float number, the power in watts,
|
||||
e.g. 302.6
|
||||
"""
|
||||
is_valid, power = self.power_sensor.get_reading()
|
||||
if not is_valid:
|
||||
return None
|
||||
|
||||
return "{:.1f}".format(power)
|
||||
|
||||
def get_input_voltage(self):
|
||||
"""
|
||||
Retrieves current PSU voltage input
|
||||
|
||||
Returns:
|
||||
A float number, the input voltage in volts,
|
||||
e.g. 12.1
|
||||
"""
|
||||
is_valid, input_voltage = self.input_voltage_sensor.get_reading()
|
||||
if not is_valid:
|
||||
return None
|
||||
|
||||
return "{:.1f}".format(input_voltage)
|
||||
|
||||
def get_input_current(self):
|
||||
"""
|
||||
Retrieves present electric current supplied to PSU
|
||||
|
||||
Returns:
|
||||
A float number, electric current in amperes,
|
||||
e.g. 15.4
|
||||
"""
|
||||
is_valid, input_current = self.input_current_sensor.get_reading()
|
||||
if not is_valid:
|
||||
return None
|
||||
|
||||
return "{:.1f}".format(input_current)
|
||||
|
||||
def get_input_power(self):
|
||||
"""
|
||||
Retrieves current energy supplied to PSU
|
||||
|
||||
Returns:
|
||||
A float number, the power in watts,
|
||||
e.g. 302.6
|
||||
"""
|
||||
is_valid, input_power = self.input_power_sensor.get_reading()
|
||||
if not is_valid:
|
||||
return None
|
||||
|
||||
return "{:.1f}".format(input_power)
|
||||
|
||||
def get_powergood_status(self):
|
||||
"""
|
||||
Retrieves the powergood status of PSU
|
||||
|
||||
Returns:
|
||||
A boolean, True if PSU has stablized its output voltages and
|
||||
passed all its internal self-tests, False if not.
|
||||
"""
|
||||
status = False
|
||||
is_valid, state = self.state_sensor.get_reading()
|
||||
if is_valid:
|
||||
if (state == 0x01):
|
||||
status = True
|
||||
|
||||
return status
|
||||
|
||||
def get_mfr_id(self):
|
||||
"""
|
||||
Retrives the Manufacturer Id of PSU
|
||||
|
||||
Returns:
|
||||
A string, the manunfacturer id.
|
||||
"""
|
||||
return self.fru.get_board_mfr_id()
|
||||
|
||||
def get_type(self):
|
||||
"""
|
||||
Retrives the Power Type of PSU
|
||||
|
||||
Returns :
|
||||
A string, PSU power type
|
||||
"""
|
||||
board_product = self.fru.get_board_product()
|
||||
if board_product is not None :
|
||||
info = board_product.split(',')
|
||||
if 'AC' in info : return 'AC'
|
||||
if 'DC' in info : return 'DC'
|
||||
return None
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
# DellEMC S5224F
|
||||
#
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the Thermals' information which are available in the platform
|
||||
#
|
||||
########################################################################
|
||||
|
||||
|
||||
try:
|
||||
from sonic_platform_base.thermal_base import ThermalBase
|
||||
from sonic_platform.ipmihelper import IpmiSensor
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Thermal(ThermalBase):
|
||||
"""DellEMC Platform-specific Thermal class"""
|
||||
|
||||
# [ Sensor-Name, Sensor-ID ]
|
||||
SENSOR_MAPPING = [
|
||||
['CPU On-board', 0xe],
|
||||
['ASIC On-board', 0x2],
|
||||
['System Front Left', 0x3],
|
||||
['System Front Middle', 0x1],
|
||||
['System Front Right', 0x4],
|
||||
['Inlet Airflow Sensor', 0x5],
|
||||
['PSU1 Airflow Sensor', 0x7],
|
||||
['PSU2 Airflow Sensor', 0x8]
|
||||
]
|
||||
|
||||
def __init__(self, thermal_index):
|
||||
ThermalBase.__init__(self)
|
||||
self.index = thermal_index + 1
|
||||
self.sensor = IpmiSensor(self.SENSOR_MAPPING[self.index - 1][1])
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the thermal
|
||||
|
||||
Returns:
|
||||
string: The name of the thermal
|
||||
"""
|
||||
return self.SENSOR_MAPPING[self.index - 1][0]
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the thermal
|
||||
|
||||
Returns:
|
||||
bool: True if thermal is present, False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the model number (or part number) of the Thermal
|
||||
|
||||
Returns:
|
||||
string: Model/part number of Thermal
|
||||
"""
|
||||
return 'NA'
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the Thermal
|
||||
|
||||
Returns:
|
||||
string: Serial number of Thermal
|
||||
"""
|
||||
return 'NA'
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the thermal
|
||||
|
||||
Returns:
|
||||
A boolean value, True if thermal is operating properly,
|
||||
False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
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
|
||||
"""
|
||||
is_valid, temperature = self.sensor.get_reading()
|
||||
if not is_valid:
|
||||
temperature = 0
|
||||
|
||||
return float(temperature)
|
||||
|
||||
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
|
||||
"""
|
||||
is_valid, high_threshold = self.sensor.get_threshold("UpperNonCritical")
|
||||
if not is_valid:
|
||||
return super(Thermal, self).get_high_threshold()
|
||||
|
||||
return float(high_threshold)
|
||||
|
||||
def get_high_critical_threshold(self):
|
||||
"""
|
||||
Retrieves the high critical threshold temperature of thermal
|
||||
|
||||
Returns:
|
||||
A float number, the high critical threshold temperature of thermal in
|
||||
Celsius up to nearest thousandth of one degree Celsius,
|
||||
e.g. 30.125
|
||||
"""
|
||||
is_valid, high_crit_threshold = self.sensor.get_threshold("UpperCritical")
|
||||
if not is_valid:
|
||||
return super(Thermal, self).get_high_critical_threshold()
|
||||
|
||||
return float(high_crit_threshold)
|
||||
|
||||
def get_low_threshold(self):
|
||||
"""
|
||||
Retrieves the low threshold temperature of thermal
|
||||
|
||||
Returns:
|
||||
A float number, the low threshold temperature of thermal in
|
||||
Celsius up to nearest thousandth of one degree Celsius,
|
||||
e.g. 30.125
|
||||
"""
|
||||
is_valid, low_threshold = self.sensor.get_threshold("LowerNonRecoverable")
|
||||
if not is_valid:
|
||||
low_threshold = 0
|
||||
|
||||
return float(low_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
|
||||
"""
|
||||
# Thermal threshold values are pre-defined based on HW.
|
||||
return False
|
||||
|
||||
def set_low_threshold(self, temperature):
|
||||
"""
|
||||
Sets the low 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
|
||||
"""
|
||||
# Thermal threshold values are pre-defined based on HW.
|
||||
return False
|
@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# DELLEMC S5248f
|
||||
#
|
||||
# Abstract base class for implementing a platform-specific class with
|
||||
# which to interact with a hardware watchdog module in SONiC
|
||||
#
|
||||
########################################################################
|
||||
|
||||
try:
|
||||
import ctypes
|
||||
import subprocess
|
||||
import syslog
|
||||
import sonic_platform.component as Component
|
||||
from sonic_platform_base.watchdog_base import WatchdogBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class _timespec(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('tv_sec', ctypes.c_long),
|
||||
('tv_nsec', ctypes.c_long)
|
||||
]
|
||||
|
||||
|
||||
class Watchdog(WatchdogBase):
|
||||
"""
|
||||
Abstract base class for interfacing with a hardware watchdog module
|
||||
"""
|
||||
|
||||
TIMERS = [15,20,30,40,50,60,65,70,80,100,120,140,160,180,210,240]
|
||||
|
||||
armed_time = 0
|
||||
timeout = 0
|
||||
CLOCK_MONOTONIC = 1
|
||||
|
||||
def __init__(self):
|
||||
self._librt = ctypes.CDLL('librt.so.1', use_errno=True)
|
||||
self._clock_gettime = self._librt.clock_gettime
|
||||
self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)]
|
||||
|
||||
def _get_command_result(self, cmdline):
|
||||
try:
|
||||
proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
stdout = proc.communicate()[0]
|
||||
proc.wait()
|
||||
result = stdout.rstrip('\n'.encode())
|
||||
except OSError:
|
||||
result = None
|
||||
|
||||
return result
|
||||
|
||||
def _get_reg_val(self):
|
||||
# 0x31 = CPLD I2C Base Address
|
||||
# 0x07 = Watchdog Function Register
|
||||
value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07")
|
||||
if not value:
|
||||
return None
|
||||
else:
|
||||
return int(value, 16)
|
||||
|
||||
def _set_reg_val(self,val):
|
||||
# 0x31 = CPLD I2C Base Address
|
||||
# 0x07 = Watchdog Function Register
|
||||
value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s"
|
||||
% (val))
|
||||
return value
|
||||
|
||||
def _get_time(self):
|
||||
"""
|
||||
To get clock monotonic time
|
||||
"""
|
||||
ts = _timespec()
|
||||
if self._clock_gettime(self.CLOCK_MONOTONIC, ctypes.pointer(ts)) != 0:
|
||||
self._errno = ctypes.get_errno()
|
||||
return 0
|
||||
return ts.tv_sec + ts.tv_nsec * 1e-9
|
||||
|
||||
def arm(self, seconds):
|
||||
"""
|
||||
Arm the hardware watchdog with a timeout of <seconds> seconds.
|
||||
If the watchdog is currently armed, calling this function will
|
||||
simply reset the timer to the provided value. If the underlying
|
||||
hardware does not support the value provided in <seconds>, this
|
||||
method should arm the watchdog with the *next greater*
|
||||
available value.
|
||||
|
||||
Returns:
|
||||
An integer specifying the *actual* number of seconds the
|
||||
watchdog was armed with. On failure returns -1.
|
||||
"""
|
||||
timer_offset = -1
|
||||
for key,timer_seconds in enumerate(self.TIMERS):
|
||||
if seconds <= timer_seconds:
|
||||
timer_offset = key
|
||||
seconds = timer_seconds
|
||||
break
|
||||
|
||||
if timer_offset == -1:
|
||||
return -1
|
||||
|
||||
cpld_version = Component.get_cpld0_version()
|
||||
wd_enabled_version = "0.8"
|
||||
|
||||
if cpld_version < wd_enabled_version:
|
||||
syslog.syslog(syslog.LOG_ERR,
|
||||
'Older System CPLD ver, Update to 0.8 to support watchdog ')
|
||||
return -1
|
||||
|
||||
# Extracting 5th to 8th bits for WD timer values
|
||||
reg_val = self._get_reg_val()
|
||||
wd_timer_offset = (reg_val >> 4) & 0xf
|
||||
|
||||
if wd_timer_offset != timer_offset:
|
||||
# Setting 5th to 7th bits
|
||||
# value from timer_offset
|
||||
self.disarm()
|
||||
self._set_reg_val((reg_val & 0x07) | (timer_offset << 4))
|
||||
|
||||
if self.is_armed():
|
||||
# Setting last bit to WD Timer punch
|
||||
# Last bit = WD Timer punch
|
||||
self._set_reg_val(reg_val & 0xFE)
|
||||
|
||||
self.armed_time = self._get_time()
|
||||
self.timeout = seconds
|
||||
return seconds
|
||||
else:
|
||||
# Setting 4th bit to enable WD
|
||||
# 4th bit = Enable WD
|
||||
reg_val = self._get_reg_val()
|
||||
self._set_reg_val(reg_val | 0x8)
|
||||
|
||||
self.armed_time = self._get_time()
|
||||
self.timeout = seconds
|
||||
return seconds
|
||||
|
||||
def disarm(self):
|
||||
"""
|
||||
Disarm the hardware watchdog
|
||||
|
||||
Returns:
|
||||
A boolean, True if watchdog is disarmed successfully, False
|
||||
if not
|
||||
"""
|
||||
if self.is_armed():
|
||||
# Setting 4th bit to disable WD
|
||||
# 4th bit = Disable WD
|
||||
reg_val = self._get_reg_val()
|
||||
self._set_reg_val(reg_val & 0xF7)
|
||||
|
||||
self.armed_time = 0
|
||||
self.timeout = 0
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def is_armed(self):
|
||||
"""
|
||||
Retrieves the armed state of the hardware watchdog.
|
||||
|
||||
Returns:
|
||||
A boolean, True if watchdog is armed, False if not
|
||||
"""
|
||||
|
||||
# Extracting 4th bit to get WD Enable/Disable status
|
||||
# 0 - Disabled WD
|
||||
# 1 - Enabled WD
|
||||
reg_val = self._get_reg_val()
|
||||
wd_offset = (reg_val >> 3) & 1
|
||||
|
||||
return bool(wd_offset)
|
||||
|
||||
def get_remaining_time(self):
|
||||
"""
|
||||
If the watchdog is armed, retrieve the number of seconds
|
||||
remaining on the watchdog timer
|
||||
|
||||
Returns:
|
||||
An integer specifying the number of seconds remaining on
|
||||
their watchdog timer. If the watchdog is not armed, returns
|
||||
-1.
|
||||
|
||||
S5224f doesnot have hardware support to show remaining time.
|
||||
Due to this limitation, this API is implemented in software.
|
||||
This API would return correct software time difference if it
|
||||
is called from the process which armed the watchdog timer.
|
||||
If this API called from any other process, it would return
|
||||
0. If the watchdog is not armed, this API would return -1.
|
||||
"""
|
||||
if not self.is_armed():
|
||||
return -1
|
||||
|
||||
if self.armed_time > 0 and self.timeout != 0:
|
||||
cur_time = self._get_time()
|
||||
|
||||
if cur_time <= 0:
|
||||
return 0
|
||||
|
||||
diff_time = int(cur_time - self.armed_time)
|
||||
|
||||
if diff_time > self.timeout:
|
||||
return self.timeout
|
||||
else:
|
||||
return self.timeout - diff_time
|
||||
|
||||
return 0
|
||||
|
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Dell S5224f Platform modules
|
||||
Before=pmon.service
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/s5224f_platform.sh init
|
||||
ExecStop=/usr/local/bin/s5224f_platform.sh deinit
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
Reference in New Issue
Block a user