diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers.json.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers.json.j2
new file mode 100644
index 000000000000..0b1cb2c541b6
--- /dev/null
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers.json.j2
@@ -0,0 +1,2 @@
+{%- set default_topo = 't1' %}
+{%- include 'buffers_config.j2' %}
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t0.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..3e39d411e8bf
--- /dev/null
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t0.j2
@@ -0,0 +1,47 @@
+
+{%- set default_cable = '5m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {%- for port_idx in range(0,128,4) %}
+ {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "11213696",
+ "type": "ingress",
+ "mode": "dynamic",
+ "xoff": "3855488"
+ },
+ "egress_lossy_pool": {
+ "size": "9532224",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "15982720",
+ "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":"1518",
+ "static_th":"3995680"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t1.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..d9f562f95624
--- /dev/null
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t1.j2
@@ -0,0 +1,47 @@
+
+{%- set default_cable = '40m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {%- for port_idx in range(0,128,4) %}
+ {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "10443264",
+ "type": "ingress",
+ "mode": "dynamic",
+ "xoff": "4625920"
+ },
+ "egress_lossy_pool": {
+ "size": "8877440",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "15982720",
+ "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":"1518",
+ "static_th":"3995680"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/pg_profile_lookup.ini b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/pg_profile_lookup.ini
new file mode 100644
index 000000000000..3b2a417cebcd
--- /dev/null
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold xon_offset
+ 10000 5m 1248 2288 35776 -4 2288
+ 25000 5m 1248 2288 53248 -4 2288
+ 40000 5m 1248 2288 66560 -4 2288
+ 50000 5m 1248 2288 90272 -4 2288
+ 100000 5m 1248 2288 165568 -4 2288
+ 10000 40m 1248 2288 37024 -4 2288
+ 25000 40m 1248 2288 53248 -4 2288
+ 40000 40m 1248 2288 71552 -4 2288
+ 50000 40m 1248 2288 96096 -4 2288
+ 100000 40m 1248 2288 177632 -4 2288
+ 10000 300m 1248 2288 46176 -4 2288
+ 25000 300m 1248 2288 79040 -4 2288
+ 40000 300m 1248 2288 108160 -4 2288
+ 50000 300m 1248 2288 141856 -4 2288
+ 100000 300m 1248 2288 268736 -4 2288
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/qos.json.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/qos.json.j2
new file mode 100644
index 000000000000..b724b48c2c23
--- /dev/null
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/qos.json.j2
@@ -0,0 +1,167 @@
+{
+ "TC_TO_PRIORITY_GROUP_MAP": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "2": "2",
+ "3": "3",
+ "4": "4",
+ "5": "5",
+ "6": "6",
+ "7": "7"
+ }
+ },
+ "MAP_PFC_PRIORITY_TO_QUEUE": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "2": "2",
+ "3": "3",
+ "4": "4",
+ "5": "5",
+ "6": "6",
+ "7": "7"
+ }
+ },
+ "TC_TO_QUEUE_MAP": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "2": "2",
+ "3": "3",
+ "4": "4",
+ "5": "5",
+ "6": "6",
+ "7": "7"
+ }
+ },
+ "DSCP_TO_TC_MAP": {
+ "AZURE": {
+ "0":"0",
+ "1":"0",
+ "2":"0",
+ "3":"3",
+ "4":"4",
+ "5":"0",
+ "6":"0",
+ "7":"0",
+ "8":"1",
+ "9":"0",
+ "10":"0",
+ "11":"0",
+ "12":"0",
+ "13":"0",
+ "14":"0",
+ "15":"0",
+ "16":"0",
+ "17":"0",
+ "18":"0",
+ "19":"0",
+ "20":"0",
+ "21":"0",
+ "22":"0",
+ "23":"0",
+ "24":"0",
+ "25":"0",
+ "26":"0",
+ "27":"0",
+ "28":"0",
+ "29":"0",
+ "30":"0",
+ "31":"0",
+ "32":"0",
+ "33":"0",
+ "34":"0",
+ "35":"0",
+ "36":"0",
+ "37":"0",
+ "38":"0",
+ "39":"0",
+ "40":"0",
+ "41":"0",
+ "42":"0",
+ "43":"0",
+ "44":"0",
+ "45":"0",
+ "46":"0",
+ "47":"0",
+ "48":"0",
+ "49":"0",
+ "50":"0",
+ "51":"0",
+ "52":"0",
+ "53":"0",
+ "54":"0",
+ "55":"0",
+ "56":"0",
+ "57":"0",
+ "58":"0",
+ "59":"0",
+ "60":"0",
+ "61":"0",
+ "62":"0",
+ "63":"0"
+ }
+ },
+ "SCHEDULER": {
+ "scheduler.0" : {
+ "type":"DWRR",
+ "weight": "25"
+ },
+ "scheduler.1" : {
+ "type":"DWRR",
+ "weight": "30"
+ },
+ "scheduler.2" : {
+ "type":"DWRR",
+ "weight": "20"
+ }
+ },
+ "PORT_QOS_MAP": {
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": {
+ "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]",
+ "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]",
+ "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]",
+ "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]",
+ "pfc_enable": "3,4"
+ }
+ },
+ "WRED_PROFILE": {
+ "AZURE_LOSSY" : {
+ "wred_green_enable":"true",
+ "wred_yellow_enable":"true",
+ "ecn":"ecn_all",
+ "red_max_threshold":"512000",
+ "red_min_threshold":"512000",
+ "yellow_max_threshold":"512000",
+ "yellow_min_threshold":"512000",
+ "green_max_threshold": "184320",
+ "green_min_threshold": "184320"
+ },
+ "AZURE_LOSSLESS" : {
+ "wred_green_enable":"true",
+ "wred_yellow_enable":"true",
+ "ecn":"ecn_all",
+ "red_max_threshold":"512000",
+ "red_min_threshold":"512000",
+ "yellow_max_threshold":"512000",
+ "yellow_min_threshold":"512000",
+ "green_max_threshold": "184320",
+ "green_min_threshold": "184320"
+ }
+ },
+ "QUEUE": {
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1" : {
+ "wred_profile" : "[WRED_PROFILE|AZURE_LOSSY]"
+ },
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4" : {
+ "scheduler" : "[SCHEDULER|scheduler.0]"
+ },
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0" : {
+ "scheduler" : "[SCHEDULER|scheduler.1]"
+ },
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1" : {
+ "scheduler" : "[SCHEDULER|scheduler.2]"
+ }
+ }
+}
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf
index 8d4683add468..cda2e2810cbf 100644
--- a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf
@@ -1,4 +1,4 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200
-ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax pcie_aspm=off irqpoll"
+ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax pcie_aspm=off irqpoll modprobe.blacklist=i2c_ismt"
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/minigraph.xml b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/minigraph.xml
index 210eac2fd620..215ac176c5dd 100644
--- a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/minigraph.xml
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/minigraph.xml
@@ -1,1074 +1,233 @@
-
-
-
-
-
- ARISTA01T0
- 10.0.0.33
- sonic
- 10.0.0.32
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.0
- ARISTA01T2
- 10.0.0.1
- 1
- 180
- 60
-
-
- ARISTA02T0
- 10.0.0.35
- sonic
- 10.0.0.34
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.2
- ARISTA02T2
- 10.0.0.3
- 1
- 180
- 60
-
-
- ARISTA03T0
- 10.0.0.37
- sonic
- 10.0.0.36
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.4
- ARISTA03T2
- 10.0.0.5
- 1
- 180
- 60
-
-
- ARISTA04T0
- 10.0.0.39
- sonic
- 10.0.0.38
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.6
- ARISTA04T2
- 10.0.0.7
- 1
- 180
- 60
-
-
- ARISTA05T0
- 10.0.0.41
- sonic
- 10.0.0.40
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.8
- ARISTA05T2
- 10.0.0.9
- 1
- 180
- 60
-
-
- ARISTA06T0
- 10.0.0.43
- sonic
- 10.0.0.42
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.10
- ARISTA06T2
- 10.0.0.11
- 1
- 180
- 60
-
-
- ARISTA07T0
- 10.0.0.45
- sonic
- 10.0.0.44
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.12
- ARISTA07T2
- 10.0.0.13
- 1
- 180
- 60
-
-
- ARISTA08T0
- 10.0.0.47
- sonic
- 10.0.0.46
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.14
- ARISTA08T2
- 10.0.0.15
- 1
- 180
- 60
-
-
- ARISTA09T0
- 10.0.0.49
- sonic
- 10.0.0.48
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.16
- ARISTA09T2
- 10.0.0.17
- 1
- 180
- 60
-
-
- ARISTA10T0
- 10.0.0.51
- sonic
- 10.0.0.50
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.18
- ARISTA10T2
- 10.0.0.19
- 1
- 180
- 60
-
-
- ARISTA11T0
- 10.0.0.53
- sonic
- 10.0.0.52
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.20
- ARISTA11T2
- 10.0.0.21
- 1
- 180
- 60
-
-
- ARISTA12T0
- 10.0.0.55
- sonic
- 10.0.0.54
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.22
- ARISTA12T2
- 10.0.0.23
- 1
- 180
- 60
-
-
- ARISTA13T0
- 10.0.0.57
- sonic
- 10.0.0.56
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.24
- ARISTA13T2
- 10.0.0.25
- 1
- 180
- 60
-
-
- ARISTA14T0
- 10.0.0.59
- sonic
- 10.0.0.58
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.26
- ARISTA14T2
- 10.0.0.27
- 1
- 180
- 60
-
-
- ARISTA15T0
- 10.0.0.61
- sonic
- 10.0.0.60
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.28
- ARISTA15T2
- 10.0.0.29
- 1
- 180
- 60
-
-
- ARISTA16T0
- 10.0.0.63
- sonic
- 10.0.0.62
- 1
- 180
- 60
-
-
- sonic
- 10.0.0.30
- ARISTA16T2
- 10.0.0.31
- 1
- 180
- 60
-
-
-
-
- 65100
- sonic
-
-
- 10.0.0.33
-
-
-
-
- 10.0.0.1
-
-
-
-
- 10.0.0.35
-
-
-
-
- 10.0.0.3
-
-
-
-
- 10.0.0.37
-
-
-
-
- 10.0.0.5
-
-
-
-
- 10.0.0.39
-
-
-
-
- 10.0.0.7
-
-
-
-
- 10.0.0.41
-
-
-
-
- 10.0.0.9
-
-
-
-
- 10.0.0.43
-
-
-
-
- 10.0.0.11
-
-
-
-
- 10.0.0.45
-
-
-
-
- 10.0.0.13
-
-
-
-
- 10.0.0.47
-
-
-
-
- 10.0.0.15
-
-
-
-
- 10.0.0.49
-
-
-
-
- 10.0.0.17
-
-
-
-
- 10.0.0.51
-
-
-
-
- 10.0.0.19
-
-
-
-
- 10.0.0.53
-
-
-
-
- 10.0.0.21
-
-
-
-
- 10.0.0.55
-
-
-
-
- 10.0.0.23
-
-
-
-
- 10.0.0.57
-
-
-
-
- 10.0.0.25
-
-
-
-
- 10.0.0.59
-
-
-
-
- 10.0.0.27
-
-
-
-
- 10.0.0.61
-
-
-
-
- 10.0.0.29
-
-
-
-
- 10.0.0.63
-
-
-
-
- 10.0.0.31
-
-
-
-
-
-
-
- 64001
- ARISTA01T0
-
-
-
- 65200
- ARISTA01T2
-
-
-
- 64002
- ARISTA02T0
-
-
-
- 65200
- ARISTA02T2
-
-
-
- 64003
- ARISTA03T0
-
-
-
- 65200
- ARISTA03T2
-
-
-
- 64004
- ARISTA04T0
-
-
-
- 65200
- ARISTA04T2
-
-
-
- 64005
- ARISTA05T0
-
-
-
- 65200
- ARISTA05T2
-
-
-
- 64006
- ARISTA06T0
-
-
-
- 65200
- ARISTA06T2
-
-
-
- 64007
- ARISTA07T0
-
-
-
- 65200
- ARISTA07T2
-
-
-
- 64008
- ARISTA08T0
-
-
-
- 65200
- ARISTA08T2
-
-
-
- 64009
- ARISTA09T0
-
-
-
- 65200
- ARISTA09T2
-
-
-
- 64010
- ARISTA10T0
-
-
-
- 65200
- ARISTA10T2
-
-
-
- 64011
- ARISTA11T0
-
-
-
- 65200
- ARISTA11T2
-
-
-
- 64012
- ARISTA12T0
-
-
-
- 65200
- ARISTA12T2
-
-
-
- 64013
- ARISTA13T0
-
-
-
- 65200
- ARISTA13T2
-
-
-
- 64014
- ARISTA14T0
-
-
-
- 65200
- ARISTA14T2
-
-
-
- 64015
- ARISTA15T0
-
-
-
- 65200
- ARISTA15T2
-
-
-
- 64016
- ARISTA16T0
-
-
-
- 65200
- ARISTA16T2
-
-
-
-
-
-
-
-
-
- HostIP
- Loopback0
-
- 10.1.0.32/32
-
- 10.1.0.32/32
-
-
-
-
-
-
-
- sonic
-
-
-
-
-
- Ethernet0
- 10.0.0.0/31
-
-
-
- Ethernet4
- 10.0.0.2/31
-
-
-
- Ethernet8
- 10.0.0.4/31
-
-
-
- Ethernet12
- 10.0.0.6/31
-
-
-
- Ethernet16
- 10.0.0.8/31
-
-
-
- Ethernet20
- 10.0.0.10/31
-
-
-
- Ethernet24
- 10.0.0.12/31
-
-
-
- Ethernet28
- 10.0.0.14/31
-
-
-
- Ethernet32
- 10.0.0.16/31
-
-
-
- Ethernet36
- 10.0.0.18/31
-
-
-
- Ethernet40
- 10.0.0.20/31
-
-
-
- Ethernet44
- 10.0.0.22/31
-
-
-
- Ethernet48
- 10.0.0.24/31
-
-
-
- Ethernet52
- 10.0.0.26/31
-
-
-
- Ethernet56
- 10.0.0.28/31
-
-
-
- Ethernet60
- 10.0.0.30/31
-
-
-
- Ethernet64
- 10.0.0.32/31
-
-
-
- Ethernet68
- 10.0.0.34/31
-
-
-
- Ethernet72
- 10.0.0.36/31
-
-
-
- Ethernet76
- 10.0.0.38/31
-
-
-
- Ethernet80
- 10.0.0.40/31
-
-
-
- Ethernet84
- 10.0.0.42/31
-
-
-
- Ethernet88
- 10.0.0.44/31
-
-
-
- Ethernet92
- 10.0.0.46/31
-
-
-
- Ethernet96
- 10.0.0.48/31
-
-
-
- Ethernet100
- 10.0.0.50/31
-
-
-
- Ethernet104
- 10.0.0.52/31
-
-
-
- Ethernet108
- 10.0.0.54/31
-
-
-
- Ethernet112
- 10.0.0.56/31
-
-
-
- Ethernet116
- 10.0.0.58/31
-
-
-
- Ethernet120
- 10.0.0.60/31
-
-
-
- Ethernet124
- 10.0.0.62/31
-
-
-
-
-
-
-
-
-
-
-
- DeviceInterfaceLink
- sonic
- Ethernet0
- ARISTA01T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet4
- ARISTA02T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet8
- ARISTA03T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet12
- ARISTA04T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet16
- ARISTA05T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet20
- ARISTA06T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet24
- ARISTA07T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet28
- ARISTA08T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet32
- ARISTA09T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet36
- ARISTA10T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet40
- ARISTA11T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet44
- ARISTA12T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet48
- ARISTA13T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet52
- ARISTA14T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet56
- ARISTA15T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet60
- ARISTA16T2
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet64
- ARISTA01T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet68
- ARISTA02T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet72
- ARISTA03T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet76
- ARISTA04T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet80
- ARISTA05T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet84
- ARISTA06T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet88
- ARISTA07T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet92
- ARISTA08T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet96
- ARISTA09T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet100
- ARISTA10T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet104
- ARISTA11T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet108
- ARISTA12T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet112
- ARISTA13T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet116
- ARISTA14T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet120
- ARISTA15T0
- Ethernet1
-
-
- DeviceInterfaceLink
- sonic
- Ethernet124
- ARISTA16T0
- Ethernet1
-
-
-
-
- sonic
- MiTAC-LY1200-B32H0-C3
-
-
-
-
-
-
- sonic
-
-
- DhcpResources
-
-
-
-
- NtpResources
-
- 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
-
-
- SyslogResources
-
-
-
-
-
-
-
-
- sonic
- MiTAC-LY1200-B32H0-C3
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 10.1.0.32/32
+
+ 10.1.0.32/32
+
+
+
+
+
+
+
+ sonic
+
+
+
+
+
+ Ethernet0
+ 10.0.0.0/31
+
+
+
+ Ethernet4
+ 10.0.0.2/31
+
+
+
+ Ethernet8
+ 10.0.0.4/31
+
+
+
+ Ethernet12
+ 10.0.0.6/31
+
+
+
+ Ethernet16
+ 10.0.0.8/31
+
+
+
+ Ethernet20
+ 10.0.0.10/31
+
+
+
+ Ethernet24
+ 10.0.0.12/31
+
+
+
+ Ethernet28
+ 10.0.0.14/31
+
+
+
+ Ethernet32
+ 10.0.0.16/31
+
+
+
+ Ethernet36
+ 10.0.0.18/31
+
+
+
+ Ethernet40
+ 10.0.0.20/31
+
+
+
+ Ethernet44
+ 10.0.0.22/31
+
+
+
+ Ethernet48
+ 10.0.0.24/31
+
+
+
+ Ethernet52
+ 10.0.0.26/31
+
+
+
+ Ethernet56
+ 10.0.0.28/31
+
+
+
+ Ethernet60
+ 10.0.0.30/31
+
+
+
+ Ethernet64
+ 10.0.0.32/31
+
+
+
+ Ethernet68
+ 10.0.0.34/31
+
+
+
+ Ethernet72
+ 10.0.0.36/31
+
+
+
+ Ethernet76
+ 10.0.0.38/31
+
+
+
+ Ethernet80
+ 10.0.0.40/31
+
+
+
+ Ethernet84
+ 10.0.0.42/31
+
+
+
+ Ethernet88
+ 10.0.0.44/31
+
+
+
+ Ethernet92
+ 10.0.0.46/31
+
+
+
+ Ethernet96
+ 10.0.0.48/31
+
+
+
+ Ethernet100
+ 10.0.0.50/31
+
+
+
+ Ethernet104
+ 10.0.0.52/31
+
+
+
+ Ethernet108
+ 10.0.0.54/31
+
+
+
+ Ethernet112
+ 10.0.0.56/31
+
+
+
+ Ethernet116
+ 10.0.0.58/31
+
+
+
+ Ethernet120
+ 10.0.0.60/31
+
+
+
+ Ethernet124
+ 10.0.0.62/31
+
+
+
+
+
+
+
+
+
+
+
+ sonic
+ MiTAC-LY1200-B32H0-C3
+
+
+
+
+
+
+ sonic
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+
+
+
+
+ sonic
+ MiTAC-LY1200-B32H0-C3
+
\ No newline at end of file
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/psuutil.py b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/psuutil.py
new file mode 100644
index 000000000000..8fd9d3b1f349
--- /dev/null
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/psuutil.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+#############################################################################
+# MiTAC
+#
+# Module contains an implementation of SONiC PSU Base API and
+# provides the PSUs status which are available in the platform
+#
+#############################################################################
+
+import os.path
+
+try:
+ from sonic_psu.psu_base import PsuBase
+except ImportError as e:
+ raise ImportError (str(e) + "- required module not found")
+
+class PsuUtil(PsuBase):
+ """Platform-specific PSUutil class"""
+
+ def __init__(self):
+ PsuBase.__init__(self)
+
+ self.psu_nums = 2
+ self.psu_path = "/sys/bus/i2c/devices/1-0032/"
+ self.psu_presence = "ps{}_ps"
+ self.psu_oper_status = "ps{}_pg"
+
+ def get_num_psus(self):
+ """
+ Retrieves the number of PSUs available on the device
+ :return: An integer, the number of PSUs available on the device
+ """
+ return self.psu_nums
+
+ def get_psu_status(self, index):
+ """
+ Retrieves the oprational status of power supply unit (PSU) defined
+ by 1-based index
+ :param index: An integer, 1-based index of the PSU of which to query status
+ :return: Boolean, True if PSU is operating properly, False if PSU is faulty
+ """
+ if index is None:
+ return False
+
+ status = 1
+ try:
+ with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status:
+ status = int(power_status.read(), 0)
+ except IOError:
+ return False
+
+ return status == 0
+
+ def get_psu_presence(self, index):
+ """
+ Retrieves the presence status of power supply unit (PSU) defined
+ by 1-based index
+ :param index: An integer, 1-based index of the PSU of which to query status
+ :return: Boolean, True if PSU is plugged, False if not
+ """
+ if index is None:
+ return False
+
+ status = 1
+ try:
+ with open(self.psu_path + self.psu_presence.format(index), 'r') as presence_status:
+ status = int(presence_status.read(), 0)
+ except IOError:
+ return False
+
+ return status == 0
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py
index 17d4d2f95b5f..1becec498508 100644
--- a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py
+++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py
@@ -180,3 +180,6 @@ def reset(self, port_num):
reg_file.close()
return True
+
+ def get_transceiver_change_event(self, timeout=0):
+ raise NotImplementedError
\ No newline at end of file
diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk
index c7fa0f7aa80e..5bef3b467e26 100755
--- a/platform/broadcom/rules.mk
+++ b/platform/broadcom/rules.mk
@@ -9,7 +9,7 @@ include $(PLATFORM_PATH)/platform-modules-inventec.mk
include $(PLATFORM_PATH)/platform-modules-cel.mk
include $(PLATFORM_PATH)/platform-modules-delta.mk
include $(PLATFORM_PATH)/platform-modules-quanta.mk
-#include $(PLATFORM_PATH)/platform-modules-mitac.mk
+include $(PLATFORM_PATH)/platform-modules-mitac.mk
include $(PLATFORM_PATH)/docker-orchagent-brcm.mk
include $(PLATFORM_PATH)/docker-syncd-brcm.mk
include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk
diff --git a/platform/broadcom/sonic-platform-modules-mitac/.gitignore b/platform/broadcom/sonic-platform-modules-mitac/.gitignore
index 38e72f05332d..ae5cd673e9ad 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/.gitignore
+++ b/platform/broadcom/sonic-platform-modules-mitac/.gitignore
@@ -7,6 +7,10 @@ ly1200-32x/modules/*.cmd
ly1200-32x/modules/Module.symvers
ly1200-32x/modules/modules.order
ly1200-32x/modules/.tmp_versions
+ly1200-32x/opt/xcvr-serv/*.o
+ly1200-32x/opt/sys-serv/*.o
+ly1200-32x/opt/xcvr-serv/xcvr-servd
+ly1200-32x/opt/sys-serv/sys-servd
debian/sonic-platform-mitac-ly1200-32x/
debian/sonic-platform-mitac-ly1200-32x.debhelper.log
@@ -15,3 +19,5 @@ debian/sonic-platform-mitac-ly1200-32x.postrm.debhelper
debian/sonic-platform-mitac-ly1200-32x.prerm.debhelper
debian/sonic-platform-mitac-ly1200-32x.substvars
debian/files
+debian/.debhelper
+debian/debhelper-build-stamp
diff --git a/platform/broadcom/sonic-platform-modules-mitac/README.md b/platform/broadcom/sonic-platform-modules-mitac/README.md
index d7d47a58debf..ff88d76910f1 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/README.md
+++ b/platform/broadcom/sonic-platform-modules-mitac/README.md
@@ -1 +1,2 @@
-platform drivers of MiTAC products for the SONiC project
+# sonic-platform-modules-mitac_stretch
+platform drivers of MiTAC products for the SONiC project of Debian 9
diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/control b/platform/broadcom/sonic-platform-modules-mitac/debian/control
index 8e20f8524d74..86dc337af8d9 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/debian/control
+++ b/platform/broadcom/sonic-platform-modules-mitac/debian/control
@@ -7,6 +7,5 @@ Standards-Version: 3.9.3
Package: sonic-platform-mitac-ly1200-32x
Architecture: amd64
-Depends: linux-image-3.16.0-5-amd64
-Description: kernel modules for platform devices such as fan, led, sfp
-
+Depends: linux-image-4.9.0-7-amd64, bc
+Description: kernel modules for platform devices such as fan, led, sfp
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/rules b/platform/broadcom/sonic-platform-modules-mitac/debian/rules
index 7f9f99827d21..1ccafeb62127 100755
--- a/platform/broadcom/sonic-platform-modules-mitac/debian/rules
+++ b/platform/broadcom/sonic-platform-modules-mitac/debian/rules
@@ -1,4 +1,6 @@
#!/usr/bin/make -f
+# Uncomment this to turn on verbose mode.
+export DH_VERBOSE=1
export INSTALL_MOD_DIR:=extra
@@ -7,16 +9,27 @@ KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
MODULE_DIRS:= ly1200-32x
+SERVICE_DIR := service
%:
- dh $@
+ dh $@ --with systemd
override_dh_auto_build:
(for mod in $(MODULE_DIRS); do \
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
+ make -C $(MOD_SRC_DIR)/$${mod}/opt/xcvr-serv; \
+ make -C $(MOD_SRC_DIR)/$${mod}/opt/sys-serv; \
done)
-override_dh_auto_install:
+binary: binary-arch binary-indep
+ # Nothing to do
+
+binary-arch:
+ # Nothing to do
+
+binary-indep:
+ dh_testdir
+ dh_installdirs
(for mod in $(MODULE_DIRS); do \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}\
$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
@@ -29,13 +42,24 @@ override_dh_auto_install:
mkdir -p debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/init.d; \
cp -rfL $(MOD_SRC_DIR)/$${mod}/etc/* \
debian/$(PACKAGE_PRE_NAME)-$${mod}/etc; \
+ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \
+ cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \
+ (cd debian/$(PACKAGE_PRE_NAME)-$${mod}/opt/xcvr-serv; rm -f *.[cho]; rm -f Makefile); \
+ (cd debian/$(PACKAGE_PRE_NAME)-$${mod}/opt/sys-serv; rm -f *.[cho]; rm -f Makefile); \
done)
-
-override_dh_usrlocal:
-
-override_dh_clean:
- dh_clean
- (for mod in $(MODULE_DIRS); do \
- make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \
- done)
-
+ # Resuming debhelper scripts
+ dh_testroot
+ dh_install
+ dh_installchangelogs
+ dh_installdocs
+ dh_systemd_enable
+ dh_installinit
+ dh_systemd_start
+ dh_link
+ dh_fixperms
+ dh_compress
+ dh_strip
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init
index d2f7dbf610ab..ed988b683542 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init
+++ b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init
@@ -6,8 +6,8 @@
# Required-Stop:
# Should-Start:
# Should-Stop:
-# Default-Start: S
-# Default-Stop: 0 6
+# Default-Start:
+# Default-Stop:
# Short-Description: Setup ly1200-32x board.
### END INIT INFO
@@ -16,26 +16,24 @@ start)
echo -n "Setting up board... "
echo 0 > /proc/sys/kernel/perf_cpu_time_max_percent
-
- /etc/init.d/gpe start
/etc/init.d/i2c_init start
/etc/init.d/sys_polld start
- /opt/script/start_watchdog.sh &
- /opt/script/start_service.sh &
+ /etc/init.d/xcvr_servd start
+ /etc/init.d/sys_servd start
+ echo 0 > /sys/bus/i2c/devices/1-0031/wd_en
+
echo "done."
;;
stop)
echo -n "cleaning... "
- /etc/init.d/gpe stop
/etc/init.d/i2c_init stop
/etc/init.d/xcvr_servd stop
/etc/init.d/sys_servd stop
/etc/init.d/sys_polld stop
echo "done."
-
;;
force-reload|restart)
@@ -43,7 +41,7 @@ force-reload|restart)
;;
*)
- echo "Usage: /etc/init.d/sonic-platform-mitac-ly1200-32x.init {start|stop}"
+ echo "Usage: /etc/init.d/sonic-platform-mitac-ly1200-32x {start|stop}"
exit 1
;;
esac
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld
index 936f01e8b640..a7ae13ecee8b 100755
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld
@@ -3,7 +3,7 @@
# Provides: fan-ctrld
# Required-Start:
# Required-Stop:
-# Default-Start: rc.local
+# Default-Start:
# Default-Stop:
# Short-Description: Daemon fan-ctrld
### END INIT INFO
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe
deleted file mode 100755
index c326442db047..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe
+++ /dev/null
@@ -1,39 +0,0 @@
-#! /bin/bash
-### BEGIN INIT INFO
-# Provides: gpe
-# Required-Start:
-# Required-Stop:
-# Default-Start: rc.local
-# Default-Stop:
-# Short-Description: Daemon gpe
-### END INIT INFO
-
-# Load kernel modules
-load_module () {
- if [ `lsmod | grep -c "gpe "` -eq 0 ]; then
- insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_gpe.ko
- fi
-}
-
-remove_module () {
- rmmod mitac-ly1200-32x_gpe
-}
-
-case "$1" in
- start)
- load_module
- ;;
- stop)
- remove_module
- ;;
- reload|restart|force-reload)
- remove_module
- load_module
- ;;
- *)
- echo "Usage: $N {start|stop|reload|restart|force-reload}" >&2
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init
index caddfce3325d..4281cc00c1e0 100755
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init
@@ -1,16 +1,17 @@
#!/bin/bash
### BEGIN INIT INFO
-# Provides: setup-board
+# Provides: setup-board-i2c
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
-# Default-Start: S
-# Default-Stop: 0 6
+# Default-Start:
+# Default-Stop:
# Short-Description: Setup ly1200-32x board.
### END INIT INFO
+I2C_BUS_RM_ALL=0
I2C_I801_RM_PRINT=0
I2C_ISMT_RM_PRINT=0
I2C_I801_INS_PRINT=0
@@ -47,90 +48,9 @@ function log_msg() {
# Load kernel modules
load_modules () {
- #----------remove i801 start---------------------
- if [ `lsmod | grep -c "i2c_i801 "` -eq 1 ]; then
- rmmod i2c_i801
- while [ `lsmod | grep -c "i2c_i801 "` -eq 1 ]
- do
- if [ $I2C_I801_RM_PRINT -eq 0 ]; then
- I2C_I801_RM_PRINT=1
- log_msg "Wait for i2c_i801 remove."
- fi
- if [ $I2C_I801_RM_RETRY -lt $RETRY ];then
- I2C_I801_RM_RETRY=$((I2C_I801_RM_RETRY + 1))
- else
- break
- fi
- sleep 1
- done
- if [ $I2C_I801_RM_PRINT -eq 1 ]; then
- log_msg "i2c_i801 remove success."
- fi
- fi
- #----------remove i801 end------------------------
-
-
- #----------remove ismt start----------------------
- if [ `lsmod | grep -c "i2c_ismt "` -eq 1 ]; then
- rmmod i2c_ismt
- while [ `lsmod | grep -c "i2c_ismt "` -eq 1 ]
- do
- if [ $I2C_ISMT_RM_PRINT -eq 0 ]; then
- I2C_ISMT_RM_PRINT=1
- log_msg "Wait for i2c_ismt remove."
- fi
- if [ $I2C_ISMT_RM_RETRY -lt $RETRY ];then
- I2C_ISMT_RM_RETRY=$((I2C_ISMT_RM_RETRY + 1))
- else
- break
- fi
- sleep 1
- done
- if [ $I2C_ISMT_RM_PRINT -eq 1 ]; then
- log_msg "i2c_ismt remove success."
- fi
- fi
- #----------remove ismt end------------------------
-
- #----------insert i801 start----------------------
- insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-i801.ko
- while [ `lsmod | grep -c "i2c_i801 "` -eq 0 ]
- do
- if [ $I2C_I801_INS_PRINT -eq 0 ]; then
- I2C_I801_INS_PRINT=1
- log_msg "Wait for i2c_i801 insert."
- fi
- if [ $I2C_I801_INS_RETRY -lt $RETRY ];then
- I2C_I801_INS_RETRY=$((I2C_I801_INS_RETRY + 1))
- else
- break
- fi
- sleep 1
- done
- if [ $I2C_I801_INS_PRINT -eq 1 ]; then
- log_msg "i2c_i801 insert success."
- fi
- #----------insert i801 end------------------------
-
- #----------insert ismt start----------------------
- insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-ismt.ko
- while [ `lsmod | grep -c "i2c_ismt "` -eq 0 ]
- do
- if [ $I2C_ISMT_INS_PRINT -eq 0 ]; then
- I2C_ISMT_INS_PRINT=1
- log_msg "Wait for i2c_ismt insert."
- fi
- if [ $I2C_ISMT_INS_RETRY -lt $RETRY ];then
- I2C_ISMT_INS_RETRY=$((I2C_ISMT_INS_RETRY + 1))
- else
- break
- fi
- sleep 1
- done
- if [ $I2C_ISMT_INS_PRINT -eq 1 ]; then
- log_msg "i2c_ismt insert success."
- fi
- #----------insert ismt start------------------------
+ modprobe i2c_i801
+ modprobe i2c_ismt
+
if [ `lsmod | grep -c "at24 "` -eq 0 ]; then
insmod /lib/modules/`uname -r`/kernel/drivers/misc/eeprom/at24.ko
fi
@@ -185,18 +105,24 @@ load_i2c_dev_modules () {
fi
}
+# Load nvmem_core modules
+load_nvmem_core_modules () {
+ if [ `lsmod | grep -c "nvmem_core "` -eq 0 ]; then
+ modprobe nvmem_core
+ fi
+}
+
case "$1" in
start)
- echo -n "Setting up board... "
+ echo -n "Loading modules for board... "
load_i2c_dev_modules
+ load_nvmem_core_modules
load_modules
echo "done."
;;
stop)
echo -n "cleaning... "
-
-
echo "done."
;;
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld
index 1df43346f257..7918c836c628 100755
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld
@@ -3,7 +3,7 @@
# Provides: sys-polld
# Required-Start:
# Required-Stop:
-# Default-Start: rc.local
+# Default-Start:
# Default-Stop:
# Short-Description: Daemon sys-polld
### END INIT INFO
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd
index 09ee087d5db0..2737f8fb5507 100755
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd
@@ -3,8 +3,8 @@
# Provides: sys-servd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
-# Default-Start: rc.local
-# Default-Stop: 0 1 6
+# Default-Start:
+# Default-Stop:
# Short-Description: Daemon sys-servd
### END INIT INFO
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd
index 1558614fd43c..4eed58457a33 100755
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd
@@ -3,8 +3,8 @@
# Provides: xcvr-servd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
-# Default-Start: rc.local
-# Default-Stop: 0 1 6
+# Default-Start:
+# Default-Stop:
# Short-Description: Daemon xcvr-servd
### END INIT INFO
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd
deleted file mode 120000
index d71f756d3deb..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd
+++ /dev/null
@@ -1 +0,0 @@
-../init.d/xcvr_servd
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd
deleted file mode 120000
index d71f756d3deb..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd
+++ /dev/null
@@ -1 +0,0 @@
-../init.d/xcvr_servd
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd
deleted file mode 120000
index d71f756d3deb..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd
+++ /dev/null
@@ -1 +0,0 @@
-../init.d/xcvr_servd
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h
index e851ca5fb487..cc256db58c9d 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h
@@ -8,7 +8,7 @@ struct device_attribute field \
#define SYSFS_RAW_RW_ATTR_DEF(field) \
struct device_attribute field \
- = __ATTR(field, S_IRUGO | S_IWUGO, master_cpld_##field##_raw_read, master_cpld_##field##_raw_write);
+ = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, master_cpld_##field##_raw_read, master_cpld_##field##_raw_write);
#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \
struct device_attribute field \
@@ -16,7 +16,7 @@ struct device_attribute field \
#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \
struct device_attribute field \
- = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write);
+ = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, _read, _write);
#define SYSFS_ATTR_PTR(field) \
&field.attr
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c
index e5af8b70bf9a..0900070a8d07 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c
@@ -5,7 +5,12 @@
#include "system_cpld_reg.h"
#include "system_cpld_sysfs.h"
-#ifdef CONFIG_DRV_SYSCPLD_WDT
+
+#define MIC_DEBUG_TAG " [mitac] "
+#define MITAC_WDT_MINOR 135
+#define MITAC_WDT_NAME "watchdog5"
+
+#if CONFIG_DRV_SYSCPLD_WDT
#include
#include
#include
@@ -33,7 +38,6 @@ MODULE_DEVICE_TABLE(i2c, system_cpld_ids);
static int system_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf,
int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){
unsigned int reg_val = 0, fld_val;
- static int debug_flag;
struct system_cpld_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
int err;
@@ -64,7 +68,6 @@ static int system_cpld_raw_write(struct device *dev, struct device_attribute *at
int ret_code;
unsigned int reg_val, fld_val;
unsigned long val;
- static int debug_flag;
struct system_cpld_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
if (reg_width != 8){
@@ -192,7 +195,7 @@ static const struct attribute_group system_cpld_group_misc = {
.attrs = misc_attributes,
};
-#ifdef CONFIG_DRV_SYSCPLD_WDT
+#if CONFIG_DRV_SYSCPLD_WDT
/*
*****************************************************************************
*
@@ -276,9 +279,9 @@ static void wdt_set_timeout(int index)
{
struct device *dev = &system_cpld->client->dev;
struct device_attribute *fake_attr=NULL;
- char buf[1];
+ char buf[16];
if ( WD_TIMO_MAX_NUM == 16 ) {
- sprintf(buf,"%x",index);
+ snprintf(buf, 16, "%x",index);
system_cpld_wd_timer_raw_write(dev, fake_attr, buf, (size_t)0);
}
else
@@ -390,7 +393,7 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd,
*/
static int wdt_open(struct inode *inode, struct file *file)
{
- if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+ if (MINOR(inode->i_rdev) == MITAC_WDT_MINOR) {
if (test_and_set_bit(0, &wdt_is_open)) {
return -EBUSY;
}
@@ -412,7 +415,7 @@ static int wdt_open(struct inode *inode, struct file *file)
*/
static int wdt_release(struct inode *inode, struct file *file)
{
- if (MINOR(inode->i_rdev) == WATCHDOG_MINOR)
+ if (MINOR(inode->i_rdev) == MITAC_WDT_MINOR)
clear_bit(0, &wdt_is_open);
return 0;
}
@@ -447,8 +450,8 @@ static const struct file_operations wdt_fops = {
};
static struct miscdevice wdt_dev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
+ .minor = MITAC_WDT_MINOR,
+ .name = MITAC_WDT_NAME,
.fops = &wdt_fops,
};
@@ -459,6 +462,8 @@ static struct miscdevice wdt_dev = {
static struct notifier_block wdt_notifier = {
.notifier_call = wdt_notify_sys,
};
+static struct notifier_block *p_wdt_notifier = NULL;
+
#endif /* CONFIG_DRV_SYSCPLD_WDT */
static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -483,14 +488,22 @@ static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_
printk(KERN_INFO "%s: System CPLD LCMXO3LF created.\n", __FUNCTION__);
-#ifdef CONFIG_DRV_SYSCPLD_WDT
+#if CONFIG_DRV_SYSCPLD_WDT
+ wdt_dev.minor = MITAC_WDT_MINOR;
err = misc_register(&wdt_dev);
- if (err)
- return err;
- err = register_reboot_notifier(&wdt_notifier);
if (err) {
- misc_deregister(&wdt_dev);
- return err;
+ printk(MIC_DEBUG_TAG"%s-%d misc_register register watchdog (%s : %d) fail err=%d \n", __FUNCTION__, __LINE__, wdt_dev.name, wdt_dev.minor, err);
+ wdt_dev.minor = 0;
+ }
+ else {
+ p_wdt_notifier = &wdt_notifier;
+ err = register_reboot_notifier(p_wdt_notifier);
+ if (err) {
+ printk(MIC_DEBUG_TAG"%s-%d register_reboot_notifier fail err:%d \n", __FUNCTION__, __LINE__, err);
+ misc_deregister(&wdt_dev);
+ p_wdt_notifier = NULL;
+ wdt_dev.minor = 0;
+ }
}
printk(KERN_INFO "%s: System CPLD watchdog created.\n", __FUNCTION__);
#endif
@@ -501,9 +514,9 @@ static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_
static int system_cpld_remove(struct i2c_client *client)
{
-#ifdef CONFIG_DRV_SYSCPLD_WDT
- misc_deregister(&wdt_dev);
- unregister_reboot_notifier(&wdt_notifier);
+#if CONFIG_DRV_SYSCPLD_WDT
+ if(p_wdt_notifier) unregister_reboot_notifier(p_wdt_notifier);
+ if(wdt_dev.minor) misc_deregister(&wdt_dev);
#endif
sysfs_remove_group(&client->dev.kobj, &system_cpld_group_misc);
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h
index 92d00d29d493..a619f45388cb 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h
@@ -8,7 +8,7 @@ struct device_attribute field \
#define SYSFS_RAW_RW_ATTR_DEF(field) \
struct device_attribute field \
- = __ATTR(field, S_IRUGO | S_IWUGO, slave_cpld_##field##_raw_read, slave_cpld_##field##_raw_write);
+ = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, slave_cpld_##field##_raw_read, slave_cpld_##field##_raw_write);
#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \
struct device_attribute field \
@@ -16,7 +16,7 @@ struct device_attribute field \
#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \
struct device_attribute field \
- = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write);
+ = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, _read, _write);
#define SYSFS_ATTR_PTR(field) \
&field.attr
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h
index e6b03bd1bd0d..1dbe9b2819f9 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h
@@ -8,7 +8,7 @@ struct device_attribute field \
#define SYSFS_RAW_RW_ATTR_DEF(field) \
struct device_attribute field \
- = __ATTR(field, S_IRUGO | S_IWUGO, system_cpld_##field##_raw_read, system_cpld_##field##_raw_write);
+ = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, system_cpld_##field##_raw_read, system_cpld_##field##_raw_write);
#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \
struct device_attribute field \
@@ -16,7 +16,7 @@ struct device_attribute field \
#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \
struct device_attribute field \
- = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write);
+ = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, _read, _write);
#define SYSFS_ATTR_PTR(field) \
&field.attr
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf
index 56409f5c3e30..fc37dda47f47 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf
@@ -1,12 +1,13 @@
##### Temperature vs Fan table #####
## FORMAT: "PWM" fan speed(range from 0 to 255)
-# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100%
-PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255
+# Duty Cycle 30% 32.5% 35% 37.5% 40% 45% 50% 55% 60% 65% 70% 75% 80% 90% 100%
+PWM 77 83 89 95 102 114 128 141 153 166 179 192 204 230 255
## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels
-TEMP_CPU 52 55 58 61 64 67 70 73 76 79 82 85 88 91 94 97
-TEMP_SWITCH 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120
+TEMP_CPU 46 48 50 52 54 57 60 63 66 69 72 75 78 81 84
+TEMP_SWITCH 72 74 76 78 80 83 86 89 92 95 98 101 104 107 110
#TEMP_HDD 25
#TEMP_TMP75_CPU 25
#TEMP_TMP75_CENTER 25
-#TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93
-TEMP_TMP75_FAN 26.5 31.5 36.5 41.5 46.5 51.5 56.5 61.5 66.5 71.5 76.5 81.5 86.5 91.5 96.5 101.5
+#TEMP_TMP75_RIGHT 33 37 45 53 61 69 77 85 93
+TEMP_TMP75_FAN 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55
+TEMP_XCVR 36 38 40 42 44 46 48 50 52 54 56 58 60 63 66
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf
index 6c459d874feb..ee316c66bd06 100644
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf
@@ -1,12 +1,12 @@
##### Temperature vs Fan table #####
## FORMAT: "PWM" fan speed(range from 0 to 255)
-# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100%
-PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255
+# Duty Cycle 29% 31% 33% 35% 37.5% 40% 45% 50% 55% 60% 65% 70% 75% 80% 90% 100%
+PWM 74 79 84 89 96 102 115 128 140 153 166 179 191 204 230 255
## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels
-TEMP_CPU 60 65 70 73 76 79 82 85 88 91 94 97 100 103 106 109
-TEMP_SWITCH 73 76 79 82 85 88 91 94 97 100 103 106 109 112 115 118
+TEMP_CPU 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81
+TEMP_SWITCH 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
#TEMP_HDD 25
#TEMP_TMP75_CPU 25
#TEMP_TMP75_CENTER 25
-TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93
+TEMP_TMP75_RIGHT 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55
#TEMP_TMP75_FAN 25
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh
deleted file mode 100755
index 4b0c4c35471f..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#/bin/bash
-
-# process name/id
-DAEMON_NAME=`basename $0`
-DAEMON_PID="$$"
-
-DEF_SEVERITY="INFO"
-
-#/*
-#* FEATURE:
-#* log_msg
-#* PURPOSE:
-#* log message
-#* PARAMETERS:
-#* msg (IN) message
-#* RETURNS:
-#*
-#*/
-function log_msg() {
- local msg=$1
-
- `logger -t $DAEMON_NAME -p $DEF_SEVERITY $msg`
-}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh
deleted file mode 100755
index 2bc9589738d0..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#/bin/bash
-
-DIR=$(dirname $0)
-
-# include files
-source ${DIR}/funcs.sh
-
-ACPI_INSTALL_PRINT=0
-ACPID_INSTALL_PRINT=0
-BC_INSTALL_PRINT=0
-ACPID_SOCKET_PRINT=0
-ACPI_PRINT=0
-
-
-while [ 1 ]
-do
- if [ `dpkg -l |grep -c "acpi "` -eq "0" ]; then
- dpkg -i /opt/debs/acpi_1.7-1_amd64.deb
- if [ "$?" -ne "0" ]; then
- if [ $ACPI_INSTALL_PRINT -eq 0 ]; then
- ACPI_INSTALL_PRINT=1
- log_msg "Wait for acpi package install."
- fi
- sleep 1
- continue
- else
- log_msg "Install acpi package success."
- fi
- fi
- break
-done
-
-while [ 1 ]
-do
- if [ `dpkg -l |grep -c "acpid "` -eq "0" ]; then
- dpkg -i /opt/debs/acpid_2.0.23-2_amd64.deb
- if [ "$?" -ne "0" ]; then
- if [ $ACPID_INSTALL_PRINT -eq 0 ]; then
- ACPID_INSTALL_PRINT=1
- log_msg "Wait for acpid package install."
- fi
- sleep 1
- continue
- else
- log_msg "Install acpid package success."
- fi
- fi
- break
-done
-
-while [ 1 ]
-do
- if [ `dpkg -l |grep -c " bc "` -eq "0" ]; then
- dpkg -i /opt/debs/bc_1.06.95-9_amd64.deb
- if [ "$?" -ne "0" ]; then
- if [ $BC_INSTALL_PRINT -eq 0 ]; then
- BC_INSTALL_PRINT=1
- log_msg "Wait for bc package install."
- fi
- sleep 1
- continue
- else
- log_msg "Install bc package success."
- fi
- fi
- break
-done
-
-while [ 1 ]
-do
- if [ ! -e "/sys/firmware/acpi/interrupts/gpe01" ]; then
- if [ $ACPI_PRINT -eq 0 ]; then
- ACPI_PRINT=1
- log_msg "Wait for acpi daemon start."
- fi
- sleep 1
- continue
- fi
- log_msg "The acpi daemon start."
- break
-done
-
-while [ 1 ]
-do
- if [ ! -e "/var/run/acpid.socket" ]; then
- if [ $ACPID_SOCKET_PRINT -eq 0 ]; then
- ACPID_SOCKET_PRINT=1
- log_msg "Wait for acipd daemon start."
- fi
- sleep 1
- continue
- fi
- log_msg "The acpid daemon start."
- break
-done
-
-/etc/init.d/xcvr_servd start
-/etc/init.d/sys_servd start
-exit 0;
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh
deleted file mode 100755
index 2268e5e0d16e..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#/bin/bash
-
-DIR=$(dirname $0)
-
-# include files
-source ${DIR}/funcs.sh
-
-WATCHDOG_PRINT=0
-
-while [ 1 ]
-do
- if [ `dpkg -l |grep -c "watchdog "` -eq "0" ]; then
- dpkg -i /opt/debs/watchdog_5.14-3_amd64.deb
- if [ "$?" -ne "0" ]; then
- if [ $WATCHDOG_PRINT -eq 0 ]; then
- WATCHDOG_PRINT=1
- log_msg "Wait for watchdog package install."
- fi
- sleep 1
- continue
- else
- log_msg "Install watchdog package success."
- fi
- fi
- break
-done
-
-ln -sf /opt/watchdog/watchdog.conf /etc/watchdog.conf
-
-/usr/sbin/watchdog -c /etc/watchdog.conf
-
-exit 0;
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/Makefile b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/Makefile
new file mode 100644
index 000000000000..c91a02ade953
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/Makefile
@@ -0,0 +1,51 @@
+#/*
+#**********************************************************************
+#*
+#* @filename Makefile
+#*
+#* @purpose This Makefile is used for Lattice utility
+#*
+#* @create 2017/03/16
+#*
+#* @author eddy.weng
+#*
+#* @history 2017/03/16: init version
+#*
+#**********************************************************************
+#*/
+
+TARGETS := sys-servd
+INC = $(wildcard *.h)
+OBJ=$(subst .c,.o,$(wildcard *.c))
+
+.PHONY: all
+all: $(TARGETS)
+
+.PHONY: config
+config:
+
+.PHONY: patch
+patch:
+
+.PHONY: install
+install:
+ mkdir -p $(INST_DIR)/sys-serv/
+ cp $(TARGETS) $(INST_DIR)/sys-serv/
+
+.PHONY: uninstall
+uninstall:
+ rm -f $(addprefix $(INST_DIR)/xcvr-serv/,$(TARGETS))
+
+.PHONY: clean
+clean:
+ rm -rf $(OBJ) $(TARGETS)
+
+.PHONY: distclean
+distclean: clean
+
+$(OBJ): $(INC)
+%.o: %.c
+ $(CC) -c -o $@ $< -Wall -Wextra -Werror
+
+$(TARGETS): $(OBJ)
+ $(CC) $^ -lrt -pthread -o $@
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_cpu_temp_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_cpu_temp_servd.c
new file mode 100644
index 000000000000..2ac8d0e424ac
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_cpu_temp_servd.c
@@ -0,0 +1,105 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_cpu_temp_servd.c
+ *
+ * @purpose BMS cpu temperature service
+ *
+ * @create 2017/3/17
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_irq_sysd.h"
+
+#include
+
+/*
+* FEATURE:
+* bms_cpu_temp_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_cpu_temp_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_RDONLY), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+/*
+* FEATURE:
+* bms_cpu_temp_servd
+* PURPOSE:
+* service to handle message queue event of cpu temperature
+* PARAMETERS:
+* args (IN) message queue name
+* RETURNS:
+* open success, this function will wait for message queue.
+* for other cases, will exit this program.
+*/
+void*
+bms_cpu_temp_servd(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ bms_sys_serv_mq_data_t msg;
+ int ret_code;
+
+ /* Open message queue */
+ if (bms_cpu_temp_msq_open(mq_name, &mq_desc) < 0) {
+ goto quit;
+ }
+
+ while (1) {
+ /* Wait for message queue */
+ if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ switch (msg.serv_type) {
+ case SERV_TYPE_RX_INTR: /* CPU_THERMTRIP_IRQ interrupt */
+ syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name);
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name);
+ break;
+ }
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_polld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_polld.c
new file mode 100644
index 000000000000..a4a0594b4706
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_polld.c
@@ -0,0 +1,314 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "bms_sys_serv_common.h"
+#include "bms_fan_servd.h"
+
+/*
+* FEATURE:
+* bms_fan_poll_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_poll_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_WRONLY | O_NONBLOCK), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_poll_msq_send
+* PURPOSE:
+* send POSIX message queue
+* PARAMETERS:
+* msg (IN) message of send data
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_poll_msq_send(bms_sys_serv_mq_data_t* msg,
+ mqd_t *mqd)
+{
+ int ret_code;
+
+ if (mq_send(*mqd, (char*)msg, sizeof(*msg), 0) < 0) {
+ ret_code = errno;
+ if (ret_code == EAGAIN) {
+ syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", msg->serv_name);
+ }
+ else {
+ syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", msg->serv_name, strerror(ret_code));
+ }
+ }
+
+ return -ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_fan_poll_init
+* PURPOSE:
+* initial all
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_poll_init(char *mq_name,
+ mqd_t *mq_desc)
+{
+ int ret_code = 0;
+
+ /* open message queue*/
+ if ((ret_code = bms_fan_poll_msq_open(mq_name, mq_desc)) < 0) {
+ return ret_code;
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_poll_detect_fan_status
+* PURPOSE:
+* datect fan status is present or non present
+* PARAMETERS:
+* present_bmap (OUT) pointer of present bmap
+* nonpresent_bmap (OUT) pointer of non-present bmap
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_poll_detect_module_status(unsigned int *present_bmap,
+ unsigned int *nonpresent_bmap,
+ unsigned int *intr_bmap)
+{
+ int ret_code = 0, i, j;
+ unsigned int module_present_bmap;
+ unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM];
+ unsigned int module_intr[BMS_FAN_MODULE_NUM] = {BMS_FAN_INTR_NORMAL};
+ unsigned int intr_tmp;
+
+ for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){
+ bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]);
+ }
+
+ /* read fan present from sysfs, 0 for present and 1 for non-present */
+ if((ret_code = bms_fan_serv_fan_present_get( &module_present_bmap)) < 0){
+ return ret_code;
+ }
+
+ /* get interrupt source from fan control */
+ for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){
+ for(j = 0 ; j < BMS_FAN_NUM_PER_MODULE; j++){
+ if((ret_code = bms_fan_serv_fan_intr_get(((i * BMS_FAN_NUM_PER_MODULE) + j), &intr_tmp)) < 0){
+ return ret_code;
+ }
+ if(intr_tmp == BMS_FAN_INTR_FAULT){
+ module_intr[i] = BMS_FAN_INTR_FAULT;
+ break;
+ }
+ }
+ }
+
+ /* present */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ //bms_fan_serv_cache_module_status_get(i, &status);
+ if((cache_status[i] == BMS_FAN_MODULE_STATUS_NONPRESENT) ||
+ (cache_status[i] == BMS_FAN_MODULE_STATUS_NONREADY) ||
+ (cache_status[i] == BMS_FAN_MODULE_STATUS_NONINIT)){
+ if(!(module_present_bmap & (1 << i))){
+ *present_bmap |= (1 << i);
+ }
+ }
+ }
+
+
+ //mask = 1;
+
+ /* non preent */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ //bms_fan_serv_cache_module_status_get(i, &status);
+ if((cache_status[i] == BMS_FAN_MODULE_STATUS_NORMAL) ||
+ (cache_status[i] == BMS_FAN_MODULE_STATUS_NONINIT) ||
+ (cache_status[i] == BMS_FAN_MODULE_STATUS_FAILED)){
+ if(module_present_bmap & (1 << i)){
+ *nonpresent_bmap |= (1 << i);
+ }
+ }
+ }
+
+ /* fan fault */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if((cache_status[i] == BMS_FAN_MODULE_STATUS_NORMAL) ||
+ (cache_status[i] == BMS_FAN_MODULE_STATUS_NONREADY)){
+ if(module_intr[i] == BMS_FAN_INTR_FAULT){
+ *intr_bmap |= (1 << i);
+ }
+ }
+ }
+
+ return ret_code;
+}
+
+
+
+/*
+* FEATURE:
+* bms_fan_poll_module_fault_reset
+* PURPOSE:
+* reset fan fault status in fan controller
+* PARAMETERS:
+* fan_number (IN) fan number
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_poll_module_fault_reset(unsigned int module_number)
+{
+ return bms_fan_serv_fan_pwm_set(module_number, BMS_FAN_PWM_DUTY_CYCLE_MAX);
+}
+
+/*
+* FEATURE:
+* bms_fan_polld
+* PURPOSE:
+* bms fan module polling daemon
+* PARAMETERS:
+* args (IN) input value(message name)
+* RETURNS:
+* The process will always polling fan module.
+*/
+void*
+bms_fan_polld(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ int ret_code = 0, i;
+ unsigned int module_type;
+ bms_sys_serv_mq_data_t msg;
+ unsigned int present_bmap = 0, nonpresent_bmap = 0, intr_bmap = 0;
+ unsigned int cache_status, cache_type, cache_retry;
+
+ msg.serv_name = mq_name;
+
+ if((ret_code = bms_fan_poll_init(mq_name, &mq_desc)) < 0){
+ goto quit;
+ }
+
+ while(!bms_fan_init_done){
+ sleep(1);
+ }
+
+ while(1){
+ present_bmap = 0;
+ nonpresent_bmap = 0;
+ intr_bmap = 0;
+
+ if((ret_code = bms_fan_poll_detect_module_status(&present_bmap, &nonpresent_bmap, &intr_bmap)) < 0){
+ goto wait;
+ }
+
+ if((present_bmap == 0) &&
+ (nonpresent_bmap == 0) &&
+ (intr_bmap == 0))
+ goto wait;
+
+ if(present_bmap != 0){
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if(present_bmap & (1 << i)){
+ bms_fan_serv_cache_module_cache_get(i, &cache_status, &cache_type);
+
+ bms_fan_serv_cache_module_cache_retry_get(i, &cache_retry);
+
+ /* Due to max31790 driver has cache to protect i2c, so we will get older data sometimes.
+ * That data will confuse the fan fault status.
+ * So we will read fan fault status after wait 3 second delay.
+ */
+ if(cache_retry == BMS_FAN_NONREADY_RETRY_INIT){
+ if((ret_code = bms_fan_poll_module_fault_reset(i)) < 0){
+ continue;
+ }
+ bms_fan_serv_cache_module_cache_retry_set(i, ++cache_retry);
+ }else{
+ if(cache_retry < BMS_FAN_NONREADY_RETRY){
+ bms_fan_serv_cache_module_cache_retry_set(i, ++cache_retry);
+ continue;
+ }
+ }
+ msg.serv_type = SERV_TYPE_FAN_MODULE_PRESENT;
+ msg.number = i;
+
+ if((ret_code = bms_fan_serv_module_type_get(i, &module_type)) < 0){
+ continue;
+ }
+ msg.type = module_type;
+
+ bms_fan_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+ }
+
+ if(nonpresent_bmap != 0){
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if(nonpresent_bmap & (1 << i)){
+ msg.number = i;
+ msg.serv_type = SERV_TYPE_FAN_MODULE_NONPRESENT;
+ bms_fan_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+ }
+
+ /* handle interrupt bit map */
+ if(intr_bmap != 0){
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if(intr_bmap & (1 << i)){
+
+ bms_fan_serv_cache_module_cache_retry_get(i, &cache_retry);
+
+ if(cache_retry < BMS_FAN_NONREADY_RETRY){
+ continue;
+ }
+
+ msg.number = i;
+ msg.serv_type = SERV_TYPE_RX_INTR;
+ bms_fan_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+ }
+
+wait:
+ sleep(1);
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.c
new file mode 100644
index 000000000000..0ea40b7a83d9
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.c
@@ -0,0 +1,1383 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_fan_servd.c
+ *
+ * @purpose BMS fan service daemon
+ *
+ * @create 2017/3/17
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "bms_sys_serv_common.h"
+#include "bms_fan_servd.h"
+
+bms_fan_serv_data_t bms_fan_serv_data[BMS_FAN_MODULE_NUM * BMS_FAN_NUM_PER_MODULE] = {
+ {
+ .number = 1,
+ .hwmon_path = "/sys/bus/i2c/devices/3-0020/hwmon",
+ .intr_src = "fan1_fault",
+ .intr_msk = "fan1_fault_mask",
+ .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray1_led",
+ .type = "/sys/bus/i2c/devices/1-0032/fan_type1",
+ .present = "/sys/bus/i2c/devices/1-0032/fan_tray1_6_present",
+ .pwm = "pwm1",
+ .pwm_enable = "pwm1_enable",
+ .input = "fan1_input",
+ .smart_fan_path = "/etc/init.d/fan-ctrld",
+ },
+ {
+ .number = 2,
+ .hwmon_path = NULL, /* share same path with FAN number 1 */
+ .intr_src = "fan2_fault",
+ .intr_msk = "fan2_fault_mask",
+ .tray_led = NULL,
+ .type = NULL,
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm2",
+ .pwm_enable = "pwm2_enable",
+ .input = "fan2_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 3,
+ .hwmon_path = NULL, /* share same path with FAN number 1 */
+ .intr_src = "fan3_fault",
+ .intr_msk = "fan3_fault_mask",
+ .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray2_led",
+ .type = "/sys/bus/i2c/devices/1-0032/fan_type2",
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm3",
+ .pwm_enable = "pwm3_enable",
+ .input = "fan3_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 4,
+ .hwmon_path = NULL, /* share same path with FAN number 1 */
+ .intr_src = "fan4_fault",
+ .intr_msk = "fan4_fault_mask",
+ .tray_led = NULL,
+ .type = NULL,
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm4",
+ .pwm_enable = "pwm4_enable",
+ .input = "fan4_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 5,
+ .hwmon_path = NULL, /* share same path with FAN number 1 */
+ .intr_src = "fan5_fault",
+ .intr_msk = "fan5_fault_mask",
+ .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray3_led",
+ .type = "/sys/bus/i2c/devices/1-0032/fan_type3",
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm5",
+ .pwm_enable = "pwm5_enable",
+ .input = "fan5_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 6,
+ .hwmon_path = NULL, /* share same path with FAN number 1 */
+ .intr_src = "fan6_fault",
+ .intr_msk = "fan6_fault_mask",
+ .tray_led = NULL,
+ .type = NULL,
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm6",
+ .pwm_enable = "pwm6_enable",
+ .input = "fan6_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 7,
+ .hwmon_path = "/sys/bus/i2c/devices/3-0023/hwmon",
+ .intr_src = "fan1_fault",
+ .intr_msk = "fan1_fault_mask",
+ .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray4_led",
+ .type = "/sys/bus/i2c/devices/1-0032/fan_type4",
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm1",
+ .pwm_enable = "pwm1_enable",
+ .input = "fan1_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 8,
+ .hwmon_path = NULL, /* share same path with FAN number 7 */
+ .intr_src = "fan2_fault",
+ .intr_msk = "fan2_fault_mask",
+ .tray_led = NULL,
+ .type = NULL,
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm2",
+ .pwm_enable = "pwm2_enable",
+ .input = "fan2_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 9,
+ .hwmon_path = NULL, /* share same path with FAN number 7 */
+ .intr_src = "fan3_fault",
+ .intr_msk = "fan3_fault_mask",
+ .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray5_led",
+ .type = "/sys/bus/i2c/devices/1-0032/fan_type5",
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm3",
+ .pwm_enable = "pwm3_enable",
+ .input = "fan3_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 10,
+ .hwmon_path = NULL, /* share same path with FAN number 7 */
+ .intr_src = "fan4_fault",
+ .intr_msk = "fan4_fault_mask",
+ .tray_led = NULL,
+ .type = NULL,
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm4",
+ .pwm_enable = "pwm4_enable",
+ .input = "fan4_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 11,
+ .hwmon_path = NULL, /* share same path with FAN number 7 */
+ .intr_src = "fan5_fault",
+ .intr_msk = "fan5_fault_mask",
+ .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray6_led",
+ .type = "/sys/bus/i2c/devices/1-0032/fan_type6",
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm5",
+ .pwm_enable = "pwm5_enable",
+ .input = "fan5_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+ {
+ .number = 12,
+ .hwmon_path = NULL, /* share same path with FAN number 7 */
+ .intr_src = "fan6_fault",
+ .intr_msk = "fan6_fault_mask",
+ .tray_led = NULL,
+ .type = NULL,
+ .present = NULL, /* share same byte with FAN1 */
+ .pwm = "pwm6",
+ .pwm_enable = "pwm6_enable",
+ .input = "fan6_input",
+ .smart_fan_path = NULL, /* share same path with FAN1 */
+ },
+};
+
+unsigned int bms_fan_status[BMS_FAN_MODULE_NUM];
+unsigned int bms_fan_type[BMS_FAN_MODULE_NUM];
+unsigned int bms_fan_retry[BMS_FAN_MODULE_NUM];
+unsigned int bms_board_type;
+int bms_fan_init_done = 0;
+pthread_mutex_t bms_fan_cache_lock;
+
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_module_led_set
+* PURPOSE:
+* fan service fan module led set to file system
+* PARAMETERS:
+* module_number (IN) module number
+* value (IN) setting value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_module_led_set(unsigned int module_number,
+ unsigned int value)
+{
+ return bms_sys_serv_write(bms_fan_serv_data[module_number * BMS_FAN_NUM_PER_MODULE].tray_led, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_pwm_set
+* PURPOSE:
+* fan service fan pwm duty cycle set to file system
+* PARAMETERS:
+* module_number (IN) module number
+* value (IN) setting value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_pwm_set(unsigned int module_number,
+ unsigned int value)
+{
+ int i, ret_code = 0;
+
+ for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){
+ if((ret_code = bms_sys_serv_write(bms_fan_serv_data[(module_number * BMS_FAN_NUM_PER_MODULE) + i].pwm, value)) < 0){
+ break;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_pwm_enable_set
+* PURPOSE:
+* fan service fan pwm mode set to file system
+* PARAMETERS:
+* module_number (IN) module number
+* value (IN) setting value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_pwm_enable_set(unsigned int module_number,
+ unsigned int value)
+{
+ int i, ret_code = 0;
+
+ for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){
+ if((ret_code = bms_sys_serv_write(bms_fan_serv_data[(module_number * BMS_FAN_NUM_PER_MODULE) + i].pwm_enable, value)) < 0){
+ break;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_mask_set
+* PURPOSE:
+* fan service fan mask set to file system in fan controller
+* PARAMETERS:
+* fan_number (IN) fan number
+* value (IN) setting value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_mask_set(unsigned int fan_number,
+ unsigned int value)
+{
+/*
+* within kernel 4.9 max31790 driver, there is no "fan_fault_mask" file nodes
+* so just return 0
+*/
+#if 1
+#define UNUSED(x) (void)(x)
+ UNUSED(fan_number);
+ UNUSED(value);
+ return 0;
+#else
+ return bms_sys_serv_write(bms_fan_serv_data[fan_number].intr_msk, value);
+#endif
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_global_mask_set
+* PURPOSE:
+* fan service fan global mask set to file system
+* PARAMETERS:
+* index (IN) fan index in bms_sys_serv_data
+* value (IN) setting value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_global_mask_set(unsigned int index,
+ unsigned int value)
+{
+ return bms_sys_serv_write(bms_sys_serv_data[index].intr_msk, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_panel_led_set
+* PURPOSE:
+* fan service fan panel led set to file system in CPLD
+* PARAMETERS:
+* value (IN) setting value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_panel_led_set(unsigned int value)
+{
+ return bms_sys_serv_write(BMS_SYSFS_FAN_PANEL_LED, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_intr_get
+* PURPOSE:
+* fan service fan interrupt get from file system
+* PARAMETERS:
+* fan_number (IN) fan number
+* value (out) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_intr_get(unsigned int fan_number,
+ unsigned int *value)
+{
+ return bms_sys_serv_dec_read(bms_fan_serv_data[fan_number].intr_src, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_input_get
+* PURPOSE:
+* fan service fan input value get from file system
+* PARAMETERS:
+* fan_number (IN) fan number
+* value (out) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_input_get(unsigned int fan_number,
+ unsigned int *value)
+{
+ return bms_sys_serv_dec_read(bms_fan_serv_data[fan_number].input, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_mask_get
+* PURPOSE:
+* fan service fan fault mask value get from file system
+* PARAMETERS:
+* fan_number (IN) fan number
+* value (out) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_mask_get(unsigned int fan_number,
+ unsigned int *value)
+{
+ return bms_sys_serv_dec_read(bms_fan_serv_data[fan_number].intr_msk, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_module_type_get
+* PURPOSE:
+* fan service fan type get from file system
+* PARAMETERS:
+* module_number (IN) module number
+* value (OUT) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_module_type_get(unsigned int module_number,
+ unsigned int *value)
+{
+ return bms_sys_serv_hex_read(bms_fan_serv_data[module_number * BMS_FAN_NUM_PER_MODULE].type, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_present_get
+* PURPOSE:
+* fan service fan present get from file system
+* PARAMETERS:
+* value (OUT) pointer of present bitmap
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_present_get(unsigned int *value)
+{
+ return bms_sys_serv_hex_read(bms_fan_serv_data[0].present, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_board_type_get
+* PURPOSE:
+* fan service fan board get from file system
+* PARAMETERS:
+* value (OUT) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_board_type_get(unsigned int *value)
+{
+ return bms_sys_serv_hex_read(BMS_SYSFS_BOARD_TYPE, value);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_mask_init
+* PURPOSE:
+* enable all fan interrupt mask in fan controller
+* PARAMETERS:
+*
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_mask_init(void)
+{
+ int i, ret_code = 0;
+
+ for(i = 0; i < BMS_FAN_NUM_PER_MODULE * BMS_FAN_MODULE_NUM; i++){
+ if((ret_code = bms_fan_serv_fan_mask_set(i, BMS_FAN_INTR_MASKED)) < 0){
+ break;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_cache_init
+* PURPOSE:
+* initial fan status and fan type
+* PARAMETERS:
+*
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_cache_init(void)
+{
+ int ret_code = 0, i;
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ bms_fan_status[i] = BMS_FAN_MODULE_STATUS_NONINIT;
+ bms_fan_retry[i] = BMS_FAN_NONREADY_RETRY_INIT;
+ if((bms_board_type == BMS_AC_PSU_NORMAL_FAN) || (bms_board_type == BMS_DC_PSU_NORMAL_FAN)){
+ bms_fan_type[i] = BMS_FAN_MODULE_TYPE_NORMAL;
+ }else if((bms_board_type == BMS_AC_PSU_REVERSE_FAN) || (bms_board_type == BMS_DC_PSU_REVERSE_FAN)){
+ bms_fan_type[i] = BMS_FAN_MODULE_TYPE_REVERSE;
+ }else{
+ syslog(LOG_WARNING|LOG_USER,"Can't identify board_type.\n");
+ return -EINVAL;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_pwm_init
+* PURPOSE:
+* initial all fan pwm mode and duty cycle
+* PARAMETERS:
+*
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_pwm_init(void)
+{
+ int ret_code, i;
+
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if((ret_code = bms_fan_serv_fan_pwm_enable_set(i, BMS_FAN_PWM_ENABLE_PWM)) < 0){
+ break;
+ }
+ if((ret_code = bms_fan_serv_fan_pwm_set(i, BMS_FAN_PWM_DUTY_CYCLE_MAX)) < 0){
+ break;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_mutex_init
+* PURPOSE:
+* initial mutex
+* PARAMETERS:
+*
+* RETURNS:
+* init success, this function shall return zero.
+* otherwise, an error number shall be returned to indicate the error.
+*/
+static int
+bms_fan_serv_mutex_init(void)
+{
+ int ret_code;
+
+ if((ret_code = pthread_mutex_init(&bms_fan_cache_lock, NULL)) != 0){
+ return -ret_code;
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_cache_module_cache_get
+* PURPOSE:
+* fan service cache get
+* PARAMETERS:
+* module_number (IN) module number
+* module_status (OUT) pointer of module status
+* module_type (OUT) pointer of module type
+* RETURNS:
+*/
+void
+bms_fan_serv_cache_module_cache_get(unsigned int module_number,
+ unsigned int* module_status,
+ unsigned int* module_type)
+{
+ pthread_mutex_lock(&bms_fan_cache_lock);
+ *module_status = bms_fan_status[module_number];
+ *module_type = bms_fan_type[module_number];
+ pthread_mutex_unlock(&bms_fan_cache_lock);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_cache_module_cache_retry_get
+* PURPOSE:
+* fan service cache retry get
+* PARAMETERS:
+* module_number (IN) module number
+* module_retry (OUT) pointer of module retry
+* RETURNS:
+*/
+void
+bms_fan_serv_cache_module_cache_retry_get(unsigned int module_number,
+ unsigned int* module_retry)
+{
+ pthread_mutex_lock(&bms_fan_cache_lock);
+ *module_retry = bms_fan_retry[module_number];
+ pthread_mutex_unlock(&bms_fan_cache_lock);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_cache_module_cache_retry_set
+* PURPOSE:
+* fan service cache retry set
+* PARAMETERS:
+* module_number (IN) module number
+* value (OUT) retry value
+* RETURNS:
+*/
+void
+bms_fan_serv_cache_module_cache_retry_set(unsigned int module_number,
+ unsigned int value)
+{
+ pthread_mutex_lock(&bms_fan_cache_lock);
+ bms_fan_retry[module_number] = value;
+ pthread_mutex_unlock(&bms_fan_cache_lock);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_file_path_rename
+* PURPOSE:
+* rename sysfs path
+* PARAMETERS:
+* RETURNS:
+* success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_file_path_rename(void)
+{
+ int i, ret_code = 0;
+
+ for(i = 0; i < BMS_FAN_MODULE_NUM * BMS_FAN_CONTROL_NUM ; i++){
+ if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path,
+ bms_fan_serv_data[i].intr_src)) < 0){
+ return -ret_code;
+ }
+ if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path,
+ bms_fan_serv_data[i].intr_msk)) < 0){
+ return -ret_code;
+ }
+ if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path,
+ bms_fan_serv_data[i].pwm)) < 0){
+ return -ret_code;
+ }
+ if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path,
+ bms_fan_serv_data[i].pwm_enable)) < 0){
+ return -ret_code;
+ }
+ if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path,
+ bms_fan_serv_data[i].input)) < 0){
+ return -ret_code;
+ }
+ }
+
+ return ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_fan_serv_init
+* PURPOSE:
+* initial fan servd
+* PARAMETERS:
+* mq_name (IN) message queue name
+* mq_desc (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_init(char *mq_name,
+ mqd_t *mq_desc)
+{
+ int ret_code = 0;
+
+ /* 1. record board type from CPLD */
+ if((ret_code = bms_fan_serv_fan_board_type_get(&bms_board_type)) < 0){
+ return ret_code;
+ }
+
+ /* 2. initial cache to maintain fan statue and type. */
+ if((ret_code = bms_fan_serv_cache_init()) < 0){
+ return ret_code;
+ }
+
+ /* 3. rename file path */
+ if((ret_code = bms_fan_serv_file_path_rename()) < 0){
+ return ret_code;
+ }
+
+ /* 4. enable all fan mask */
+ if((ret_code = bms_fan_serv_mask_init()) < 0)
+ return ret_code;
+
+ /* 5. open message queue */
+ if ((ret_code = bms_sys_serv_msq_open(mq_name, mq_desc)) < 0) {
+ return ret_code;
+ }
+
+ /* 6. default set PWM mode */
+ if ((ret_code = bms_fan_serv_pwm_init() < 0)) {
+ return ret_code;
+ }
+
+ /* 7. initial Mutexes */
+ if ((ret_code = bms_fan_serv_mutex_init() < 0)) {
+ return ret_code;
+ }
+
+ /* 8. set initial flag */
+ bms_fan_init_done = 1;
+
+ return ret_code;
+}
+
+
+/*
+ * FEATURE:
+ * bms_fan_serv_source_identify
+ * PURPOSE:
+ * identify interrupt source from absent or interrupt
+ * PARAMETERS:
+ * module_bmap (OUT) module bi map
+ * module_cause (OUT) module status
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_fan_serv_source_identify(unsigned int *module_bmap,
+ unsigned int *module_cause)
+{
+ unsigned int module_present_bmap, fan_intr;
+ unsigned int mask = 1;
+ unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM];
+ int ret_code = 0, i;
+
+ for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){
+ bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]);
+ }
+ /* Is fan interrupt, return bmap */
+ /* this i is fan number */
+ for(i = 0 ; i < BMS_FAN_MODULE_NUM * BMS_FAN_NUM_PER_MODULE; i++){
+ /* read from max31790, 0 for normal and 1 for failed */
+ if((ret_code = bms_fan_serv_fan_intr_get(i, &fan_intr)) < 0){
+ return ret_code;
+ }
+
+ if(((cache_status[i / BMS_FAN_NUM_PER_MODULE] == BMS_FAN_MODULE_STATUS_NORMAL) ||
+ (cache_status[i / BMS_FAN_NUM_PER_MODULE] == BMS_FAN_MODULE_STATUS_NONREADY))
+ && (fan_intr == BMS_FAN_INTR_FAULT)){
+ *module_bmap |= (mask << ((i / BMS_FAN_NUM_PER_MODULE)));
+ *module_cause = BMS_FAN_MODULE_STATUS_FAILED;
+ }
+ }
+
+ if(*module_bmap != 0){
+ return ret_code;
+ }
+
+ /* read fan module present from sysfs, 0 for present and 1 for non-present */
+ if((ret_code = bms_fan_serv_fan_present_get(&module_present_bmap)) < 0){
+ return ret_code;
+ }
+
+ /* Is module non-present, return module number, because we don't care non-present here. */
+ /* this i is fan module */
+ for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){
+ if((cache_status[i] == BMS_FAN_MODULE_STATUS_NORMAL) ||
+ (cache_status[i] == BMS_FAN_MODULE_STATUS_NONREADY) ||
+ (cache_status[i] == BMS_FAN_MODULE_STATUS_FAILED)){
+ if((module_present_bmap & mask)){
+ *module_bmap = i;
+ *module_cause = BMS_FAN_MODULE_STATUS_NONPRESENT;
+ return ret_code;
+ }
+ }
+ mask = mask << 1;
+ }
+
+ syslog(LOG_WARNING|LOG_USER,"Can't found fan interrupt source .\n");
+ return -EINVAL;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_cause_log
+* PURPOSE:
+* log of fan cause
+* PARAMETERS:
+* module_number (IN) module number
+* module_cause (IN) cause of fan module status
+* RETURNS:
+*/
+static void
+bms_fan_serv_cause_log(unsigned int module_number,
+ unsigned int module_cause)
+{
+ if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT)
+ syslog(LOG_DEBUG|LOG_USER,"The fan module %u was non present\n", module_number + 1);
+ else if(module_cause == BMS_FAN_MODULE_STATUS_FAILED)
+ syslog(LOG_WARNING|LOG_USER,"The fan module %u was fault\n", module_number + 1);
+ else if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL)
+ syslog(LOG_DEBUG|LOG_USER,"The fan module %u was present\n", module_number + 1);
+ else
+ syslog(LOG_WARNING|LOG_USER,"LOG error, unknown fan_cause in fan module %u\n", module_number + 1);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_intr_mask_set
+* PURPOSE:
+* set specific fan mask
+* PARAMETERS:
+* module_number (IN) module number
+* module_mask (IN) module mask
+* RETURNS:
+* success, this function returns zero.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_intr_mask_set(unsigned int module_number,
+ unsigned int module_mask)
+{
+ int ret_code = 0, i;
+
+ /* write to max31790, 0 for unmask and 1 for masked */
+ for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){
+ if((ret_code = bms_fan_serv_fan_mask_set((module_number * BMS_FAN_NUM_PER_MODULE) + i, module_mask)) < 0){
+ return ret_code;
+ }
+ }
+
+ return ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_fan_serv_find_serv_data_index
+* PURPOSE:
+* find index of fan of serv_data
+* PARAMETERS:
+
+* RETURNS:
+* success, this function returns value.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_find_serv_data_index(void)
+{
+ int i;
+ for(i = 0; i < bms_sys_serv_data_num; i++){
+ if(strcmp(bms_sys_serv_data[i].name, BMS_FAN_SERV_DATA_NAME) == 0)
+ return i;
+ }
+
+ syslog(LOG_WARNING|LOG_USER,"Can't find %s item index in bms_sys_serv_data\n", BMS_FAN_SERV_DATA_NAME);
+ return -EINVAL;
+}
+
+
+/*
+* FEATURE:
+* bms_fan_serv_global_mask_enable
+* PURPOSE:
+* enable fan global mask
+* PARAMETERS:
+
+* RETURNS:
+* success, this function returns zero.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_global_mask_enable(void)
+{
+ int ret_code = 0, index;
+
+ if((ret_code = bms_fan_serv_find_serv_data_index()) < 0)
+ return ret_code;
+
+ index = ret_code;
+ if((ret_code = bms_fan_serv_fan_global_mask_set(index, BMS_FAN_GLOBAL_INTR_UNMASKED)) < 0){
+ return ret_code;
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_board_type_comp
+* PURPOSE:
+* compare board tpye with fan type
+* PARAMETERS:
+* module_type (IN) module type
+* RETURNS:
+* success, compare the same return zero.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_board_type_comp(unsigned int module_type)
+{
+
+ if(((bms_board_type == BMS_AC_PSU_NORMAL_FAN) || (bms_board_type == BMS_DC_PSU_NORMAL_FAN)) &&
+ (module_type == BMS_FAN_MODULE_TYPE_NORMAL)){
+ return 0;
+ }
+
+ if(((bms_board_type == BMS_AC_PSU_REVERSE_FAN) || (bms_board_type == BMS_DC_PSU_REVERSE_FAN)) &&
+ (module_type == BMS_FAN_MODULE_TYPE_REVERSE)){
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_module_led_update
+* PURPOSE:
+* update fan module led
+* PARAMETERS:
+* module_number (IN) module number
+* module_cause (IN) cause of fan module event
+* module_type (IN) fan module type
+* RETURNS:
+* success, compare the same return zero.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_module_led_update(unsigned int module_number,
+ unsigned int module_cause,
+ unsigned int module_type)
+{
+ int ret_code = 0;
+ unsigned int cache_status, cache_type;
+
+ bms_fan_serv_cache_module_cache_get(module_number, &cache_status, &cache_type);
+
+ /* current fan module led status */
+ if(cache_status == BMS_FAN_MODULE_STATUS_NORMAL){
+ if(bms_fan_serv_board_type_comp(cache_type) == 0){
+ /* current fan module led is green */
+ if(module_cause == BMS_FAN_MODULE_STATUS_FAILED){
+ /* change fan module led to amber */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_AMBER)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }else if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT){
+ /* shutdown fan module led */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_OFF)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }else if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){
+ /* Do nothing */
+ return ret_code;
+ }
+ }else{
+ /* current fan module is amber */
+ if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT){
+ /* shutdown fan module led */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_OFF)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }else if(module_cause == BMS_FAN_MODULE_STATUS_FAILED){
+ /* Do nothing */
+ return ret_code;
+ }else if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){
+ if(bms_fan_serv_board_type_comp(module_type) == 0){
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_GREEN)) < 0){
+ return ret_code;
+ }
+ }else{
+ /* Do nothing */
+ return ret_code;
+ }
+ }
+ }
+ }else
+ if((cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT) ||
+ (cache_status == BMS_FAN_MODULE_STATUS_NONINIT) ||
+ (cache_status == BMS_FAN_MODULE_STATUS_NONREADY)){
+ /* current fan module is off */
+ if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){
+ if(bms_fan_serv_board_type_comp(module_type) == 0){
+ /* change fan module led to green */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_GREEN)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }else{
+ /* change fan module to amber */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_AMBER)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }
+ }else if(module_cause == BMS_FAN_MODULE_STATUS_FAILED){
+ /* change fan module led to amber */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_AMBER)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }else if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT){
+ /* Do nothing */
+ return ret_code;
+ }
+ }else
+ if(cache_status == BMS_FAN_MODULE_STATUS_FAILED){
+ /* current fan module led is amber */
+ /* mast be present the fan cause will be BMS_FAN_MODULE_STATUS_NORMAL */
+ if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){
+ if (bms_fan_serv_board_type_comp(module_type) == 0){
+ /* change fan module led to green */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_GREEN)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }else{
+ /* fan type was different from board type, current fan module led was amber, so do nothing */
+ return ret_code;
+ }
+ }else if((module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT)){
+ /* shutdown fan module led */
+ if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_OFF)) < 0){
+ return ret_code;
+ }
+ return ret_code;
+ }else if((module_cause == BMS_FAN_MODULE_STATUS_FAILED)){
+ /* Do nothing */
+ return ret_code;
+ }
+ }
+
+ syslog(LOG_WARNING|LOG_USER,"Error input different from cache.\n");
+ return -EINVAL;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_cache_update
+* PURPOSE:
+* update data to cache
+* PARAMETERS:
+* module_number (IN) module number
+* module_cause (IN) cause of fan module event
+* module_type (IN) fan module type
+* RETURNS:
+*/
+static void
+bms_fan_serv_cache_update(unsigned int module_number,
+ unsigned int module_cause,
+ unsigned int module_type)
+{
+ pthread_mutex_lock(&bms_fan_cache_lock);
+ bms_fan_status[module_number] = module_cause;
+
+ if((int)module_type != -1){
+ bms_fan_type[module_number] = module_type;
+ }
+ pthread_mutex_unlock(&bms_fan_cache_lock);
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_panel_led_by_cache_get
+* PURPOSE:
+* get panel led status from scan cache
+* PARAMETERS:
+*
+* RETURNS:
+* BMS_FAN_PANEL_LED_AMBER or BMS_FAN_PANEL_LED_GREEN
+*/
+static int
+bms_fan_serv_panel_led_by_cache_get(void)
+{
+ int i = 0;
+ unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM];
+
+ /* read value from cache */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]);
+ }
+
+ /* is cache have any non init status */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if(cache_status[i] == BMS_FAN_MODULE_STATUS_NONINIT){
+ return BMS_FAN_PANEL_LED_OFF;
+ }
+ }
+
+ /* is cache all normal and fan type the same with board type */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if((cache_status[i] != BMS_FAN_MODULE_STATUS_NORMAL) ||
+ (bms_fan_serv_board_type_comp(cache_type[i]) != 0)){
+ return BMS_FAN_PANEL_LED_AMBER;
+ }
+ }
+ return BMS_FAN_PANEL_LED_GREEN;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_panel_led_speed_normal_change
+* PURPOSE:
+* change panel fan led to green and fan speed to normal
+* PARAMETERS:
+*
+* RETURNS:
+* success, compare the same return zero.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_panel_led_speed_normal_change(void)
+{
+ int ret_code = 0, i;
+ unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM];
+ char buf[64];
+
+ /* read value from cache */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]);
+ }
+
+ if((ret_code = bms_fan_serv_fan_panel_led_set(BMS_FAN_PANEL_LED_GREEN)) < 0){
+ return ret_code;
+ }
+
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if(cache_status[i] == BMS_FAN_MODULE_STATUS_NONPRESENT)
+ continue;
+ if((ret_code = bms_fan_serv_fan_pwm_set(i, BMS_FAN_PWM_DUTY_CYCLE_NORMAL)) < 0){
+ return ret_code;
+ }
+ }
+
+ snprintf(buf, sizeof(buf),"%s start", bms_fan_serv_data[0].smart_fan_path);
+ system(buf);
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_panel_led_speed_failed_change
+* PURPOSE:
+* change panel fan led to amber and fan speed to max
+* PARAMETERS:
+*
+* RETURNS:
+* success, compare the same return zero.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_panel_led_speed_failed_change(void)
+{
+ int ret_code = 0, i;
+ unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM];
+ char buf[64];
+
+ /* read value from cache */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]);
+ }
+
+ if((ret_code = bms_fan_serv_fan_panel_led_set(BMS_FAN_PANEL_LED_AMBER)) < 0){
+ return ret_code;
+ }
+
+ snprintf(buf, sizeof(buf),"%s stop", bms_fan_serv_data[0].smart_fan_path);
+ system(buf);
+
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++){
+ if(cache_status[i] == BMS_FAN_MODULE_STATUS_NONPRESENT)
+ continue;
+ if((ret_code = bms_fan_serv_fan_pwm_set(i, BMS_FAN_PWM_DUTY_CYCLE_MAX)) < 0){
+ return ret_code;
+ }
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_cache_airflow_module_panel_led_update
+* PURPOSE:
+* update all fan cache, air flow, fan module and panel led
+* PARAMETERS:
+* module_number (IN) module number
+* module_cause (IN) cause of fan module event
+* module_type (IN) fan module type
+* RETURNS:
+* success, compare the same return zero.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_fan_serv_cache_airflow_module_panel_led_update(unsigned int module_number,
+ unsigned int module_cause,
+ unsigned int module_type)
+{
+ int ret_code = 0;
+ unsigned int pre_status, cur_status;
+ if((ret_code = bms_fan_serv_module_led_update(module_number, module_cause, module_type)) < 0)
+ return ret_code;
+
+ pre_status = bms_fan_serv_panel_led_by_cache_get();
+
+ bms_fan_serv_cache_update(module_number, module_cause, module_type);
+
+ cur_status = bms_fan_serv_panel_led_by_cache_get();
+
+
+ if(cur_status == pre_status)
+ return ret_code;
+ if(cur_status == BMS_FAN_PANEL_LED_GREEN){
+ if((ret_code = bms_fan_serv_panel_led_speed_normal_change()) < 0){
+ return ret_code;
+ }
+ }else{
+ if((ret_code = bms_fan_serv_panel_led_speed_failed_change()) < 0){
+ return ret_code;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_fan_serv_fan_failed_datect
+* PURPOSE:
+* detect fan failed cause
+* PARAMETERS:
+* module_number (IN) module number
+* module_status (OUT) cause of fan module status
+* success, compare the same return zero.
+* for other cases, negative errno is returned.
+*/
+int
+bms_fan_serv_fan_failed_datect(unsigned int module_number,
+ unsigned int *fan_status)
+{
+ unsigned int fan_intr, fan_input;
+ int ret_code, i;
+
+ /* fan failed datect */
+ /* read from max31790, 0 for normal and 1 for failed */
+ for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){
+ if((ret_code = bms_fan_serv_fan_intr_get((module_number * BMS_FAN_NUM_PER_MODULE) + i, &fan_intr)) < 0){
+ return ret_code;
+ }
+ if(fan_intr){
+ *fan_status = BMS_FAN_MODULE_STATUS_FAILED;
+ return ret_code;
+ }
+ }
+
+ /* detect fan speed */
+ for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){
+ if((ret_code = bms_fan_serv_fan_input_get((module_number * BMS_FAN_NUM_PER_MODULE) + i, &fan_input)) < 0){
+ return ret_code;
+ }
+
+ if(fan_input == BMS_FAN_MIN_FAN_SPEED){
+ *fan_status = BMS_FAN_MODULE_STATUS_FAILED;
+ return ret_code;
+ }
+ }
+
+ *fan_status = BMS_FAN_MODULE_STATUS_NORMAL;
+
+ return ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_fan_servd
+* PURPOSE:
+* service to handle message queue event of fan
+* PARAMETERS:
+* args (IN) message queue name
+* RETURNS:
+* open success, this function will wait for message queue.
+* for other cases, will exit this program.
+*/
+void*
+bms_fan_servd(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ bms_sys_serv_mq_data_t msg;
+ int ret_code;
+ unsigned int module_number, module_type;
+ unsigned int module_status;
+ unsigned int cache_status, cache_type;
+
+ /* initial */
+ if(bms_fan_serv_init(mq_name, &mq_desc) != 0)
+ goto quit;
+
+ while (1) {
+ /* Wait for message queue */
+ if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ switch (msg.serv_type) {
+ case SERV_TYPE_RX_INTR: /* FAN_ALERT_INT interrupt */
+ module_number = msg.number;
+
+ bms_fan_serv_cause_log(module_number, BMS_FAN_MODULE_STATUS_FAILED);
+
+ if(bms_fan_serv_cache_airflow_module_panel_led_update(module_number, BMS_FAN_MODULE_STATUS_FAILED, -1) < 0){
+ break;
+ }
+ break;
+
+ case SERV_TYPE_FAN_MODULE_PRESENT:
+ module_number = msg.number;
+ module_type = msg.type;
+
+ /* ignore wrong status */
+ bms_fan_serv_cache_module_cache_get(module_number, &cache_status, &cache_type);
+ if((cache_status != BMS_FAN_MODULE_STATUS_NONREADY) &&
+ (cache_status != BMS_FAN_MODULE_STATUS_NONINIT) &&
+ (cache_status != BMS_FAN_MODULE_STATUS_NONPRESENT)){
+ break;
+ }
+
+ if((cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT) ||
+ (cache_status == BMS_FAN_MODULE_STATUS_NONINIT)){
+ /* we assume fan module must failed when fan present */
+ module_status = BMS_FAN_MODULE_STATUS_FAILED;
+ }else{
+ if(bms_fan_serv_fan_failed_datect(module_number, &module_status) < 0){
+ break;
+ }
+ }
+
+ if(module_status == BMS_FAN_MODULE_STATUS_FAILED){
+ /* if fan present within 1 second, set fan status to non-ready */
+ bms_fan_serv_cache_update(module_number, BMS_FAN_MODULE_STATUS_NONREADY, module_type);
+ }else if(module_status == BMS_FAN_MODULE_STATUS_NORMAL){
+
+ bms_fan_serv_cause_log(module_number, BMS_FAN_MODULE_STATUS_NORMAL);
+ bms_fan_serv_cache_airflow_module_panel_led_update(module_number, BMS_FAN_MODULE_STATUS_NORMAL, module_type);
+
+ }
+
+ if((cache_status == BMS_FAN_MODULE_STATUS_NONINIT) ||
+ (cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT)){
+ if(bms_fan_serv_board_type_comp(module_type) < 0){
+ syslog(LOG_WARNING|LOG_USER,"The fan module %u type was wrong\n", module_number + 1);
+ }
+ }
+
+ break;
+ case SERV_TYPE_FAN_MODULE_NONPRESENT:
+ module_number = msg.number;
+
+ /* ignore wrong status */
+ bms_fan_serv_cache_module_cache_get(module_number, &cache_status, &cache_type);
+ if(cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT){
+ break;
+ }
+
+ /* clear retry cache */
+ bms_fan_serv_cache_module_cache_retry_set(module_number, BMS_FAN_NONREADY_RETRY_INIT);
+
+ if(cache_status != BMS_FAN_MODULE_STATUS_NONINIT){
+ bms_fan_serv_cause_log(module_number, BMS_FAN_MODULE_STATUS_NONPRESENT);
+ }
+ if(bms_fan_serv_cache_airflow_module_panel_led_update(module_number, BMS_FAN_MODULE_STATUS_NONPRESENT, -1) < 0)
+ break;
+
+ break;
+ default:
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name);
+ break;
+ }
+ }
+
+quit:
+ pthread_mutex_destroy(&bms_fan_cache_lock);
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.h
new file mode 100644
index 000000000000..7f1fdde5a21e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.h
@@ -0,0 +1,114 @@
+#ifndef __BMS_FAN_SERVD_H__
+#define __BMS_FAN_SERVD_H__
+
+#include "bms_irq_sysd.h"
+
+#define FAN_FILE_PATH_LEN 64
+
+typedef struct {
+ int number;
+ char *hwmon_path;
+ char intr_src[FAN_FILE_PATH_LEN];
+ char intr_msk[FAN_FILE_PATH_LEN];
+ char *tray_led;
+ char *type;
+ char *present;
+ char pwm[FAN_FILE_PATH_LEN];
+ char pwm_enable[FAN_FILE_PATH_LEN];
+ char input[FAN_FILE_PATH_LEN];
+ char *smart_fan_path;
+}bms_fan_serv_data_t;
+
+enum {
+ BMS_AC_PSU_NORMAL_FAN = 0,
+ BMS_AC_PSU_REVERSE_FAN,
+ BMS_DC_PSU_NORMAL_FAN,
+ BMS_DC_PSU_REVERSE_FAN,
+};
+
+enum {
+ BMS_FAN_MODULE_STATUS_NONINIT = 0,
+ BMS_FAN_MODULE_STATUS_NONREADY,
+ BMS_FAN_MODULE_STATUS_NORMAL,
+ BMS_FAN_MODULE_STATUS_NONPRESENT,
+ BMS_FAN_MODULE_STATUS_FAILED,
+};
+
+enum {
+ BMS_FAN_MODULE_TYPE_REVERSE = 0,
+ BMS_FAN_MODULE_TYPE_NORMAL,
+};
+
+enum {
+ BMS_FAN_INTR_UNMASKED = 0,
+ BMS_FAN_INTR_MASKED,
+};
+
+enum {
+ BMS_FAN_INTR_NORMAL = 0,
+ BMS_FAN_INTR_FAULT,
+};
+
+enum {
+ BMS_FAN_GLOBAL_INTR_MASKED = 0,
+ BMS_FAN_GLOBAL_INTR_UNMASKED,
+};
+
+enum {
+ BMS_FAN_MODULE_LED_OFF = 0,
+ BMS_FAN_MODULE_LED_GREEN,
+ BMS_FAN_MODULE_LED_AMBER,
+};
+
+enum {
+ BMS_FAN_PANEL_LED_OFF = 0,
+ BMS_FAN_PANEL_LED_AMBER,
+ BMS_FAN_PANEL_LED_GREEN,
+};
+
+enum {
+ BMS_FAN_PWM_ENABLE_OFF = 0,
+ BMS_FAN_PWM_ENABLE_PWM,
+ BMS_FAN_PWM_ENABLE_RPM
+};
+
+enum {
+ BMS_FAN_PWM_DUTY_CYCLE_NORMAL = 254,
+ BMS_FAN_PWM_DUTY_CYCLE_MAX = 255,
+};
+
+
+extern bms_sys_serv_data_t bms_sys_serv_data[];
+extern int bms_sys_serv_data_num;
+
+extern int bms_fan_init_done;
+extern void bms_fan_serv_fan_debug_cache_print(char * test);
+extern bms_fan_serv_data_t bms_fan_serv_data[];
+extern unsigned int bms_fan_status[];
+extern unsigned int bms_fan_type[];
+extern unsigned int bms_board_type;
+
+extern void bms_fan_serv_cache_module_cache_get(unsigned int module_number, unsigned int* module_status, unsigned int* module_type);
+extern int bms_fan_serv_fan_present_get(unsigned int *value);
+extern int bms_fan_serv_module_type_get(unsigned int module_number, unsigned int *value);
+extern void bms_fan_serv_cache_module_cache_retry_get(unsigned int module_number, unsigned int* module_retry);
+extern void bms_fan_serv_cache_module_cache_retry_set(unsigned int module_number, unsigned int value);
+extern int bms_fan_serv_fan_pwm_set(unsigned int module_number, unsigned int value);
+extern int bms_fan_serv_fan_input_get(unsigned int fan_number, unsigned int *value);
+extern int bms_fan_serv_fan_intr_get(unsigned int fan_number, unsigned int *value);
+
+
+#define BMS_SYSFS_FAN_PANEL_LED "/sys/bus/i2c/devices/1-0032/fan_led"
+#define BMS_FAN_NUM_PER_MODULE 2
+#define BMS_FAN_MODULE_NUM 6
+#define BMS_FAN_MIN_FAN_SPEED 480
+#define BMS_FAN_NONREADY_RETRY_INIT 0
+#define BMS_FAN_NONREADY_RETRY 3
+#define BMS_FAN_SERV_DATA_NAME "FAN"
+#define BMS_FAN_CONTROL_NUM 2
+
+/* fan message queue range define 100~199 */
+#define SERV_TYPE_FAN_MODULE_PRESENT 100
+#define SERV_TYPE_FAN_MODULE_NONPRESENT 101
+
+#endif /* __BMS_FAN_SERVD_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.c
new file mode 100644
index 000000000000..2f63dfa46212
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.c
@@ -0,0 +1,510 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_irq_sysd.c
+ *
+ * @purpose BMS irq system daemon
+ *
+ * @create 2017/3/16
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/16: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_irq_sysd.h"
+#include "bms_sys_serv_common.h"
+#include "bms_fan_servd.h"
+#include "bms_psu_servd.h"
+
+#define PROC_PRIORITY 90
+
+/* MIC_FEAT_SYS_INT : 1 means interrupt, 0 means polling */
+#define MIC_FEAT_SYS_INT 0
+
+
+
+#if (MIC_FEAT_SYS_INT)
+#include
+#include
+#include
+
+#define BMS_SYS_GPE_SYSFS "/sys/firmware/acpi/interrupts/gpe%.2X"
+#define BMS_SYS_GPE_SYSFS_CHAR_NUM 40 /* ex. /sys/firmware/acpi/interrupts/gpe01 */
+#define BMS_SYS_GPE_DISABLE 0
+#define BMS_SYS_GPE_INIT_SKIP 0xFF
+#define BMS_SYS_ACPID_SOCKET_SYSFS "/var/run/acpid.socket"
+#define BMS_SYS_GPE_INTR_TAG "bms_acpi PNP0C01:00 000000%.2X 00000000"
+#define BMS_SYS_GPE_INTR_TAG_CHAR_NUM 38 /* ex. bms_acpi PNP0C01:00 00000002 00000000 */
+#endif
+
+
+bms_sys_serv_data_t bms_sys_serv_data[] = {
+ {
+ .name = "VRHOT",
+ .intr_src = "/sys/bus/i2c/devices/1-0031/vrhot_irq",
+ .intr_msk = "/sys/bus/i2c/devices/1-0031/vrhot_irq_en",
+ .mq_name = "/sys_vrhot_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = bms_vrhot_servd,
+ .polld = NULL,
+ .intr_msk_default = !SYS_SERV_INTR_MASK_EN,
+ },
+ {
+ .name = "CPU_TEMP",
+ .intr_src = "/sys/bus/i2c/devices/1-0031/cpu_thermtrip_irq",
+ .intr_msk = "/sys/bus/i2c/devices/1-0031/cpu_thermtrip_irq_en",
+ .mq_name = "/sys_isr_cpu_thermtrip_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = bms_cpu_temp_servd,
+ .polld = NULL,
+ .intr_msk_default = !SYS_SERV_INTR_MASK_EN,
+ },
+ {
+ .name = "SYS_TEMP",
+ .intr_src = "/sys/bus/i2c/devices/1-0031/temp_alert_irq",
+ .intr_msk = "/sys/bus/i2c/devices/1-0031/temp_alert_irq_en",
+ .mq_name = "/sys_temp_alert_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = bms_sys_temp_servd,
+ .polld = NULL,
+ .intr_msk_default = !SYS_SERV_INTR_MASK_EN,
+ },
+ {
+ .name = "PS1",
+ .intr_src = "/sys/bus/i2c/devices/1-0032/ps1_int",
+ .intr_msk = "/sys/bus/i2c/devices/1-0032/ps1_int_msk",
+ .mq_name = "/sys_psu_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = bms_psu_servd,
+ .polld = bms_psu_polld,
+ .intr_msk_default = SYS_SERV_INTR_MASK_EN,/* detect by polling */
+ },
+ {
+ .name = "PS2",
+ .intr_src = "/sys/bus/i2c/devices/1-0032/ps2_int",
+ .intr_msk = "/sys/bus/i2c/devices/1-0032/ps2_int_msk",
+ .mq_name = "/sys_psu_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PSU1 */
+ .polld = NULL,
+ .intr_msk_default = SYS_SERV_INTR_MASK_EN,/* detect by polling */
+ },
+ {
+ .name = "USB",
+ .intr_src = "/sys/bus/i2c/devices/1-0032/usb_fault",
+ .intr_msk = "/sys/bus/i2c/devices/1-0032/usb_fault_msk",
+ .mq_name = "/sys_usb_fault_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = bms_usb_servd,
+ .polld = NULL,
+ .intr_msk_default = !SYS_SERV_INTR_MASK_EN,
+ },
+ {
+ .name = "PCIE",
+ .intr_src = "/sys/bus/i2c/devices/1-0032/pcie_int",
+ .intr_msk = "/sys/bus/i2c/devices/1-0032/pcie_int_msk",
+ .mq_name = "/sys_pcie_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = bms_pcie_servd,
+ .polld = NULL,
+ .intr_msk_default = SYS_SERV_INTR_MASK_EN,
+ },
+ {
+ .name = "FAN",
+ .intr_src = "/sys/bus/i2c/devices/1-0032/fan_alert_int",
+ .intr_msk = "/sys/bus/i2c/devices/1-0032/fan_alert_int_msk",
+ .mq_name = "/sys_fan_alert_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_irq_sys_isr,
+ .isrd = bms_fan_servd,
+ .polld = bms_fan_polld,
+ .intr_msk_default = SYS_SERV_INTR_MASK_EN,
+ },
+};
+
+int bms_sys_serv_data_num = sizeof(bms_sys_serv_data) / sizeof(bms_sys_serv_data[0]);
+
+/*
+* FEATURE:
+* bms_irq_sys_isr
+* PURPOSE:
+* Handle system interrupt routine
+* PARAMETERS:
+* name (IN) service name
+* qname (IN) message queue name
+* mq_desc (IN) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_irq_sys_isr(char *name,
+ char *qname,
+ mqd_t mq_desc)
+{
+ int ret_code = 0;
+ bms_sys_serv_mq_data_t msg;
+
+ msg.serv_type = SERV_TYPE_RX_INTR;
+ msg.serv_name = name;
+
+ if (mq_send(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ if (ret_code == EAGAIN) {
+ syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", qname);
+ }
+ else {
+ syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", qname, strerror(ret_code));
+ }
+ }
+
+ return -ret_code;
+}
+
+#if MIC_FEAT_SYS_INT == 1
+/*
+ * FEATURE:
+ * bms_gpe_event_write
+ * PURPOSE:
+ * set event to gpe
+ * PARAMETERS:
+ * gpe_num (IN) gpe number
+ * enable (IN) 1 means enable, 0 means disable, others set 0.
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_sys_serv_gpe_event_write(unsigned int gpe_num,
+ unsigned int enable)
+{
+ char buf[10], filename[BMS_SYS_GPE_SYSFS_CHAR_NUM] = { 0 };
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ snprintf(filename, sizeof(filename), BMS_SYS_GPE_SYSFS, gpe_num);
+ /* Open file */
+ if ((fd = open(filename, O_WRONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Write file */
+ if (enable == BMS_SYS_GPE_DISABLE) {
+ snprintf(buf, buf_size, "%s", "disable\n");
+ } else if (enable == !BMS_SYS_GPE_DISABLE) {
+ snprintf(buf, buf_size, "%s", "enable\n");
+ } else if (enable == BMS_SYS_GPE_INIT_SKIP) {
+ snprintf(buf, buf_size, "%s", "disable\n");
+ } else {
+ snprintf(buf, buf_size, "%d", 0);
+ }
+ if ((count = write(fd, buf, buf_size)) != (-1)) {;}
+ else if (enable == BMS_SYS_GPE_INIT_SKIP) {;}
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+#endif
+
+
+/*
+* FEATURE:
+* bms_irq_sys_msq_create
+* PURPOSE:
+* Create message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_irq_sys_msq_create(char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_CREAT | O_EXCL | O_WRONLY | O_NONBLOCK), ret_code = 0, i;
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+ struct mq_attr attr = {
+ .mq_maxmsg = 64,
+ .mq_msgsize = sizeof(bms_sys_serv_mq_data_t),
+ };
+
+ /* Check others item had the same qname that already created */
+ for(i = 0; i < bms_sys_serv_data_num; i++){
+ if(bms_sys_serv_data[i].mq_name){
+ if(strcmp(bms_sys_serv_data[i].mq_name, qname) == 0){
+ if(bms_sys_serv_data[i].mq_desc != (mqd_t)-1){
+ *mqd = bms_sys_serv_data[i].mq_desc;
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* destroy message queue if it presents */
+ if ((mq_unlink(qname) < 0) && (errno != ENOENT)) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to destroy message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags, mode, &attr)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to create message queue %s (%s)\n", qname, strerror(ret_code));
+ return -ret_code;
+ }
+
+ syslog(LOG_DEBUG|LOG_USER,"Create message queue %s\n", qname);
+
+ return -ret_code;
+}
+
+/*
+* FEATURE:
+* bms_irq_sys_terminator
+* PURPOSE:
+* Do someting when terminator flag coming
+* PARAMETERS:
+* sig (IN) signal
+* RETURNS:
+*/
+void
+bms_irq_sys_terminator(int sig)
+{
+ int i;
+ if (sig) {;}
+
+ for (i = 0; i < bms_sys_serv_data_num; i++) {
+ /* Disable interrupt function */
+ bms_sys_serv_write(bms_sys_serv_data[i].intr_msk, SYS_SERV_INTR_MASK_EN);
+
+ /* destroy message queue */
+ mq_unlink(bms_sys_serv_data[i].mq_name);
+ }
+
+ syslog(LOG_DEBUG|LOG_USER,"Terminate %s\n", __FILE__);
+
+ exit(0);
+}
+
+
+
+/*
+* FEATURE:
+* main
+* PURPOSE:
+* main start
+* PARAMETERS:
+*
+* RETURNS:
+*/
+int
+main(void)
+{
+ int i, value = 0, ret_code = 0;
+ struct sched_param sched_param = {.sched_priority = PROC_PRIORITY};
+ pthread_attr_t attr;
+
+#if(MIC_FEAT_SYS_INT)
+ int socket_dsc = 0;
+ struct sockaddr_un socket_addr;
+ char buf[BMS_SYS_GPE_INTR_TAG_CHAR_NUM],gpe_tag[BMS_SYS_GPE_INTR_TAG_CHAR_NUM];
+ unsigned int gpe_num = 0x1;
+ int unknow_interrupt = 1;
+#else
+ int mask;
+#endif
+
+ /* Set priority and make it be real-time */
+ nice(-1);
+ sched_setscheduler(0, SCHED_FIFO, &sched_param);
+
+ /* Make the process be a background daemon */
+ daemon(0 /* change working directory to root */,
+ 0 /* redirect stdin, stdout, and stderr to /dev/null */);
+
+ /* Register handler for termination */
+ signal(SIGTERM, bms_irq_sys_terminator);
+
+ /* Create message queue for each interrupt service routine (ISR) */
+ for (i = 0; i < bms_sys_serv_data_num; i++) {
+ if (bms_sys_serv_data[i].mq_name) {
+ if ((ret_code = bms_irq_sys_msq_create(bms_sys_serv_data[i].mq_name, &bms_sys_serv_data[i].mq_desc)) < 0) {
+ goto quit;
+ }
+ }
+ }
+
+ /* Enable Interrupt function */
+ for (i = 0; i < bms_sys_serv_data_num; i++) {
+ if((ret_code = bms_sys_serv_write(bms_sys_serv_data[i].intr_msk, bms_sys_serv_data[i].intr_msk_default)) < 0) {
+ goto quit;
+ }
+ }
+
+ /* Disable fan module led */
+ for(i = 0; i < BMS_FAN_MODULE_NUM; i++ ){
+ if((ret_code = bms_sys_serv_write(bms_fan_serv_data[i * BMS_FAN_NUM_PER_MODULE].tray_led, BMS_FAN_MODULE_LED_OFF)) < 0) {
+ goto quit;
+ }
+ }
+
+ /* Disable panel fan led */
+ if((ret_code = bms_sys_serv_write(BMS_SYSFS_FAN_PANEL_LED, BMS_FAN_PANEL_LED_OFF)) < 0) {
+ goto quit;
+ }
+
+
+ /* Spawn interrupt service routine (ISR) daemon */
+ for (i = 0; i < bms_sys_serv_data_num; i++) {
+ if (bms_sys_serv_data[i].isrd) {
+ pthread_attr_init(&attr);
+ pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+ pthread_attr_setschedparam(&attr, &sched_param);
+ if (pthread_create(&bms_sys_serv_data[i].isrd_tid, &attr, bms_sys_serv_data[i].isrd, (void*)bms_sys_serv_data[i].mq_name) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to create pthread (%s)\n", strerror(ret_code));
+ goto quit;
+ }
+ }
+ if (bms_sys_serv_data[i].polld) {
+ pthread_attr_init(&attr);
+ pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+ pthread_attr_setschedparam(&attr, &sched_param);
+ if (pthread_create(&bms_sys_serv_data[i].polld_tid, &attr, bms_sys_serv_data[i].polld, (void*)bms_sys_serv_data[i].mq_name) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to create pthread (%s)\n", strerror(ret_code));
+ goto quit;
+ }
+ }
+ }
+
+#if(MIC_FEAT_SYS_INT)
+ snprintf(gpe_tag, sizeof(gpe_tag), BMS_SYS_GPE_INTR_TAG, gpe_num);
+ /* set default value for GPE status */
+ bms_sys_serv_gpe_event_write(gpe_num, BMS_SYS_GPE_INIT_SKIP);
+
+ /* 3. Open the acpi socket. */
+ if ((socket_dsc = socket(AF_UNIX, SOCK_STREAM, 0)) == (-1)) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code));
+ goto quit;
+ }
+ socket_addr.sun_family = AF_UNIX;
+ strcpy(socket_addr.sun_path, BMS_SYS_ACPID_SOCKET_SYSFS);
+ if (connect(socket_dsc, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) == (-1)) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to connect ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code));
+
+ }
+#endif
+
+
+ while (1) {
+#if(MIC_FEAT_SYS_INT)
+ unknow_interrupt = 1;
+ /* 3. Enable IRQ */
+ if((ret_code = bms_sys_serv_gpe_event_write(gpe_num, !BMS_SYS_GPE_DISABLE)) < 0)
+ goto quit;
+
+ /* Wait for interrupt occurs; this is a blocking call and may leave
+ * the blocking state unexpectly while receiving a signal. In such
+ * a case, we go back to wait for the arriving of interrupt.
+ */
+
+wait_irq:
+ memset(buf,0,sizeof(buf));
+ if (recv(socket_dsc, buf, sizeof(buf), 0) <= 0) {
+ if (errno == EINTR) {goto wait_irq;}
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code));
+ goto quit;
+ }
+ if (!strncmp(buf, gpe_tag, sizeof(gpe_tag)-1)) {
+ /* Due to bms_gpe hanlder does not set disable now. */
+ if((ret_code = bms_sys_serv_gpe_event_write(gpe_num, BMS_SYS_GPE_DISABLE)) < 0)
+ goto quit;
+ } else {
+ goto wait_irq;
+ }
+#endif
+
+ /* Probe all interrupt sources */
+ for (i = 0; i < bms_sys_serv_data_num; i++) {
+ /* Detect which source(s) trigger the interrupt. 0 is assert, 1 is not assert */
+ if ((ret_code = bms_sys_serv_hex_read(bms_sys_serv_data[i].intr_src, (unsigned int*)&value)) < 0) {
+ goto quit;
+ }
+
+#if(MIC_FEAT_SYS_INT)
+ if (value != SYS_SERV_INTR_STATUS_EN)
+ continue;
+#else
+ /* 0 is masked, 1 is not mask */
+ if ((ret_code = bms_sys_serv_hex_read(bms_sys_serv_data[i].intr_msk, (unsigned int*)&mask)) < 0) {
+ goto quit;
+ }
+
+ if((value != SYS_SERV_INTR_STATUS_EN) || (mask != (!SYS_SERV_INTR_MASK_EN)))
+ continue;
+#endif
+
+ /* Disable the source that triggers the interrupt */
+ if ((ret_code = bms_sys_serv_write(bms_sys_serv_data[i].intr_msk, SYS_SERV_INTR_MASK_EN)) < 0) {
+ goto quit;
+ }
+
+ /* Call interrupt service routine (ISR) */
+ syslog(LOG_DEBUG|LOG_USER,"%s interrupt arrivals\n", bms_sys_serv_data[i].name);
+ bms_sys_serv_data[i].isr(bms_sys_serv_data[i].name, bms_sys_serv_data[i].mq_name, bms_sys_serv_data[i].mq_desc);
+#if(MIC_FEAT_SYS_INT)
+ unknow_interrupt = 0;
+#endif
+ }
+#if(MIC_FEAT_SYS_INT)
+ /* Log unknown interrupt */
+ if (unknow_interrupt) {
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown interrupt from system interrput\n");
+ }
+#else
+ sleep(2);
+#endif
+
+ }
+
+quit:
+ syslog(LOG_DEBUG|LOG_USER,"Quit daemon %s\n", __FILE__);
+ exit(ret_code);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.h
new file mode 100644
index 000000000000..637a7625a7f6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.h
@@ -0,0 +1,43 @@
+#ifndef __BMS_IRQ_SYSD_H__
+#define __BMS_IRQ_SYSD_H__
+
+#define SYS_SERV_INTR_STATUS_EN 0
+#define SYS_SERV_INTR_MASK_EN 0
+
+typedef int (*isr_t)(char *, char *, mqd_t);
+typedef void* (*isrd_t)(void*);
+
+typedef struct {
+ char *name;
+ char *intr_src;
+ char *intr_msk;
+ char *mq_name;
+ mqd_t mq_desc;
+ isr_t isr;
+ pthread_t isrd_tid;
+ isrd_t isrd;
+ pthread_t polld_tid;
+ isrd_t polld;
+ unsigned int intr_msk_default;
+} bms_sys_serv_data_t;
+
+typedef struct {
+ unsigned char serv_type;
+#define SERV_TYPE_RX_INTR 1 /* Receving an interrupt */
+ char *serv_name; /* service name */
+ unsigned int number;
+ unsigned int type;
+ unsigned int cause;
+} bms_sys_serv_mq_data_t;
+
+extern void* bms_vrhot_servd(void *args);
+extern void* bms_cpu_temp_servd(void *args);
+extern void* bms_sys_temp_servd(void *args);
+extern void* bms_psu_servd(void *args);
+extern void* bms_usb_servd(void *args);
+extern void* bms_pcie_servd(void *args);
+extern void* bms_fan_servd(void *args);
+extern void* bms_fan_polld(void *args);
+extern int bms_irq_sys_isr(char *name, char *qname, mqd_t mq_desc);
+extern void* bms_psu_polld(void *args);
+#endif /* __BMS_IRQ_SYSD_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_pcie_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_pcie_servd.c
new file mode 100644
index 000000000000..7a56d91733ec
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_pcie_servd.c
@@ -0,0 +1,106 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_pcie_servd.c
+ *
+ * @purpose BMS pcie service daemon
+ *
+ * @create 2017/3/17
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_irq_sysd.h"
+
+#include
+
+
+/*
+* FEATURE:
+* bms_pcie_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_pcie_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_RDONLY), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+/*
+* FEATURE:
+* bms_pcie_servd
+* PURPOSE:
+* service to handle message queue event of pcie
+* PARAMETERS:
+* args (IN) message queue name
+* RETURNS:
+* open success, this function will wait for message queue.
+* for other cases, will exit this program.
+*/
+void*
+bms_pcie_servd(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ bms_sys_serv_mq_data_t msg;
+ int ret_code;
+
+ /* Open message queue */
+ if (bms_pcie_msq_open(mq_name, &mq_desc) < 0) {
+ goto quit;
+ }
+
+ while (1) {
+ /* Wait for message queue */
+ if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ switch (msg.serv_type) {
+ case SERV_TYPE_RX_INTR: /* PCIE_INT interrupt */
+ syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name);
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name);
+ break;
+ }
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_polld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_polld.c
new file mode 100644
index 000000000000..5f15e4d5c00c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_polld.c
@@ -0,0 +1,310 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_psu_servd.h"
+#include "bms_sys_serv_common.h"
+
+
+/*
+* FEATURE:
+* bms_psu_poll_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_poll_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_WRONLY | O_NONBLOCK), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_poll_init
+* PURPOSE:
+* initial all
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_poll_init(char *mq_name,
+ mqd_t *mq_desc)
+{
+ int ret_code = 0;
+
+ /* open message queue*/
+ if ((ret_code = bms_psu_poll_msq_open(mq_name, mq_desc)) < 0) {
+ return ret_code;
+ }
+
+ return ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_poll_detect_psu_status
+* PURPOSE:
+* datect psu status is present or non present
+* PARAMETERS:
+* present_bmap (OUT) pointer of present bmap
+* nonpresent_bmap (OUT) pointer of non-present bmap
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_poll_detect_module_status(unsigned int *present_pg_bmap,
+ unsigned int *present_bmap,
+ unsigned int *nonpresent_bmap,
+ unsigned int *intr_table,
+ unsigned int *intr_recovery_table)
+{
+ int ret_code = 0, i;
+ unsigned int ps_pg_status;
+ unsigned int cache_status[BMS_PSU_NUM], cache_type[BMS_PSU_NUM],psu_present[BMS_PSU_NUM], psu_power_good[BMS_PSU_NUM];
+ unsigned int intr_status[BMS_PSU_NUM * BMS_PSU_INTR_NUM], intr_cache[BMS_PSU_NUM * BMS_PSU_INTR_NUM];
+
+ memset(intr_status, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM);
+ memset(intr_cache, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM);
+
+ /* read pg */
+ if((ret_code = bms_psu_serv_power_status_get(&ps_pg_status)) < 0) {
+ return ret_code;
+ }
+
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ bms_psu_serv_cache_get(i, &cache_status[i], &cache_type[i]);
+ psu_present[i] = ((ps_pg_status & (1 << (bms_psu_serv_data[i].ps_offset))) > 0) ? BMS_PSU_PS_NONPRESENT : BMS_PSU_PS_PRESENT;
+ psu_power_good[i] = ((ps_pg_status & (1 << (bms_psu_serv_data[i].pg_offset))) > 0) ? BMS_PSU_PG_FAILED : BMS_PSU_PG_GOOD;
+ }
+
+ /* read interrupt cache */
+ bms_psu_serv_intr_cache_get(intr_cache);
+
+ /* read interrupt from file system */
+ for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++){
+ if((cache_status[i / BMS_PSU_INTR_NUM] != BMS_PSU_STATUS_NORMAL) &&
+ (cache_status[i / BMS_PSU_INTR_NUM] != BMS_PSU_STATUS_FAULT)) {
+ continue;
+ }
+ if((ret_code = bms_sys_serv_dec_read(bms_psu_serv_data[i / BMS_PSU_INTR_NUM].intr_src[i % BMS_PSU_INTR_NUM], &intr_status[i])) < 0){
+ return ret_code;
+ }
+ }
+
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ if(cache_status[i] == BMS_PSU_STATUS_ABSENT) {
+ if(psu_present[i] == BMS_PSU_PS_PRESENT) {
+ /* case 1 current status is absent, and have a psu plug in */
+ *present_bmap |= (1 << i);
+ }
+ continue;
+ }
+
+ if(cache_status[i] == BMS_PSU_STATUS_PRESENT) {
+ if(psu_present[i] == BMS_PSU_PS_PRESENT) {
+ if(psu_power_good[i] == BMS_PSU_PG_GOOD) {
+ /* case 2 current status is present, and detect power good now */
+ *present_pg_bmap |= (1 << i);
+ }
+ }else
+ if(psu_present[i] == BMS_PSU_PS_NONPRESENT) {
+ /* case 3 current status is is present, and detect non present */
+ *nonpresent_bmap |= (1 << i);
+ }
+ continue;
+ }
+
+ if((cache_status[i] == BMS_PSU_STATUS_NORMAL) ||
+ (cache_status[i] == BMS_PSU_STATUS_FAULT)) {
+ if(psu_present[i] == BMS_PSU_PS_NONPRESENT) {
+ /* case 4 current status is is normal or fault, and detect non present */
+ *nonpresent_bmap |= (1 << i);
+ }else
+ if(psu_present[i] == BMS_PSU_PS_PRESENT) {
+ if(psu_power_good[i] == BMS_PSU_PG_FAILED) {
+ /* case 5 current status is is normal or fault, and detect non power good */
+ *present_bmap |= (1 << i);
+ }
+ }
+ continue;
+ }
+
+ syslog(LOG_DEBUG|LOG_USER,"[%s] Unknown cache status %u and present status %u\n", __FUNCTION__, cache_status[i], psu_present[i]);
+
+ }
+
+ for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++){
+ if(intr_status[i] == intr_cache[i])
+ continue;
+
+ if(psu_power_good[i / BMS_PSU_INTR_NUM] == BMS_PSU_PG_FAILED){
+ continue;
+ }
+
+ if(intr_status[i] == BMS_PSU_SOURCE_INTR_ASSERTED){
+ intr_table[i] = 1;
+ }
+ else{
+ intr_recovery_table[i] = 1;
+ }
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_psu_poll_msq_send
+* PURPOSE:
+* send POSIX message queue
+* PARAMETERS:
+* msg (IN) message of send data
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_poll_msq_send(bms_sys_serv_mq_data_t* msg,
+ mqd_t *mqd)
+{
+ int ret_code;
+
+ if (mq_send(*mqd, (char*)msg, sizeof(*msg), 0) < 0) {
+ ret_code = errno;
+ if (ret_code == EAGAIN) {
+ syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", msg->serv_name);
+ }
+ else {
+ syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", msg->serv_name, strerror(ret_code));
+ }
+ }
+
+ return -ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_polld
+* PURPOSE:
+* bms psu polling daemon
+* PARAMETERS:
+* args (IN) input value(message name)
+* RETURNS:
+* The process will always polling psu module.
+*/
+void*
+bms_psu_polld(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ int ret_code = 0, i;
+
+ bms_sys_serv_mq_data_t msg;
+ unsigned int present_pg_bmap = 0, nonpresent_bmap = 0;
+ unsigned int present_bmap = 0;
+ unsigned int intr_table[BMS_PSU_NUM * BMS_PSU_INTR_NUM], intr_recovery_table[BMS_PSU_NUM * BMS_PSU_INTR_NUM];
+
+ msg.serv_name = mq_name;
+
+ if((ret_code = bms_psu_poll_init(mq_name, &mq_desc)) < 0) {
+ goto quit;
+ }
+
+ while(!bms_psu_init_done) {
+ sleep(1);
+ }
+
+ while(1) {
+ present_pg_bmap = 0;
+ nonpresent_bmap = 0;
+ present_bmap = 0;
+ memset(intr_table, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM);
+ memset(intr_recovery_table, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM);
+
+ if((ret_code = bms_psu_poll_detect_module_status(&present_pg_bmap, &present_bmap,
+ &nonpresent_bmap, intr_table, intr_recovery_table)) < 0) {
+ goto wait;
+ }
+
+
+ if(present_pg_bmap != 0) {
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ if(present_pg_bmap & (1 << i)) {
+ msg.serv_type = SERV_TYPE_PSU_NORMAL;
+ msg.number = i;
+ bms_psu_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+ }
+
+ if(present_bmap != 0) {
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ if(present_bmap & (1 << i)) {
+ msg.serv_type = SERV_TYPE_PSU_PRESENT;
+ msg.number = i;
+ bms_psu_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+ }
+
+ if(nonpresent_bmap != 0) {
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ if(nonpresent_bmap & (1 << i)) {
+ msg.serv_type = SERV_TYPE_PSU_ABSENT;
+ msg.number = i;
+ bms_psu_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+ }
+
+ for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++) {
+ if(intr_table[i] == 1) {
+ msg.serv_type = SERV_TYPE_RX_INTR;
+ msg.number = i / BMS_PSU_INTR_NUM;
+ msg.cause = i % BMS_PSU_INTR_NUM;
+ bms_psu_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+
+ for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++) {
+ if(intr_recovery_table[i] == 1) {
+ msg.serv_type = SERV_TYPE_PSU_INTR_RECOVERY;
+ msg.number = i / BMS_PSU_INTR_NUM;
+ msg.cause = i % BMS_PSU_INTR_NUM;
+ bms_psu_poll_msq_send(&msg, &mq_desc);
+ }
+ }
+
+wait:
+ sleep(1);
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.c
new file mode 100644
index 000000000000..36e600921269
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.c
@@ -0,0 +1,1044 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_psu_servd.c
+ *
+ * @purpose BMS psu service daemon
+ *
+ * @create 2017/3/17
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_irq_sysd.h"
+#include "bms_sys_serv_common.h"
+#include "bms_psu_servd.h"
+
+bms_psu_serv_data_t bms_psu_serv_data[BMS_PSU_NUM] = {
+ {
+ .name = "PS1",
+ .i2c_path = "/sys/bus/i2c/devices/i2c-5/new_device",
+ .driver_name = "fse000",
+ .pg_offset = 6,
+ .ps_offset = 7,
+ .address = 0x58,
+ .pg_ps_reg = "/sys/bus/i2c/devices/1-0032/psu_en_status_fld",
+ .model_reg = "mfr_model",
+ .hwmon_path = "/sys/bus/i2c/devices/5-0058/hwmon",
+ .intr_src = {
+ "vout_ov_fault",
+ "vout_uv_fault",
+ "curr2_crit_alarm",
+ "curr2_max_alarm",
+ "ot_fault",
+ "ot_warning",
+ "vin_uv_warning",
+ "vin_uv_fault",
+ "fan1_fault",
+ "fan1_alarm",
+ },
+ },
+ {
+ .name = "PS2",
+ .i2c_path = NULL, /* share with ps1 i2c_path */
+ .driver_name = NULL, /* share with ps1 driver_name */
+ .pg_offset = 2,
+ .ps_offset = 3,
+ .address = 0x59,
+ .pg_ps_reg = NULL, /* share with ps1 pg_ps_reg */
+ .model_reg = "mfr_model",
+ .hwmon_path = "/sys/bus/i2c/devices/5-0059/hwmon",
+ .intr_src = {
+ "vout_ov_fault",
+ "vout_uv_fault",
+ "curr2_crit_alarm",
+ "curr2_max_alarm",
+ "ot_fault",
+ "ot_warning",
+ "vin_uv_warning",
+ "vin_uv_fault",
+ "fan1_fault",
+ "fan1_alarm",
+ },
+ },
+};
+
+char *bms_psu_mfr_model[] = {
+ "FSE047-180G",
+ "FSE048-180G",
+ "FSE050-180G",
+ "FSE049-180G"
+};
+
+unsigned int bms_psu_board_type;
+unsigned int bms_psu_status[BMS_PSU_NUM];
+unsigned int bms_psu_type[BMS_PSU_NUM];
+unsigned int bms_psu_driver_init[BMS_PSU_NUM] = {0};
+unsigned int bms_psu_init_done = 0;
+unsigned int bms_psu_intr_cache[BMS_PSU_NUM * BMS_PSU_INTR_NUM] = {0};
+pthread_mutex_t bms_psu_st_cache_lock;
+pthread_mutex_t bms_psu_intr_cache_lock;
+
+/*
+* FEATURE:
+* bms_psu_serv_power_status_get
+* PURPOSE:
+* psu service psu status get from file system
+* PARAMETERS:
+* psu_number (IN) psu number
+* value (OUT) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_serv_power_status_get(unsigned int *value)
+{
+ return bms_sys_serv_hex_read(bms_psu_serv_data[0].pg_ps_reg, value);
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_type_get
+* PURPOSE:
+* psu service psu type get from file system
+* PARAMETERS:
+* psu_number (IN) psu number
+* value (OUT) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_serv_type_get(unsigned int psu_number,
+ unsigned int *value)
+{
+ int ret_code, i, type_num;
+ char buf[32] = {0};
+
+ /* size of type number */
+ type_num = sizeof(bms_psu_mfr_model) / sizeof(bms_psu_mfr_model[0]);
+
+ if((ret_code = bms_sys_serv_char_read(bms_psu_serv_data[psu_number].model_reg, buf)) < 0)
+ return ret_code;
+
+ for(i = 0; i < type_num; i++) {
+ if(strncmp(bms_psu_mfr_model[i], buf, strlen(bms_psu_mfr_model[i])) == 0) {
+ break;
+ }
+ }
+
+ if(i == type_num) {
+ syslog(LOG_WARNING|LOG_USER,"[%s] can't find type data", __FUNCTION__);
+ return -EINVAL;
+ }else{
+ *value = i;
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_board_type_get
+* PURPOSE:
+* psu service board get from file system
+* PARAMETERS:
+* value (OUT) pointer of get value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_serv_board_type_get(unsigned int *value)
+{
+ return bms_sys_serv_hex_read(BMS_SYSFS_BOARD_TYPE, value);
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_cache_update
+* PURPOSE:
+* update data to cache
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_cause (IN) cause of psu event
+* psu_type (IN) psu type
+* RETURNS:
+*/
+static void
+bms_psu_serv_cache_update(unsigned int psu_number,
+ unsigned int psu_cause,
+ unsigned int psu_type)
+{
+ pthread_mutex_lock(&bms_psu_st_cache_lock);
+ bms_psu_status[psu_number] = psu_cause;
+
+ if((int)psu_type != (-1)) {
+ bms_psu_type[psu_number] = psu_type;
+ }
+ pthread_mutex_unlock(&bms_psu_st_cache_lock);
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_cache_init
+* PURPOSE:
+* initial psu status and psu type
+* PARAMETERS:
+*
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static void
+bms_psu_serv_cache_init(void)
+{
+ int i;
+
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ bms_psu_serv_cache_update(i, BMS_PSU_STATUS_ABSENT, bms_psu_board_type);
+ }
+ memset(bms_psu_intr_cache, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM);
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_power_led_set
+* PURPOSE:
+* psu service power led set to file system in CPLD
+* PARAMETERS:
+* value (IN) setting value
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_serv_power_led_set(unsigned int value)
+{
+ return bms_sys_serv_write(BMS_SYSFS_POWER_LED, value);
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_mutex_init
+* PURPOSE:
+* initial mutex
+* PARAMETERS:
+*
+* RETURNS:
+* init success, this function shall return zero.
+* otherwise, an error number shall be returned to indicate the error.
+*/
+static int
+bms_psu_serv_mutex_init(void)
+{
+ int ret_code;
+
+ if((ret_code = pthread_mutex_init(&bms_psu_st_cache_lock, NULL)) != 0) {
+ return -ret_code;
+ }
+
+ if((ret_code = pthread_mutex_init(&bms_psu_intr_cache_lock, NULL)) != 0) {
+ return -ret_code;
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_file_path_rename
+* PURPOSE:
+* psu hwmon path rename
+* PARAMETERS:
+*
+* RETURNS:
+* init success, this function shall return zero.
+* otherwise, an error number shall be returned to indicate the error.
+*/
+int
+bms_psu_serv_file_path_rename(unsigned int psu_number)
+{
+ int ret_code = 0;
+ unsigned int i;
+
+ for(i = psu_number * BMS_PSU_INTR_NUM; i < ((BMS_PSU_INTR_NUM * psu_number) + BMS_PSU_INTR_NUM); i++){
+ if(bms_psu_driver_init[i / BMS_PSU_INTR_NUM] == BMS_PSU_DRIVER_UNINIT)
+ continue;
+ if((ret_code = bms_sys_serv_hwmon_path_find(bms_psu_serv_data[i / BMS_PSU_INTR_NUM].hwmon_path,
+ bms_psu_serv_data[i / BMS_PSU_INTR_NUM].intr_src[i % BMS_PSU_INTR_NUM])) < 0){
+ return -ret_code;
+ }
+ }
+
+ if(bms_psu_driver_init[psu_number] == BMS_PSU_DRIVER_INIT_DONE){
+ if((ret_code = bms_sys_serv_hwmon_path_find(bms_psu_serv_data[psu_number].hwmon_path,
+ bms_psu_serv_data[psu_number].model_reg)) < 0){
+ return -ret_code;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_driver_plugin
+* PURPOSE:
+* plug in driver to create sysfs
+* PARAMETERS:
+*
+* RETURNS:
+* init success, this function shall return zero.
+* otherwise, an error number shall be returned to indicate the error.
+*/
+int
+bms_psu_serv_driver_plugin(int psu_number)
+{
+ char buf[64];
+ int buf_size = sizeof(buf);
+ int ret_code = 0;
+
+ if(bms_sys_serv_file_exist(bms_psu_serv_data[psu_number].hwmon_path) == 1){
+ /* hwmon path not exist*/
+
+ /* echo driver to create sysfs */
+ snprintf(buf, buf_size, "%s %d",bms_psu_serv_data[0].driver_name, bms_psu_serv_data[psu_number].address);//
+ if((ret_code = bms_sys_serv_buf_write(bms_psu_serv_data[0].i2c_path, buf, buf_size)) < 0)
+ return ret_code;
+ }
+ bms_psu_driver_init[psu_number] = BMS_PSU_DRIVER_INIT_DONE;
+
+ if ((ret_code = bms_psu_serv_file_path_rename(psu_number)) < 0) {
+ return ret_code;
+ }
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_driver_init
+* PURPOSE:
+* Initial sysfs and rename path of sysfs
+* PARAMETERS:
+*
+* RETURNS:
+* init success, this function shall return zero.
+* otherwise, an error number shall be returned to indicate the error.
+*/
+static int
+bms_psu_serv_driver_init(void)
+{
+ int ret_code = 0;
+ unsigned int psu_ps_pg = 0, i;
+
+ if((ret_code = bms_sys_serv_hex_read(bms_psu_serv_data[0].pg_ps_reg, &psu_ps_pg)) < 0)
+ return ret_code;
+
+ for(i = 0; i < BMS_PSU_NUM ; i++){
+ if((psu_ps_pg & (1 << bms_psu_serv_data[i].pg_offset)) == BMS_PSU_PG_GOOD){
+ if((ret_code = bms_psu_serv_driver_plugin(i)) < 0)
+ return ret_code;
+ }
+ }
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_init
+* PURPOSE:
+* initial psu servd
+* PARAMETERS:
+* mq_name (IN) message queue name
+* mq_desc (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_psu_serv_init(char *mq_name,
+ mqd_t *mq_desc)
+{
+ int ret_code = 0;
+
+ /* 1 init pmbus to create sysfs */
+ if((ret_code = bms_psu_serv_driver_init()) < 0) {
+ return ret_code;
+ }
+
+ /* 2. record board type from CPLD */
+ if((ret_code = bms_psu_serv_board_type_get(&bms_psu_board_type)) < 0) {
+ return ret_code;
+ }
+
+ /* 3. initial cache to maintain psu statue and type. */
+ bms_psu_serv_cache_init();
+
+ /* 4. open message queue */
+ if ((ret_code = bms_sys_serv_msq_open(mq_name, mq_desc)) < 0) {
+ return ret_code;
+ }
+
+ /* 5. initial Mutexes */
+ if ((ret_code = bms_psu_serv_mutex_init() < 0)) {
+ return ret_code;
+ }
+
+ /* 6. set initial flag */
+ bms_psu_init_done = 1;
+
+ return ret_code;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_cache_get
+* PURPOSE:
+* psu service cache get
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_status (OUT) pointer of psu status
+* psu_type (OUT) pointer of psu type
+* RETURNS:
+*/
+void
+bms_psu_serv_cache_get(unsigned int psu_number,
+ unsigned int* psu_status,
+ unsigned int* psu_type)
+{
+ pthread_mutex_lock(&bms_psu_st_cache_lock);
+ *psu_status = bms_psu_status[psu_number];
+ *psu_type = bms_psu_type[psu_number];
+ pthread_mutex_unlock(&bms_psu_st_cache_lock);
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_intr_cache_get
+* PURPOSE:
+* psu service interrupt cache get
+* PARAMETERS:
+* intr_status (OUT) pointer of psu type
+* RETURNS:
+*/
+void
+bms_psu_serv_intr_cache_get(unsigned int* intr_status)
+{
+ pthread_mutex_lock(&bms_psu_intr_cache_lock);
+ memcpy(intr_status, bms_psu_intr_cache, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM);
+ pthread_mutex_unlock(&bms_psu_intr_cache_lock);
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_intr_cache_update
+* PURPOSE:
+* psu service interrupt cache update
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_cause (IN) psu update index
+* value (IN) update value
+* RETURNS:
+*/
+void
+bms_psu_serv_intr_cache_update(unsigned int psu_number,
+ unsigned int psu_cause,
+ unsigned int value)
+{
+ pthread_mutex_lock(&bms_psu_intr_cache_lock);
+ bms_psu_intr_cache[(psu_number * BMS_PSU_INTR_NUM) + psu_cause] = value;
+ pthread_mutex_unlock(&bms_psu_intr_cache_lock);
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_intr_cache_clear
+* PURPOSE:
+* psu specific interrupt cache clear
+* PARAMETERS:
+* psu_number (IN) psu number
+* RETURNS:
+*/
+void
+bms_psu_serv_intr_cache_clear(unsigned int psu_number)
+{
+ int i = 0;
+
+ pthread_mutex_lock(&bms_psu_intr_cache_lock);
+
+ for(i = 0; i < BMS_PSU_INTR_NUM; i++) {
+ bms_psu_intr_cache[(psu_number * BMS_PSU_INTR_NUM) + i] = 0;
+ }
+
+ pthread_mutex_unlock(&bms_psu_intr_cache_lock);
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_power_led_by_cache_get
+* PURPOSE:
+* get power led status from cache
+* PARAMETERS:
+*
+* RETURNS:
+* BMS_PSU_POWER_LED_OFF or BMS_PSU_POWER_LED_AMBER or BMS_PSU_POWER_LED_GREEN,
+*/
+static int
+bms_psu_serv_power_led_by_cache_get(void)
+{
+ int i = 0;
+ unsigned int cache_status[BMS_PSU_NUM], cache_type[BMS_PSU_NUM];
+
+ /* read value from cache */
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ bms_psu_serv_cache_get(i, &cache_status[i], &cache_type[i]);
+ }
+
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ if((cache_status[i] == BMS_PSU_STATUS_NORMAL) ||
+ (cache_status[i] == BMS_PSU_STATUS_FAULT)) {
+ break;
+ }
+ }
+
+ if(i == BMS_PSU_NUM) {
+ return BMS_PSU_POWER_LED_OFF;
+ }
+
+ for(i = 0; i < BMS_PSU_NUM; i++) {
+ if((cache_status[i] == BMS_PSU_STATUS_FAULT) ||
+ (cache_type[i] != bms_psu_board_type)) {
+ return BMS_PSU_POWER_LED_AMBER;
+ }
+ }
+
+ return BMS_PSU_POWER_LED_GREEN;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_cache_power_led_update
+* PURPOSE:
+* update psu cache and power led
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_cause (IN) cause of psu event
+* psu_type (IN) psu type
+* RETURNS:
+* success, compare the same return zero.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_psu_serv_cache_power_led_update(unsigned int psu_number,
+ unsigned int psu_cause,
+ unsigned int psu_type)
+{
+ int ret_code = 0;
+ unsigned int pre_status, cur_status;
+
+ pre_status = bms_psu_serv_power_led_by_cache_get();
+
+ bms_psu_serv_cache_update(psu_number, psu_cause, psu_type);
+
+ cur_status = bms_psu_serv_power_led_by_cache_get();
+
+ if(cur_status == pre_status)
+ return ret_code;
+
+ if(cur_status == BMS_PSU_POWER_LED_GREEN) {
+ if((ret_code = bms_psu_serv_power_led_set(BMS_PSU_POWER_LED_GREEN)) < 0) {
+ return ret_code;
+ }
+ }else
+ if(cur_status == BMS_PSU_POWER_LED_AMBER) {
+ if((ret_code = bms_psu_serv_power_led_set(BMS_PSU_POWER_LED_AMBER)) < 0) {
+ return ret_code;
+ }
+ }else{
+ syslog(LOG_WARNING|LOG_USER,"[%s] Invaild vailed in cache\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ return ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_find_serv_data_index
+* PURPOSE:
+* find index of psu of serv_data
+* PARAMETERS:
+* psu_number (IN) psu number
+* RETURNS:
+* success, this function returns value.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_psu_serv_find_serv_data_index(unsigned int psu_number)
+{
+ int i;
+
+ for(i = 0; i < bms_sys_serv_data_num; i++) {
+ if(strcmp(bms_sys_serv_data[i].name, bms_psu_serv_data[psu_number].name) == 0)
+ return i;
+ }
+
+ syslog(LOG_WARNING|LOG_USER,"Can't find %s item index in bms_sys_serv_data\n", bms_psu_serv_data[psu_number].name);
+ return -EINVAL;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_intr_mask_set
+* PURPOSE:
+* set psu intr mask
+* PARAMETERS:
+* psu_number (IN) psu number
+* value (IN) mask of setting value
+* RETURNS:
+* success, this function returns zero.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_serv_intr_mask_set(unsigned int psu_number,
+ unsigned int value)
+{
+ int ret_code = 0, index;
+
+ if((ret_code = bms_psu_serv_find_serv_data_index(psu_number)) < 0)
+ return ret_code;
+
+ index = ret_code;
+ if((ret_code = bms_sys_serv_write(bms_sys_serv_data[index].intr_msk, value)) < 0) {
+ return ret_code;
+ }
+
+ return ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_intr_get
+* PURPOSE:
+* set psu intr mask
+* PARAMETERS:
+* psu_number (IN) psu number
+* value (OUT) mask of setting value
+* RETURNS:
+* success, this function returns zero.
+* for other cases, negative errno is returned.
+*/
+int
+bms_psu_serv_intr_get(unsigned int psu_number,
+ unsigned int *value)
+{
+ int ret_code = 0, index;
+
+ if((ret_code = bms_psu_serv_find_serv_data_index(psu_number)) < 0)
+ return ret_code;
+
+ index = ret_code;
+
+ if((ret_code = bms_sys_serv_hex_read(bms_sys_serv_data[index].intr_src, value)) < 0) {
+ return ret_code;
+ }
+
+ return ret_code;
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_psu_fault_datect
+* PURPOSE:
+* detect psu fault cause
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_status (OUT) pointer of psu status
+*/
+void
+bms_psu_serv_psu_fault_datect(unsigned int psu_number,
+ unsigned int *psu_status)
+{
+ unsigned int intr_table[BMS_PSU_NUM * BMS_PSU_INTR_NUM], i;
+
+ memset(intr_table, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM);
+
+ bms_psu_serv_intr_cache_get(intr_table);
+
+ for(i = 0; i < BMS_PSU_INTR_NUM; i++) {
+ if(intr_table[i + (psu_number * BMS_PSU_INTR_NUM)] == BMS_PSU_SOURCE_INTR_ASSERTED){
+ *psu_status = BMS_PSU_STATUS_FAULT;
+ return;
+ }
+ }
+
+ *psu_status = BMS_PSU_STATUS_NORMAL;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_cause_log
+* PURPOSE:
+* log of psu cause
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_cause (IN) cause of psu status
+* RETURNS:
+*/
+static void
+bms_psu_serv_cause_log(unsigned int psu_number,
+ unsigned int psu_cause)
+{
+ unsigned int cache_type, cache_status;
+
+ bms_psu_serv_cache_get(psu_number, &cache_status, &cache_type);
+
+ if(psu_cause == BMS_PSU_STATUS_PRESENT) {
+ if((cache_status == BMS_PSU_STATUS_NORMAL) ||
+ (cache_status == BMS_PSU_STATUS_FAULT)) {
+ syslog(LOG_DEBUG|LOG_USER,"The psu %u was no power.", psu_number + 1);
+ }else
+ if(cache_status == BMS_PSU_STATUS_ABSENT) {
+ syslog(LOG_DEBUG|LOG_USER,"The psu %u was present, but no power.", psu_number + 1);
+ }else{
+ syslog(LOG_WARNING|LOG_USER,"LOG error, unknown psu_cause in psu %u\n", psu_number + 1);
+ }
+ }else
+ if(psu_cause == BMS_PSU_STATUS_NORMAL) {
+ if(cache_status == BMS_PSU_STATUS_ABSENT) {
+ syslog(LOG_DEBUG|LOG_USER,"The psu %u was present, and work normal.", psu_number + 1);
+ }else
+ if(cache_status == BMS_PSU_STATUS_PRESENT) {
+ syslog(LOG_DEBUG|LOG_USER,"The psu %u has power.", psu_number + 1);
+ }else
+ if(cache_status == BMS_PSU_STATUS_FAULT) {
+ /* Don't show any log */
+ }else{
+ syslog(LOG_WARNING|LOG_USER,"LOG error, unknown psu_cause in psu %u\n", psu_number + 1);
+ }
+ }else
+ if(psu_cause == BMS_PSU_STATUS_FAULT) {
+ syslog(LOG_WARNING|LOG_USER,"The psu %u was fault\n", psu_number + 1);
+ }else
+ if(psu_cause == BMS_PSU_STATUS_ABSENT) {
+ syslog(LOG_DEBUG|LOG_USER,"The psu %u was non present\n", psu_number + 1);
+ }else{
+ syslog(LOG_WARNING|LOG_USER,"LOG error, unknown psu_cause in psu %u\n", psu_number + 1);
+ }
+}
+
+
+/*
+* FEATURE:
+* bms_psu_serv_intr_log
+* PURPOSE:
+* log of psu intrrupt
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_cause (IN) psu interrupt cause
+* RETURNS:
+*/
+void
+bms_psu_serv_intr_log(unsigned int psu_number,
+ unsigned int psu_cause)
+{
+ switch (psu_cause) {
+ case BMS_PSU_VOUT_OV_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by over output voltage.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_VOUT_UV_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by under output voltage.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_IOUT_OC_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by over currents.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_IOUT_OC_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is warning by over currents.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_OT_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by over temperature.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_OT_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is warning by over temperature.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_VIN_UV_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is warning by under input voltage.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_VIN_UV_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by under input voltage.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_FAN1_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is fault.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_FAN1_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u is warning.\n", psu_number + 1);
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u receive unknown item %d.\n", psu_number + 1, psu_cause);
+ break;
+ }
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_intr_recovery_log
+* PURPOSE:
+* log of psu recovery intrrupt
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_cause (IN) psu interrupt cause
+* RETURNS:
+*/
+void
+bms_psu_serv_intr_recovery_log(unsigned int psu_number,
+ unsigned int psu_cause)
+{
+ switch (psu_cause) {
+ case BMS_PSU_VOUT_OV_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u over output voltage is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_VOUT_UV_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u under output voltage is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_IOUT_OC_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u over currents fault is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_IOUT_OC_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u over currents warning is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_OT_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u over temperature fault is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_OT_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u over temperature warning is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_VIN_UV_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u under input voltage warning is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_VIN_UV_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u under input voltage fault is recovery .\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_FAN1_FAULT:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u fan fault is recovery.\n", psu_number + 1);
+ break;
+
+ case BMS_PSU_FAN1_WARNING:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u fan warning is recovery.\n", psu_number + 1);
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"The psu %u receive unknown item %d recovery.\n", psu_number + 1, psu_cause);
+ break;
+ }
+
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_board_type_comp
+* PURPOSE:
+* compare psu type is the same with board type
+* PARAMETERS:
+* psu_type (IN) psu type
+* RETURNS:
+*/
+static int
+bms_psu_serv_board_type_comp(unsigned int psu_type)
+{
+
+ if(bms_psu_board_type == psu_type) {
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+* FEATURE:
+* bms_psu_serv_type_log
+* PURPOSE:
+* log of psu the is the same with board type
+* PARAMETERS:
+* psu_number (IN) psu number
+* psu_type (IN) psu type
+* RETURNS:
+*/
+static void
+bms_psu_serv_type_log(unsigned int psu_number,
+ unsigned int psu_type)
+{
+ if((bms_psu_serv_board_type_comp(psu_type) < 0))
+ syslog(LOG_WARNING|LOG_USER,"The psu %u type was wrong\n", psu_number + 1);
+}
+
+
+/*
+* FEATURE:
+* bms_psu_servd
+* PURPOSE:
+* service to handle message queue event of cpu temperature
+* PARAMETERS:
+* args (IN) message queue name
+* RETURNS:
+* open success, this function will wait for message queue.
+* for other cases, will exit this program.
+*/
+void*
+bms_psu_servd(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ bms_sys_serv_mq_data_t msg;
+ int ret_code;
+ unsigned int psu_number, psu_type, psu_status, pg_status;
+ unsigned int psu_pg;
+
+ /* Open message queue */
+ if (bms_psu_serv_init(mq_name, &mq_desc) < 0) {
+ goto quit;
+ }
+
+ while (1) {
+ /* Wait for message queue */
+ if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ switch (msg.serv_type) {
+ case SERV_TYPE_RX_INTR:
+ psu_number = msg.number;
+
+ bms_psu_serv_intr_cache_update(psu_number, msg.cause, BMS_PSU_SOURCE_INTR_ASSERTED);
+
+ bms_psu_serv_intr_log(psu_number, msg.cause);
+
+ bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_FAULT, -1);
+ break;
+
+ case SERV_TYPE_PSU_NORMAL:
+ psu_number = msg.number;
+PSU_NORMAL:
+
+ if(bms_psu_driver_init[psu_number] == BMS_PSU_DRIVER_UNINIT){
+ if ((ret_code = bms_psu_serv_driver_plugin(psu_number)) < 0) {
+ break;
+ }
+ }
+
+ if((ret_code = bms_psu_serv_type_get(psu_number, &psu_type)) < 0) {
+ break;
+ }
+
+ bms_psu_serv_psu_fault_datect(psu_number, &psu_status);
+
+ if(psu_status == BMS_PSU_STATUS_FAULT) {
+ bms_psu_serv_cache_update(psu_number, BMS_PSU_STATUS_NORMAL, psu_type);
+ bms_psu_serv_type_log(psu_number, psu_type);
+ }else{
+ bms_psu_serv_cause_log(psu_number, BMS_PSU_STATUS_NORMAL);
+ bms_psu_serv_type_log(psu_number, psu_type);
+ bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_NORMAL, psu_type);
+ }
+
+ break;
+
+ case SERV_TYPE_PSU_PRESENT:
+ psu_number = msg.number;
+
+ if ((ret_code = bms_psu_serv_power_status_get(&pg_status)) < 0) {
+ break;
+ }
+
+ psu_pg = ((pg_status & (1 << (bms_psu_serv_data[psu_number].pg_offset))) > 0) ? BMS_PSU_PG_FAILED : BMS_PSU_PG_GOOD;
+
+ if(psu_pg == BMS_PSU_PG_GOOD) {
+ goto PSU_NORMAL;
+ }else{
+ bms_psu_serv_cause_log(psu_number, BMS_PSU_STATUS_PRESENT);
+
+ bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_PRESENT, -1);
+ }
+ break;
+
+ case SERV_TYPE_PSU_ABSENT:
+ psu_number = msg.number;
+
+ bms_psu_serv_intr_cache_clear(psu_number);
+
+ bms_psu_serv_cause_log(psu_number, BMS_PSU_STATUS_ABSENT);
+ bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_ABSENT, -1);
+
+ break;
+
+ case SERV_TYPE_PSU_INTR_RECOVERY:
+ psu_number = msg.number;
+ bms_psu_serv_intr_cache_update(psu_number, msg.cause, BMS_PSU_SOURCE_INTR_DEASSERTED);
+
+ bms_psu_serv_intr_recovery_log(psu_number, msg.cause);
+
+ bms_psu_serv_psu_fault_datect(psu_number, &psu_status);
+
+ if(psu_status == BMS_PSU_STATUS_FAULT) {
+ bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_FAULT, -1);
+ }
+ else if(psu_status == BMS_PSU_STATUS_NORMAL) {
+ goto PSU_NORMAL;
+ }else{
+ syslog(LOG_WARNING|LOG_USER,"Receive psu %d INTR_RECOVERY message, but can't find next status\n", psu_number);
+ }
+
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name);
+ break;
+ }
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.h
new file mode 100644
index 000000000000..8de0353e5be9
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.h
@@ -0,0 +1,103 @@
+#ifndef __BMS_PSU_SERVD_H__
+#define __BMS_PSU_SERVD_H__
+#include "bms_irq_sysd.h"
+
+#define PSU_FILE_PATH_LEN 64
+
+enum {
+ BMS_PSU_AC_NORMAL_FAN = 0,
+ BMS_PSU_AC_REVERSE_FAN,
+ BMS_PSU_DC_NORMAL_FAN,
+ BMS_PSU_DC_REVERSE_FAN,
+};
+
+enum {
+ BMS_PSU_STATUS_NORMAL = 0,
+ BMS_PSU_STATUS_PRESENT,
+ BMS_PSU_STATUS_ABSENT,
+ BMS_PSU_STATUS_FAULT,
+};
+
+enum {
+ BMS_PSU_POWER_LED_OFF = 0,
+ BMS_PSU_POWER_LED_AMBER,
+ BMS_PSU_POWER_LED_GREEN,
+};
+
+enum {
+ BMS_PSU_INTR_MASKED = 0,
+ BMS_PSU_INTR_UNMASKED,
+};
+
+enum {
+ BMS_PSU_INTR_ASSERTED = 0,
+ BMS_PSU_INTR_DEASSERTED,
+};
+
+enum {
+ BMS_PSU_SOURCE_INTR_DEASSERTED = 0,
+ BMS_PSU_SOURCE_INTR_ASSERTED,
+};
+
+enum {
+ BMS_PSU_PG_GOOD = 0,
+ BMS_PSU_PG_FAILED,
+};
+
+enum {
+ BMS_PSU_PS_PRESENT = 0,
+ BMS_PSU_PS_NONPRESENT,
+};
+
+enum {
+ BMS_PSU_DRIVER_UNINIT = 0,
+ BMS_PSU_DRIVER_INIT_DONE,
+};
+
+enum {
+ BMS_PSU_VOUT_OV_FAULT = 0,
+ BMS_PSU_VOUT_UV_FAULT,
+ BMS_PSU_IOUT_OC_FAULT,
+ BMS_PSU_IOUT_OC_WARNING,
+ BMS_PSU_OT_FAULT,
+ BMS_PSU_OT_WARNING,
+ BMS_PSU_VIN_UV_WARNING,
+ BMS_PSU_VIN_UV_FAULT,
+ BMS_PSU_FAN1_FAULT,
+ BMS_PSU_FAN1_WARNING,
+/*----------------------------------*/
+ BMS_PSU_INTR_NUM,
+};
+
+typedef struct {
+ char* name;
+ int pg_offset;
+ int ps_offset;
+ int address;
+ char* pg_ps_reg;
+ char model_reg[PSU_FILE_PATH_LEN];
+ char* hwmon_path;
+ char intr_src[BMS_PSU_INTR_NUM][PSU_FILE_PATH_LEN];
+ char* i2c_path;
+ char* driver_name;
+}bms_psu_serv_data_t;
+
+
+#define BMS_PSU_NUM 2
+#define BMS_SYSFS_POWER_LED "/sys/bus/i2c/devices/1-0032/power_led"
+
+/* PSU message queue range define 200~299 */
+#define SERV_TYPE_PSU_PRESENT 200
+#define SERV_TYPE_PSU_ABSENT 201
+#define SERV_TYPE_PSU_NORMAL 202
+#define SERV_TYPE_PSU_INTR_RECOVERY 203
+
+extern bms_sys_serv_data_t bms_sys_serv_data[];
+extern int bms_sys_serv_data_num;
+extern unsigned int bms_psu_init_done;
+extern int bms_psu_serv_power_status_get(unsigned int *value);
+extern void bms_psu_serv_cache_get(unsigned int psu_number, unsigned int* psu_status, unsigned int* psu_type);
+extern bms_psu_serv_data_t bms_psu_serv_data[];
+extern void bms_psu_serv_intr_cache_get(unsigned int* intr_status);
+
+#endif /* __BMS_PSU_SERVD_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.c
new file mode 100644
index 000000000000..3681c17d5e79
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.c
@@ -0,0 +1,311 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*
+* FEATURE:
+* bms_sys_serv_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+int
+bms_sys_serv_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_RDONLY), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+
+
+/*
+ * FEATURE:
+ * bms_sys_serv_hex_read
+ * PURPOSE:
+ * hex read from file system
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * value (OUT) pointer of current value buffer
+ * RETURNS:
+ * open success, this function returns zero.
+ * for other cases, negative errno is returned.
+ */
+int
+bms_sys_serv_hex_read(char *filename,
+ unsigned int *value)
+{
+ char buf[32] = {0};
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ /* Open xcvr pin file */
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Read pin file */
+ if ((count = read(fd, buf, buf_size)) != (-1)) {
+ *value = strtol(buf, NULL, 16);
+ }
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_sys_serv_dec_read
+ * PURPOSE:
+ * dec read from file system
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * value (OUT) pointer of current value buffer
+ * RETURNS:
+ * open success, this function returns zero.
+ * for other cases, negative errno is returned.
+ */
+int
+bms_sys_serv_dec_read(char *filename,
+ unsigned int *value)
+{
+ char buf[32];
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ /* Open file */
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Read pin file */
+ if ((count = read(fd, buf, buf_size)) != (-1)) {
+ *value = strtol(buf, NULL, 10);
+ }
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_sys_serv_char_read
+ * PURPOSE:
+ * char read from file system
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * value (OUT) pointer of current value buffer
+ * RETURNS:
+ * open success, this function returns zero.
+ * for other cases, negative errno is returned.
+ */
+int
+bms_sys_serv_char_read(char *filename,
+ char *value)
+{
+ char buf[32];
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ /* Open file */
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Read pin file */
+ if ((count = read(fd, buf, buf_size)) != (-1)) {
+ /* the last character was \n*/
+ memcpy(value, buf, count);
+ }
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+
+
+/*
+ * FEATURE:
+ * bms_sys_serv_write
+ * PURPOSE:
+ * byte data write to file system
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * value (IN) new register value
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_sys_serv_write(char *filename,
+ unsigned int value)
+{
+ char buf[4];
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ /* Open file */
+ if ((fd = open(filename, O_WRONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Write file */
+ snprintf(buf, buf_size, "%d", value);
+ if ((count = write(fd, buf, buf_size)) != (-1)) {;}
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_sys_serv_buf_write
+ * PURPOSE:
+ * buf data write to file system
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * buf (IN) buf data
+ * buf_size (IN) buf size
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_sys_serv_buf_write(char *filename,
+ char *buf,
+ int buf_size)
+{
+ int fd, ret_code = 0;
+ ssize_t count;
+
+ /* Open file */
+ if ((fd = open(filename, O_WRONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Write file */
+ if ((count = write(fd, buf, buf_size)) != (-1)) {;}
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_sys_serv_hwmon_path_find
+ * PURPOSE:
+ * find hwmon path for when insert different order
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * value (IN) new register value
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_sys_serv_hwmon_path_find(char *filepath,
+ char *filename)
+{
+ struct dirent **namelist;
+ int ret_code = 0;
+ char name[32];
+
+ memcpy(name, filename, strlen(filename)+1);
+
+ ret_code = scandir(filepath , &namelist, NULL, alphasort);
+
+ if (ret_code < 0){
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to scandir %s (%s)\n", filepath, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* if counter is 2, that mean the folder is empty that include "." and ".." */
+ if(ret_code <= 2){
+ syslog(LOG_WARNING|LOG_USER,"Failed to find folder hwmon (%s)\n", strerror(ret_code));
+ return -ENXIO;
+ }
+
+ sprintf(filename, "%s/%s/%s", filepath, namelist[--ret_code]->d_name, name);
+ free(namelist);
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_sys_serv_file_exist
+ * PURPOSE:
+ * find file name exist
+ * PARAMETERS:
+ * filename (IN) file name
+ * RETURNS:
+ * file exist, return zero
+ * for other cases, return 1
+ */
+int
+bms_sys_serv_file_exist(char *filename)
+{
+ if( access( filename, F_OK ) != -1 ) {
+ // file exists
+ return 0;
+ }
+ // file doesn't exist
+ return 1;
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.h
new file mode 100644
index 000000000000..41db1d5c8682
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.h
@@ -0,0 +1,16 @@
+#ifndef __BMS_SYS_SERV_COMMON_H__
+#define __BMS_SYS_SERV_COMMON_H__
+
+#define BMS_SYSFS_BOARD_TYPE "/sys/bus/i2c/devices/1-0032/brd_type"
+
+extern int bms_sys_serv_msq_open(const char *qname, mqd_t *mqd);
+extern int bms_sys_serv_hex_read(char *filename, unsigned int *value);
+extern int bms_sys_serv_write(char *filename, unsigned int value);
+extern int bms_sys_serv_dec_read(char *filename, unsigned int *value);
+extern int bms_sys_serv_char_read(char *filename, char *value);
+extern int bms_sys_serv_hwmon_path_find(char *filepath, char *filename);
+extern int bms_sys_serv_buf_write(char *filename, char *buf, int buf_size);
+extern int bms_sys_serv_file_exist(char *filename);
+
+
+#endif /* __BMS_SYS_SERV_COMMON_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_temp_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_temp_servd.c
new file mode 100644
index 000000000000..ba8e22301d83
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_temp_servd.c
@@ -0,0 +1,105 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_sys_temp_servd.c
+ *
+ * @purpose BMS system temperature service daemon
+ *
+ * @create 2017/3/17
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_irq_sysd.h"
+
+#include
+
+/*
+* FEATURE:
+* bms_sys_temp_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_sys_temp_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_RDONLY), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+/*
+* FEATURE:
+* bms_sys_temp_servd
+* PURPOSE:
+* service to handle message queue event of cpu temperature
+* PARAMETERS:
+* args (IN) message queue name
+* RETURNS:
+* open success, this function will wait for message queue.
+* for other cases, will exit this program.
+*/
+void*
+bms_sys_temp_servd(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ bms_sys_serv_mq_data_t msg;
+ int ret_code;
+
+ /* Open message queue */
+ if (bms_sys_temp_msq_open(mq_name, &mq_desc) < 0) {
+ goto quit;
+ }
+
+ while (1) {
+ /* Wait for message queue */
+ if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ switch (msg.serv_type) {
+ case SERV_TYPE_RX_INTR: /* TEMP_ALERT_IRQ interrupt */
+ syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name);
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name);
+ break;
+ }
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_usb_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_usb_servd.c
new file mode 100644
index 000000000000..fe97ad15f377
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_usb_servd.c
@@ -0,0 +1,105 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_usb_servd.c
+ *
+ * @purpose BMS usb service daemon
+ *
+ * @create 2017/3/17
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_irq_sysd.h"
+
+#include
+
+/*
+* FEATURE:
+* bms_usb_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_usb_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_RDONLY), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+/*
+* FEATURE:
+* bms_usb_servd
+* PURPOSE:
+* service to handle message queue event of cpu temperature
+* PARAMETERS:
+* args (IN) message queue name
+* RETURNS:
+* open success, this function will wait for message queue.
+* for other cases, will exit this program.
+*/
+void*
+bms_usb_servd(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ bms_sys_serv_mq_data_t msg;
+ int ret_code;
+
+ /* Open message queue */
+ if (bms_usb_msq_open(mq_name, &mq_desc) < 0) {
+ goto quit;
+ }
+
+ while (1) {
+ /* Wait for message queue */
+ if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ switch (msg.serv_type) {
+ case SERV_TYPE_RX_INTR: /* USB_FAULT interrupt */
+ syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name);
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name);
+ break;
+ }
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_vrhot_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_vrhot_servd.c
new file mode 100644
index 000000000000..ca1446e2a9fb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_vrhot_servd.c
@@ -0,0 +1,105 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_vrhot_servd.c
+ *
+ * @purpose BMS vrhot service daemon
+ *
+ * @create 2017/3/17
+ *
+ * @author eddy.weng
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_irq_sysd.h"
+
+#include
+
+/*
+* FEATURE:
+* bms_vrhot_msq_open
+* PURPOSE:
+* open POSIX message queue
+* PARAMETERS:
+* qname (IN) message queue name
+* mqd (OUT) pointer of message queue description
+* RETURNS:
+* open success, this function returns 0.
+* for other cases, negative errno is returned.
+*/
+static int
+bms_vrhot_msq_open(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_RDONLY), ret_code = 0;
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+/*
+* FEATURE:
+* bms_vrhot_servd
+* PURPOSE:
+* service to handle message queue event of cpu temperature
+* PARAMETERS:
+* args (IN) message queue name
+* RETURNS:
+* open success, this function will wait for message queue.
+* for other cases, will exit this program.
+*/
+void*
+bms_vrhot_servd(void *args)
+{
+ char *mq_name = (char*)args;
+ mqd_t mq_desc;
+ bms_sys_serv_mq_data_t msg;
+ int ret_code;
+
+ /* Open message queue */
+ if (bms_vrhot_msq_open(mq_name, &mq_desc) < 0) {
+ goto quit;
+ }
+
+ while (1) {
+ /* Wait for message queue */
+ if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ switch (msg.serv_type) {
+ case SERV_TYPE_RX_INTR: /* VRHOT_IRQ interrupt */
+ syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name);
+ break;
+
+ default:
+ syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name);
+ break;
+ }
+ }
+
+quit:
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd
deleted file mode 100755
index a1b4f177897c..000000000000
Binary files a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd and /dev/null differ
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf
deleted file mode 100644
index 81f0b7b819bf..000000000000
--- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf
+++ /dev/null
@@ -1,45 +0,0 @@
-#ping = 172.31.14.1
-#ping = 172.26.1.255
-#interface = eth0
-#file = /var/log/messages
-#change = 1407
-
-# Uncomment to enable test. Setting one of these values to '0' disables it.
-# These values will hopefully never reboot your machine during normal use
-# (if your machine is really hung, the loadavg will go much higher than 25)
-#max-load-1 = 24
-#max-load-5 = 18
-#max-load-15 = 12
-
-# Note that this is the number of pages!
-# To get the real size, check how large the pagesize is on your machine.
-#min-memory = 1
-#allocatable-memory = 1
-
-#repair-binary = /usr/sbin/repair
-#repair-timeout =
-#test-binary =
-#test-timeout =
-
-watchdog-device = /dev/watchdog
-
-# Defaults compiled into the binary
-#temperature-device =
-#max-temperature = 120
-
-# Defaults compiled into the binary
-#admin = root
-#interval = 1
-#logtick = 1
-#log-dir = /var/log/watchdog
-
-# This greatly decreases the chance that watchdog won't be scheduled before
-# your machine is really loaded
-realtime = yes
-priority = 99
-
-# Check if rsyslogd is still running by enabling the following line
-#pidfile = /var/run/rsyslogd.pid
-
-# timeout : 15 , 30 , 60 , 90 , 120 , 180 , 240 sec
-watchdog-timeout = 120
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/Makefile b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/Makefile
new file mode 100644
index 000000000000..1d31ffa929a6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/Makefile
@@ -0,0 +1,51 @@
+#/*
+#**********************************************************************
+#*
+#* @filename Makefile
+#*
+#* @purpose This Makefile is used for Lattice utility
+#*
+#* @create 2017/03/03
+#*
+#* @author yencheng.lin
+#*
+#* @history 2017/03/03: init version
+#*
+#**********************************************************************
+#*/
+
+TARGETS := xcvr-servd
+INC = $(wildcard *.h)
+OBJ=$(subst .c,.o,$(wildcard *.c))
+
+.PHONY: all
+all: $(TARGETS)
+
+.PHONY: config
+config:
+
+.PHONY: patch
+patch:
+
+.PHONY: install
+install:
+ mkdir -p $(INST_DIR)/xcvr-serv/
+ cp $(TARGETS) $(INST_DIR)/xcvr-serv/
+
+.PHONY: uninstall
+uninstall:
+ rm -f $(addprefix $(INST_DIR)/xcvr-serv/,$(TARGETS))
+
+.PHONY: clean
+clean:
+ rm -rf $(OBJ) $(TARGETS)
+
+.PHONY: distclean
+distclean: clean
+
+$(OBJ): $(INC)
+%.o: %.c
+ $(CC) -c -o $@ $< -Wall -Wextra -Werror
+
+$(TARGETS): $(OBJ)
+ $(CC) $^ -lrt -pthread -o $@
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.c
new file mode 100644
index 000000000000..0400b8114762
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.c
@@ -0,0 +1,342 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_xcvr_access.c
+ *
+ * @purpose access EEPROM of transceiver module
+ *
+ * @create 2017/3/17
+ *
+ * @author yencheng.lin
+ *
+ * @history 2017/3/17: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_xcvr_access.h"
+
+#define DISABLE_MASK 0xFF
+
+#define SFF_UPPER_PAGE_BYTE_START 128
+#define HIGH_POWER_CLASS_MASK 0x03
+#define LEGACY_POWER_CLASS_MASK 0xC0
+
+#define XCVR_HW_INTR_MASK_START 100
+#define XCVR_CHANNEL_INTR_MASK_START 242
+#define XCVR_HW_INTR_MASK_PAGE 0
+#define XCVR_CHANNEL_INTR_MASK_PAGE 3
+#define XCVR_HW_INTR_MASK_BYTES 5
+#define XCVR_CHANNEL_INTR_MASK_BYTES 6
+
+/* TODO might be 0x50 or 0x51 */
+unsigned char bms_xcvr_addr = 0x50;
+
+static int bms_xcvr_i2c_open(unsigned char bus, int *i2c_fd);
+static int bms_xcvr_i2c_read(unsigned char bus, unsigned char addr, unsigned short offset, unsigned char *val);
+static int bms_xcvr_i2c_write(unsigned char bus, unsigned char addr, unsigned short offset, unsigned char val);
+
+typedef struct {
+ unsigned short page;
+ unsigned short offset;
+ unsigned char shift;
+ unsigned char width;
+} bms_xcvr_data_t;
+
+bms_xcvr_data_t bms_xcvr_data_list[] = {
+ /*page, offset, shift, width */
+ { 0, 2, 0, 1 },/* "Data_Note_Ready" is bit0 of byte2 in the page0 */
+ { 0, 127, 0, 8 },/* "Page Select" is byte128 in the page0 */
+ { 0, 6, 0, 1 },/* "Initialization complete flag" is bit0 of byte 6 in the page0 */
+ { 0, 129, 0, 8 },/* "Ext. Identifier" is bit0-1 of byte129 in the page0 */
+ { 0, 93, 0, 3 },/* "Power Mode Control" is bit0-2 of byte 93 in the page0 */
+};
+int bms_xcvr_data_list_num = sizeof(bms_xcvr_data_list) / sizeof(bms_xcvr_data_list[0]);
+
+/*
+ * FEATURE:
+ * bms_xcvr_i2c_open
+ * PURPOSE:
+ * low-level function to open an I2C adapter device file
+ * PARAMETERS:
+ * bus (IN) I2C bus to be looking for
+ * i2c_fd (OUT) file descriptor
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+static int
+bms_xcvr_i2c_open(unsigned char bus,
+ int *i2c_fd)
+{
+ int err = 0;
+ char dev_name[20];
+
+ sprintf(dev_name, "/dev/i2c-%u", bus);
+ if ((*i2c_fd = open(dev_name, O_RDWR)) < 0) {
+ err = errno;
+ syslog(LOG_DEBUG|LOG_USER,
+ "[%s] could not open I2C adapter %s: %s\n",
+ __func__, dev_name, strerror(err));
+ return -err;
+ }
+
+ return err;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_i2c_read
+ * PURPOSE:
+ * low-level function to read 8-bit data from an I2C slave component
+ * PARAMETERS:
+ * bus (IN) I2C bus to be looking for
+ * addr (IN) I2C slave address of the transceiver
+ * offset (IN) register offset
+ * val (OUT) pointer of current value buffer
+ * RETURNS:
+ * read success, this function returns 0.
+ * for other cases, negative errno is returned.
+ */
+static int
+bms_xcvr_i2c_read(unsigned char bus,
+ unsigned char addr,
+ unsigned short offset,
+ unsigned char *val)
+{
+ int err = 0, value;
+ int i2c_fd = 0;
+
+ if ((err = bms_xcvr_i2c_open(bus, &i2c_fd)) < 0) {goto quit;}
+ if ((ioctl(i2c_fd, I2C_SLAVE_FORCE, addr)) < 0) {
+ err = errno;
+ return -err;
+ }
+ value = i2c_smbus_read_byte_data(i2c_fd, offset);
+ if (value < 0) {
+ err = errno;
+ syslog(LOG_DEBUG|LOG_USER,
+ "[%s] could not read register 0x%X: %s\n",
+ __func__, offset, strerror(err));
+ close(i2c_fd);
+ return -err;
+ }
+ *val = value;
+
+quit:
+ close(i2c_fd);
+ return err;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_i2c_write
+ * PURPOSE:
+ * low-level function to write 8-bit data to an I2C slave component
+ * PARAMETERS:
+ * bus (IN) I2C bus to be looking for
+ * addr (IN) I2C slave address of the transceiver
+ * offset (IN) register offset
+ * val (IN) new register value
+ * RETURNS:
+ * write success, this function returns 0.
+ * for other cases, negative errno is returned.
+ */
+static int
+bms_xcvr_i2c_write(unsigned char bus,
+ unsigned char addr,
+ unsigned short offset,
+ unsigned char val)
+{
+ int err = 0;
+ int i2c_fd = 0;
+
+ if ((err = bms_xcvr_i2c_open(bus, &i2c_fd)) < 0) {goto quit;}
+ if ((ioctl(i2c_fd, I2C_SLAVE_FORCE, addr)) < 0) {
+ err = errno;
+ return -err;
+ }
+ if (i2c_smbus_write_byte_data(i2c_fd, offset, val) < 0) {
+ err = errno;
+ syslog(LOG_DEBUG|LOG_USER,
+ "[%s] could not write register 0x%X: %s\n",
+ __func__, offset, strerror(err));
+ close(i2c_fd);
+ return -err;
+ }
+
+quit:
+ close(i2c_fd);
+ return err;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_max_power_class
+ * PURPOSE:
+ * setup max power class for high or legacy device
+ * PARAMETERS:
+ * bus (IN) I2C bus to be looking for
+ * addr (IN) I2C slave address of transceiver
+ * legacy_power (IN) 1 means power class 2-4 and 0 means power class 5-7
+ * RETURNS:
+ * set success, this function returns 0.
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_max_power_class(unsigned char bus,
+ unsigned char addr,
+ unsigned char legacy_power)
+{
+ int err = 0, item = REG_POWER_MODE_CONTROL;
+ unsigned short val = (legacy_power ? 0x1 : 0x5);
+
+ err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[item].offset, val);
+ return err;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_min_power_class
+ * PURPOSE:
+ * setup minpower class for high or legacy device
+ * PARAMETERS:
+ * bus (IN) I2C bus to be looking for
+ * addr (IN) I2C slave address of transceiver
+ * RETURNS:
+ * set success, this function returns 0.
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_min_power_class(unsigned char bus,
+ unsigned char addr)
+{
+ int err = 0, item = REG_POWER_MODE_CONTROL;
+ unsigned short val = 0x7; /* Legacy device will skip bit2 */
+
+ err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[item].offset, val);
+ return err;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_read
+ * PURPOSE:
+ * read register of transceiver
+ * PARAMETERS:
+ * bus (IN) I2C bus to be looking for
+ * addr (IN) I2C slave address of transceiver
+ * reg_item (IN) the regitster of transceiver
+ * value (OUT) pointer of current value buffer
+ * RETURNS:
+ * read success, this function returns 0.
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_read(unsigned char bus,
+ unsigned char addr,
+ int reg_item,
+ unsigned char *value)
+{
+ int err = 0;
+ unsigned short page = bms_xcvr_data_list[reg_item].page;
+ unsigned short offset = bms_xcvr_data_list[reg_item].offset;
+ unsigned char shift = bms_xcvr_data_list[reg_item].shift;
+ unsigned char width = bms_xcvr_data_list[reg_item].width;
+ unsigned char mask = ((((unsigned char)1) << (width)) - 1);
+ unsigned char val = 0;
+
+ if (offset >= SFF_UPPER_PAGE_BYTE_START) {
+ val = page;
+ if ((err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[REG_PAGE_SELECT].offset, val)) < 0) {goto quit;}
+ }
+ if ((err = bms_xcvr_i2c_read( bus, addr, offset, &val)) < 0) {goto quit;}
+ *value = ((val >> shift) & mask);
+quit:
+ return err;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_intr_mask
+ * PURPOSE:
+ * mask interrupt for initianl process
+ * PARAMETERS:
+ * bus (IN) I2C bus to be looking for
+ * addr (IN) I2C slave address of transceiver
+ * RETURNS:
+ * set success, this function returns 0.
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_intr_mask(unsigned char bus,
+ unsigned char addr)
+{
+ int err = 0, i = 0, bytes = 0;
+ unsigned short val = 0;
+
+ /* Switch to register "Hardware Interrupt Pin Masks".
+ * It starts from byte 100 of page 0 and includes the following 5 bytes.
+ * When interrupt pin masks are 0xFF, the hardware interrupt will not trigger interrupt pin of transceiver.
+ */
+ val = XCVR_HW_INTR_MASK_PAGE;
+ if ((err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[REG_PAGE_SELECT].offset, val)) < 0) {goto quit;}
+ bytes = XCVR_HW_INTR_MASK_BYTES;
+ val = DISABLE_MASK;
+ for (i = 0; i < bytes; i++) {
+ if ((err = bms_xcvr_i2c_write( bus, addr, (XCVR_HW_INTR_MASK_START + i), val)) < 0) {goto quit;}
+ }
+
+ /* Switch to register "Channel Masks".
+ * It starts from byte 242 of page 3 and includes the following 6 bytes.
+ * When interrupt pin masks are 0xFF, the channel interrupt will not trigger interrupt pin of transceiver.
+ */
+ val = XCVR_CHANNEL_INTR_MASK_PAGE;
+ if ((err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[REG_PAGE_SELECT].offset, val)) < 0) {goto quit;}
+ bytes = XCVR_CHANNEL_INTR_MASK_BYTES;
+ val = DISABLE_MASK;
+ for (i = 0; i < bytes; i++) {
+ if ((err = bms_xcvr_i2c_write( bus, addr, (XCVR_CHANNEL_INTR_MASK_START + i), val)) < 0) {goto quit;}
+ }
+quit:
+ return err;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_check_power_class
+ * PURPOSE:
+ * check power class from transceiver register
+ * PARAMETERS:
+ * xcvr_power_data (IN) power data is from Power Class byte
+ * xcvr_power_class (OUT) pointer of current value buffer
+ * RETURNS:
+ * no.
+ */
+void
+bms_xcvr_check_power_class(unsigned char xcvr_power_data,
+ unsigned char *xcvr_power_class)
+{
+ unsigned char value, power_class = 0;
+ value = xcvr_power_data & HIGH_POWER_CLASS_MASK;
+ if (value == 0)
+ value = xcvr_power_data & LEGACY_POWER_CLASS_MASK;
+ switch (value) {
+ case 0x00: power_class = 1; break;
+ case 0x40: power_class = 2; break;
+ case 0x80: power_class = 3; break;
+ case 0xC0: power_class = 4; break;
+ case 0x01: power_class = 5; break;
+ case 0x02: power_class = 6; break;
+ case 0x03: power_class = 7; break;
+ default: power_class = 1; break;
+ }
+ *xcvr_power_class = power_class;
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.h
new file mode 100644
index 000000000000..771d8b651c2a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.h
@@ -0,0 +1,25 @@
+#ifndef __BMS_XCVR_ACCESS_H__
+#define __BMS_XCVR_ACCESS_H__
+enum {
+ REG_DATA_NOT_READY = 0,
+ REG_PAGE_SELECT,
+ REG_INITIALIZATION_COMPLETE_FLAG,
+ REG_HIGH_POWER_CLASS,
+ REG_POWER_MODE_CONTROL,
+};
+
+extern unsigned char bms_xcvr_addr;
+#define XCVR_READY 0
+#define XCVR_INIT_COMPLETE 1
+#define XCVR_LEGACY_POWER 1
+#define XCVR_POWER_INIT_MASK 0x1
+
+#define POWER_CLASS_MASK 0xC3
+
+extern void bms_xcvr_check_power_class(unsigned char xcvr_read_byte, unsigned char *xcvr_power_class);
+extern int bms_xcvr_intr_mask(unsigned char bus, unsigned char addr);
+extern int bms_xcvr_read(unsigned char bus, unsigned char addr, int reg_item, unsigned char *val);
+extern int bms_xcvr_max_power_class(unsigned char bus, unsigned char addr, unsigned char legacy_power);
+extern int bms_xcvr_min_power_class(unsigned char bus, unsigned char addr);
+
+#endif /*__BMS_XCVR_ACCESS_H__*/
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_isrd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_isrd.c
new file mode 100644
index 000000000000..6f9a082a704d
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_isrd.c
@@ -0,0 +1,312 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_xcvr_isrd.c
+ *
+ * @purpose BMS switch board interrupt handler
+ *
+ * @create 2017/3/3
+ *
+ * @author yencheng.lin
+ *
+ * @history 2017/3/3: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_xcvr_servd.h"
+
+#define MASTER_CPLD_START_PORT 1
+#define SLAVE_CPLD_START_PORT 17
+
+/* MIC_FEAT_XCVR_INT : 1 means interrupt, 0 means polling */
+#define MIC_FEAT_XCVR_INT 0
+
+#if MIC_FEAT_XCVR_INT == 1
+#include
+#include
+#include
+
+#define GPE_SYSFS "/sys/firmware/acpi/interrupts/gpe%.2X"
+#define GPE_SYSFS_CHAR_NUM 40 /* ex. /sys/firmware/acpi/interrupts/gpe01 */
+#define GPE_DISABLE 0
+#define GPE_INIT_SKIP 0xFF
+#define ACPID_SOCKET_SYSFS "/var/run/acpid.socket"
+#define GPE_INTR_TAG "bms_acpi PNP0C01:00 000000%.2X 00000000"
+#define GPE_INTR_TAG_CHAR_NUM 38 /* ex. bms_acpi PNP0C01:00 00000002 00000000 */
+#endif
+
+#if MIC_FEAT_XCVR_INT == 1
+/*
+ * FEATURE:
+ * bms_gpe_event_write
+ * PURPOSE:
+ * set event to gpe
+ * PARAMETERS:
+ * gpe_num (IN) gpe number
+ * enable (IN) 1 means enable, 0 means disable, others set 0.
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_gpe_event_write(unsigned int gpe_num,
+ unsigned int enable)
+{
+ char buf[10], filename[GPE_SYSFS_CHAR_NUM] = { 0 };
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ snprintf(filename, sizeof(filename), GPE_SYSFS, gpe_num);
+ /* Open file */
+ if ((fd = open(filename, O_WRONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Write file */
+ if (enable == GPE_DISABLE) {
+ snprintf(buf, buf_size, "%s", "disable\n");
+ } else if (enable == !GPE_DISABLE) {
+ snprintf(buf, buf_size, "%s", "enable\n");
+ } else if (enable == GPE_INIT_SKIP) {
+ snprintf(buf, buf_size, "%s", "disable\n");
+ } else {
+ snprintf(buf, buf_size, "%d", 0);
+ }
+ if ((count = write(fd, buf, buf_size)) != (-1)) {;}
+ else if (enable == GPE_INIT_SKIP) {;}
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+#endif
+
+/*
+ * FEATURE:
+ * open_msq
+ * PURPOSE:
+ * open message queue
+ * PARAMETERS:
+ * qname (IN) queue name
+ * mqd (OUT) pointer of message queue description
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+open_msq(const char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_WRONLY | O_NONBLOCK), ret_code = 0;
+
+ /* open POSIX message queue */
+ if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ return -ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_isr
+ * PURPOSE:
+ * send message queue
+ * PARAMETERS:
+ * port_bmap (IN) bmap of triggered port
+ * qname (IN) queue name
+ * mq_desc (IN) message queue description
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_isr(unsigned int port_bmap,
+ char *qname,
+ mqd_t mq_desc)
+{
+ int ret_code = 0;
+ bms_xcvr_serv_mq_data_t msg;
+
+ msg.intr_type = INTR_TYPE_RX_INTR;
+ msg.port_bmap = port_bmap;
+
+ if (mq_send(mq_desc, (const char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ if (ret_code == EAGAIN) {
+ syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", qname);
+ }
+ else {
+ syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", qname, strerror(ret_code));
+ }
+ }
+
+ return -ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_isrd
+ * PURPOSE:
+ * wait for interrupt and call bms_xcvr_isr function
+ * PARAMETERS:
+ * args (IN) base port number by master or slave CPLD
+ * RETURNS:
+ * no.
+ */
+void*
+bms_xcvr_isrd(void *args)
+{
+ mqd_t mq_handle;
+ unsigned int port_num = *(unsigned int *)args, start_port, end_port, value = 0;
+ unsigned int irq_trigger_bmap = 0, intr_msk_bmap = 0, intr_msk_cache_bmap = 0;
+ int i, ret_code = 0;
+#if MIC_FEAT_XCVR_INT == 1
+ int socket_dsc = 0;
+ struct sockaddr_un socket_addr;
+ char buf[GPE_INTR_TAG_CHAR_NUM],gpe_tag[GPE_INTR_TAG_CHAR_NUM];
+ unsigned int gpe_num = 0x0;
+#endif
+ /* Initial of bms_xcvr_isrd */
+
+ /* 1. the ISR is for master or slave CPLD */
+ if (port_num == MASTER_CPLD_START_PORT) {
+ start_port = MASTER_CPLD_START_PORT - 1;
+#if MIC_FEAT_XCVR_INT == 1
+ gpe_num = 0x47;
+#endif
+ } else if (port_num == SLAVE_CPLD_START_PORT) {
+ start_port = SLAVE_CPLD_START_PORT - 1;
+#if MIC_FEAT_XCVR_INT == 1
+ gpe_num = 0x2;
+#endif
+ }
+ end_port = start_port + (SLAVE_CPLD_START_PORT - MASTER_CPLD_START_PORT);
+
+ /* 2. Open message queue */
+ if (open_msq(xcvrirq_data[0].mq_name, &mq_handle) < 0) {
+ goto quit;
+ }
+
+#if MIC_FEAT_XCVR_INT == 1
+ snprintf(gpe_tag, sizeof(gpe_tag), GPE_INTR_TAG, gpe_num);
+ /* set default value for GPE status */
+ bms_gpe_event_write(gpe_num, GPE_INIT_SKIP);
+
+ /* 3. Open the acpi socket. */
+ if ((socket_dsc = socket(AF_UNIX, SOCK_STREAM, 0)) == (-1)) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code));
+ goto quit;
+ }
+ socket_addr.sun_family = AF_UNIX;
+ strcpy(socket_addr.sun_path, ACPID_SOCKET_SYSFS);
+ if (connect(socket_dsc, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) == (-1)) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to connect ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code));
+ goto quit;
+ }
+#endif
+
+ while (1) {
+#if MIC_FEAT_XCVR_INT == 1
+ /* 3. Enable IRQ */
+ if((ret_code = bms_gpe_event_write(gpe_num, !GPE_DISABLE)) < 0)
+ goto quit;
+
+ /* Wait for interrupt occurs; this is a blocking call and may leave
+ * the blocking state unexpectly while receiving a signal. In such
+ * a case, we go back to wait for the arriving of interrupt.
+ */
+wait_irq:
+ memset(buf,0,sizeof(buf));
+ if (recv(socket_dsc, buf, sizeof(buf), 0) <= 0) {
+ if (errno == EINTR) {goto wait_irq;}
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code));
+ goto quit;
+ }
+ if (!strncmp(buf, gpe_tag, sizeof(gpe_tag)-1)) {
+ /* Due to bms_gpe hanlder does not set disable now. */
+ if((ret_code = bms_gpe_event_write(gpe_num, GPE_DISABLE)) < 0)
+ goto quit;
+ } else {
+ goto wait_irq;
+ }
+#else
+ usleep(100000);
+#endif
+
+ /* Detect xcvr interrupt pin - mark irq_trigger_bmap from xcvr interrupt pin */
+ /* Detect which source(s) trigger the interrupt from 16 port */
+ for (i = (int)start_port, irq_trigger_bmap = 0; i < (int)end_port; i++) {
+ if (xcvrirq_data[i].intr_src) {
+ if ((ret_code = bms_xcvr_pin_read(xcvrirq_data[i].intr_src, &value)) < 0) {
+ goto quit;
+ }
+ irq_trigger_bmap |= ((~value & 0xff) << i);
+ }
+ }
+
+ /* send event with irq_trigger_bmap */
+ if (irq_trigger_bmap) {
+ /* 1. enable irq_trigger_bmap that triggers the interrupt mask */
+ /* Read irq_msk pin from cache */
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ bms_xcvr_data_read(XCVR_INTR_MSK, &intr_msk_cache_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ intr_msk_bmap = intr_msk_cache_bmap;
+
+ /* Disable the source that triggers the interrupt mask */
+ bms_xcvr_bmap_modify( &intr_msk_bmap, irq_trigger_bmap, INTR_MASK_EN);
+
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_INTR_MSK, intr_msk_bmap, intr_msk_cache_bmap)) < 0) {
+ goto quit;
+ }
+ bms_xcvr_data_write(XCVR_INTR_MSK, intr_msk_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ bms_xcvr_bmap_to_num(irq_trigger_bmap);
+ syslog(LOG_DEBUG|LOG_USER,"Interrupt port %s arrivals.\n", bms_xcvr_bmap_to_num_str);
+ /* 2. send event to message queue */
+ /* Call interrupt service routine (ISR) with only one queue name (xcvrirq_data[0]) */
+ xcvrirq_data[start_port].isr(irq_trigger_bmap, xcvrirq_data[0].mq_name, mq_handle);
+ } else {
+#if MIC_FEAT_XCVR_INT == 1
+ /* Log unknown interrupt */
+ syslog(LOG_WARNING|LOG_USER,"Receive unknown interrupt from port%d - port%d (%s)\n", start_port + 1, end_port, buf);
+#endif
+ }
+ }
+
+quit:
+ syslog(LOG_WARNING|LOG_USER,"Quit thread from %s function (port%d - port%d)\n", __func__, start_port + 1, end_port);
+#if MIC_FEAT_XCVR_INT == 1
+ close(socket_dsc);
+#endif
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_polld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_polld.c
new file mode 100644
index 000000000000..310301f8c955
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_polld.c
@@ -0,0 +1,418 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_xcvr_polld.c
+ *
+ * @purpose BMS switch board polling present pin of all port
+ *
+ * @create 2017/3/15
+ *
+ * @author yencheng.lin
+ *
+ * @history 2017/3/15: init version
+ *
+ **********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_xcvr_servd.h"
+#include
+
+pthread_mutex_t bms_xcvr_data_lock;
+pthread_t polld_tid;
+
+/* Set default value based on CPLD spec */
+unsigned int bms_xcvr_present_cache_bmap = 0xFFFFFFFF;/* ~PRESENT_EN */
+unsigned int bms_xcvr_reset_cache_bmap = 0x0;/* RST_EN */
+unsigned int bms_xcvr_modsel_cache_bmap = 0xFFFFFFFF;/* ~MODSEL_EN */
+unsigned int bms_xcvr_intr_msk_cache_bmap = 0x0;/* INTR_MASK_EN */
+unsigned int bms_xcvr_init_done_cache_bmap = 0x0;/* ~INIT_DONE_EN */
+unsigned int bms_xcvr_lpmode_cache_bmap = 0x0;/* LPMODE_DIS */
+
+/*
+ * FEATURE:
+ * bms_xcvr_pin_read
+ * PURPOSE:
+ * read pin status from file of sysfs
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * value (OUT) pointer of current value buffer
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_pin_read(char *filename,
+ unsigned int *value)
+{
+ char buf[32] = {0};
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ /* Open xcvr pin file */
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Read pin file */
+ if ((count = read(fd, buf, buf_size)) != (-1)) {
+ *value = strtol(buf, NULL, 16);
+ }
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_pin_write
+ * PURPOSE:
+ * write value to file of sysfs
+ * PARAMETERS:
+ * filename (IN) file path in the sysfs
+ * value (IN) new register value
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_pin_write(char *filename,
+ unsigned int value)
+{
+ char buf[3];
+ int fd, ret_code = 0, buf_size = sizeof(buf);
+ ssize_t count;
+
+ /* Open file */
+ if ((fd = open(filename, O_WRONLY)) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code));
+ return -ret_code;
+ }
+
+ /* Write file */
+ snprintf(buf, buf_size, "%x", value);
+ if ((count = write(fd, buf, buf_size)) != (-1)) {;}
+ else {
+ ret_code = (count >= 0) ? EIO : errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code));
+ close(fd);
+ return -ret_code;
+ }
+
+ close(fd);
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_data_read
+ * PURPOSE:
+ * read pin status from data base
+ * PARAMETERS:
+ * pin_num (IN) the number means different pin name
+ * value (OUT) pointer of current value buffer
+ * RETURNS:
+ * no
+ */
+void
+bms_xcvr_data_read(int pin_num,
+ unsigned int *value)
+{
+ switch (pin_num) {
+ case XCVR_PRESENT:
+ *value = bms_xcvr_present_cache_bmap;
+ break;
+ case XCVR_MODSEL:
+ *value = bms_xcvr_modsel_cache_bmap;
+ break;
+ case XCVR_RESET:
+ *value = bms_xcvr_reset_cache_bmap;
+ break;
+ case XCVR_INTR_MSK:
+ *value = bms_xcvr_intr_msk_cache_bmap;
+ break;
+ case XCVR_INIT_DONE:
+ *value = bms_xcvr_init_done_cache_bmap;
+ break;
+ case XCVR_LPMODE:
+ *value = bms_xcvr_lpmode_cache_bmap;
+ break;
+ default:
+ *value = 0;
+ break;
+ }
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_data_write
+ * PURPOSE:
+ * write new value to data base
+ * PARAMETERS:
+ * pin_num (IN) the number means different pin name
+ * value (IN) new register value
+ * RETURNS:
+ * no.
+ */
+void
+bms_xcvr_data_write(int pin_num,
+ unsigned int value)
+{
+ switch (pin_num) {
+ case XCVR_PRESENT:
+ bms_xcvr_present_cache_bmap = value;
+ break;
+ case XCVR_MODSEL:
+ bms_xcvr_modsel_cache_bmap = value;
+ break;
+ case XCVR_RESET:
+ bms_xcvr_reset_cache_bmap = value;
+ break;
+ case XCVR_INTR_MSK:
+ bms_xcvr_intr_msk_cache_bmap = value;
+ break;
+ case XCVR_INIT_DONE:
+ bms_xcvr_init_done_cache_bmap = value;
+ break;
+ case XCVR_LPMODE:
+ bms_xcvr_lpmode_cache_bmap = value;
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_pin_bmap_write
+ * PURPOSE:
+ * write bmap to file of sysfs
+ * PARAMETERS:
+ * pin_num (IN) the number means different pin name
+ * value (IN) new register value
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_pin_bmap_write(int pin_num,
+ unsigned int value)
+{
+ int ret_code = 0, i;
+ unsigned int val = 0;
+
+ for(i = 0; i < xcvrirq_data_num; i++) {
+ if (xcvrirq_data[i].present) {
+ val = (value >> i) & 0xff;
+ switch (pin_num) {
+ case XCVR_PRESENT:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].present, val);
+ break;
+ case XCVR_MODSEL:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].modsel, val);
+ break;
+ case XCVR_RESET:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].reset, val);
+ break;
+ case XCVR_INTR_MSK:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_msk, val);
+ break;
+ case XCVR_INTR_SRC:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_src, val);
+ break;
+ case XCVR_LPMODE:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].lpmode, val);
+ break;
+ default:
+ ret_code = -ENOTSUP;
+ break;
+ }
+ if (ret_code < 0)
+ goto quit;
+ }
+ }
+quit:
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_pin_bmap_modify
+ * PURPOSE:
+ * write bmap to file of sysfs if the value is modified
+ * PARAMETERS:
+ * pin_num (IN) the number means different pin name
+ * value (IN) new register value
+ * old_value (IN) last register value
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_pin_bmap_modify(int pin_num,
+ unsigned int value,
+ unsigned int old_value)
+{
+ int ret_code = 0, i;
+ unsigned int val = 0;
+
+ for(i = 0; i < xcvrirq_data_num; i++) {
+ if (xcvrirq_data[i].present && (((old_value ^ value) >> i) & 0xff) ) {
+ val = (value >> i) & 0xff;
+ switch (pin_num) {
+ case XCVR_PRESENT:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].present, val);
+ break;
+ case XCVR_MODSEL:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].modsel, val);
+ break;
+ case XCVR_RESET:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].reset, val);
+ break;
+ case XCVR_INTR_MSK:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_msk, val);
+ break;
+ case XCVR_INTR_SRC:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_src, val);
+ break;
+ case XCVR_LPMODE:
+ ret_code = bms_xcvr_pin_write(xcvrirq_data[i].lpmode, val);
+ break;
+ default:
+ ret_code = -ENOTSUP;
+ break;
+ }
+ if (ret_code < 0)
+ goto quit;
+ }
+ }
+quit:
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_polld
+ * PURPOSE:
+ * poll present pin for each port
+ * PARAMETERS:
+ * args (IN) NULL
+ * RETURNS:
+ * No.
+ */
+void* bms_xcvr_polld(void *args)
+{
+ int ret_code = 0, i = *(int*)args;
+ unsigned int present_bmap, present_cache_bmap, present_switch_bmap;
+ unsigned int reset_bmap, reset_cache_bmap;
+ unsigned int modsel_bmap, modsel_cache_bmap;
+ unsigned int xcvr_insert_bmap, xcvr_remove_bmap, value, init_done_cache_bmap;
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ unsigned int lpmode_bmap, lpmode_cache_bmap;
+#endif
+
+ while (1) {
+
+ /* Detect xcvr present pin */
+ /* 1. read present pin of all xcvr */
+ for (i = 0, present_bmap = 0; i < xcvrirq_data_num; i++) {
+ if (xcvrirq_data[i].present) {
+ if ((ret_code = bms_xcvr_pin_read(xcvrirq_data[i].present, &value)) < 0) {
+ goto quit;
+ }
+ present_bmap |= (value << i);
+ }
+ }
+
+ /* 2. read present,reset,modsel status from database*/
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ bms_xcvr_data_read(XCVR_PRESENT, &present_cache_bmap);
+ bms_xcvr_data_read(XCVR_RESET, &reset_cache_bmap);
+ bms_xcvr_data_read(XCVR_MODSEL, &modsel_cache_bmap);
+ bms_xcvr_data_read(XCVR_INIT_DONE, &init_done_cache_bmap);
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ bms_xcvr_data_read(XCVR_LPMODE, &lpmode_cache_bmap);
+#endif
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ reset_bmap = reset_cache_bmap;
+ modsel_bmap = modsel_cache_bmap;
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ lpmode_bmap = lpmode_cache_bmap;
+#endif
+
+ /* 3. mark present_switch_bmap if switching present pin (present <-> absent)*/
+ present_switch_bmap = present_bmap ^ present_cache_bmap;
+
+ /* Handle present_switch_bmap */
+ if (present_switch_bmap) {
+
+ /* 1. filter to xcvr_insert_bmap and xcvr_remove_bmap */
+ xcvr_insert_bmap = (present_switch_bmap & ~present_bmap);
+ xcvr_remove_bmap = (present_switch_bmap & present_bmap);
+
+ /* 2. deassert reset pin for xcvr insert port */
+ bms_xcvr_bmap_modify( &reset_bmap, xcvr_insert_bmap, ~RST_EN);
+ /* 3. assert reset pin for xcvr remove port */
+ bms_xcvr_bmap_modify( &reset_bmap, xcvr_remove_bmap, RST_EN);
+
+ /* 4. For suppot DAC to enable modsel for xcvr insert port */
+ bms_xcvr_bmap_modify( &modsel_bmap, xcvr_insert_bmap, MODSEL_EN);
+ /* 4. No matter what status , set unmodsel for remove port */
+ bms_xcvr_bmap_modify( &modsel_bmap, xcvr_remove_bmap, ~MODSEL_EN);
+
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ /* 4. No matter what status , set low power mode for remove port */
+ bms_xcvr_bmap_modify( &lpmode_bmap, xcvr_remove_bmap, ~LPMODE_DIS);
+#endif
+
+ /* 5. Cancel init_done port for xcvr remove port */
+ init_done_cache_bmap &= ~xcvr_remove_bmap;
+
+ /* Write present,reset,modsel,init_done pin status of present switch port to database*/
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_RESET, reset_bmap, reset_cache_bmap)) < 0) {
+ goto quit;
+ }
+ if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_MODSEL, modsel_bmap, modsel_cache_bmap)) < 0) {
+ goto quit;
+ }
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_LPMODE, lpmode_bmap, lpmode_cache_bmap)) < 0) {
+ goto quit;
+ }
+ bms_xcvr_data_write(XCVR_LPMODE, lpmode_bmap);
+#endif
+ bms_xcvr_data_write(XCVR_PRESENT, present_bmap);
+ bms_xcvr_data_write(XCVR_RESET, reset_bmap);
+ bms_xcvr_data_write(XCVR_MODSEL, modsel_bmap);
+ bms_xcvr_data_write(XCVR_INIT_DONE, init_done_cache_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+ }
+ sleep(1);
+ }
+
+quit:
+ syslog(LOG_DEBUG|LOG_USER,"Quit thread from %s function (%s)\n", __func__, strerror(ret_code));
+ pthread_exit(NULL);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.c
new file mode 100644
index 000000000000..b1ccc6d0bf00
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.c
@@ -0,0 +1,983 @@
+/*
+ **********************************************************************
+ *
+ * @filename bms_xcvr_servd.c
+ *
+ * @purpose BMS switch board interrupt handler
+ *
+ * @create 2017/3/3
+ *
+ * @author yencheng.lin
+ *
+ * @history 2017/3/3: init version
+ *
+ **********************************************************************
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bms_xcvr_servd.h"
+#include "bms_xcvr_access.h"
+
+#define PROC_PRIORITY 90
+/* The XCVR_LPMODE_PIN_USE is used when system can not acces with transceiver eeprom */
+#define XCVR_LPMODE_PIN_USE 0
+
+#define STR_LEN 100
+char bms_xcvr_bmap_to_num_str[STR_LEN] = { 0 };
+
+extern int bms_xcvr_isr(unsigned int port_num, char *qname, mqd_t mq_desc);
+extern void* bms_xcvr_isrd(void *args);
+
+extern pthread_mutex_t bms_xcvr_data_lock;
+extern void* bms_xcvr_polld(void *args);
+extern pthread_t polld_tid;
+
+bms_xcvr_serv_data_t xcvrirq_data[] = {
+ {
+ .port_num = 1,
+ .present = "/sys/bus/i2c/devices/1-0032/port_1_8_present",
+ .intr_src = "/sys/bus/i2c/devices/1-0032/port_1_8_irq_status",
+ .intr_msk = "/sys/bus/i2c/devices/1-0032/port_1_8_irq_msk",
+ .modsel = "/sys/bus/i2c/devices/1-0032/port_1_8_modsel",
+ .lpmode = "/sys/bus/i2c/devices/1-0032/port_1_8_lpmode",
+ .reset = "/sys/bus/i2c/devices/1-0032/port_1_8_rst",
+ .mq_name = "/xcvr_isr_mq",
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = bms_xcvr_isrd,
+ .smbus_num= 10,
+ },
+ {
+ .port_num = 2,
+ .present = NULL, /* Share same byte with PORT1 */
+ .intr_src = NULL, /* Share same byte with PORT1 */
+ .intr_msk = NULL, /* Share same byte with PORT1 */
+ .modsel = NULL, /* Share same byte with PORT1 */
+ .lpmode = NULL, /* Share same byte with PORT1 */
+ .reset = NULL, /* Share same byte with PORT1 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 11,
+ },
+ {
+ .port_num = 3,
+ .present = NULL, /* Share same byte with PORT1 */
+ .intr_src = NULL, /* Share same byte with PORT1 */
+ .intr_msk = NULL, /* Share same byte with PORT1 */
+ .modsel = NULL, /* Share same byte with PORT1 */
+ .lpmode = NULL, /* Share same byte with PORT1 */
+ .reset = NULL, /* Share same byte with PORT1 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 12,
+ },
+ {
+ .port_num = 4,
+ .present = NULL, /* Share same byte with PORT1 */
+ .intr_src = NULL, /* Share same byte with PORT1 */
+ .intr_msk = NULL, /* Share same byte with PORT1 */
+ .modsel = NULL, /* Share same byte with PORT1 */
+ .lpmode = NULL, /* Share same byte with PORT1 */
+ .reset = NULL, /* Share same byte with PORT1 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 13,
+ },
+ {
+ .port_num = 5,
+ .present = NULL, /* Share same byte with PORT1 */
+ .intr_src = NULL, /* Share same byte with PORT1 */
+ .intr_msk = NULL, /* Share same byte with PORT1 */
+ .modsel = NULL, /* Share same byte with PORT1 */
+ .lpmode = NULL, /* Share same byte with PORT1 */
+ .reset = NULL, /* Share same byte with PORT1 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 14,
+ },
+ {
+ .port_num = 6,
+ .present = NULL, /* Share same byte with PORT1 */
+ .intr_src = NULL, /* Share same byte with PORT1 */
+ .intr_msk = NULL, /* Share same byte with PORT1 */
+ .modsel = NULL, /* Share same byte with PORT1 */
+ .lpmode = NULL, /* Share same byte with PORT1 */
+ .reset = NULL, /* Share same byte with PORT1 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 15,
+ },
+ {
+ .port_num = 7,
+ .present = NULL, /* Share same byte with PORT1 */
+ .intr_src = NULL, /* Share same byte with PORT1 */
+ .intr_msk = NULL, /* Share same byte with PORT1 */
+ .modsel = NULL, /* Share same byte with PORT1 */
+ .lpmode = NULL, /* Share same byte with PORT1 */
+ .reset = NULL, /* Share same byte with PORT1 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 16,
+ },
+ {
+ .port_num = 8,
+ .present = NULL, /* Share same byte with PORT1 */
+ .intr_src = NULL, /* Share same byte with PORT1 */
+ .intr_msk = NULL, /* Share same byte with PORT1 */
+ .modsel = NULL, /* Share same byte with PORT1 */
+ .lpmode = NULL, /* Share same byte with PORT1 */
+ .reset = NULL, /* Share same byte with PORT1 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 17,
+ },
+ {
+ .port_num = 9,
+ .present = "/sys/bus/i2c/devices/1-0032/port_9_16_present",
+ .intr_src = "/sys/bus/i2c/devices/1-0032/port_9_16_irq_status",
+ .intr_msk = "/sys/bus/i2c/devices/1-0032/port_9_16_irq_msk",
+ .modsel = "/sys/bus/i2c/devices/1-0032/port_9_16_modsel",
+ .lpmode = "/sys/bus/i2c/devices/1-0032/port_9_16_lpmode",
+ .reset = "/sys/bus/i2c/devices/1-0032/port_9_16_rst",
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 18,
+ },
+ {
+ .port_num = 10,
+ .present = NULL, /* Share same byte with PORT9 */
+ .intr_src = NULL, /* Share same byte with PORT9 */
+ .intr_msk = NULL, /* Share same byte with PORT9 */
+ .modsel = NULL, /* Share same byte with PORT9 */
+ .lpmode = NULL, /* Share same byte with PORT9 */
+ .reset = NULL, /* Share same byte with PORT9 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 19,
+ },
+ {
+ .port_num = 11,
+ .present = NULL, /* Share same byte with PORT9 */
+ .intr_src = NULL, /* Share same byte with PORT9 */
+ .intr_msk = NULL, /* Share same byte with PORT9 */
+ .modsel = NULL, /* Share same byte with PORT9 */
+ .lpmode = NULL, /* Share same byte with PORT9 */
+ .reset = NULL, /* Share same byte with PORT9 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 20,
+ },
+ {
+ .port_num = 12,
+ .present = NULL, /* Share same byte with PORT9 */
+ .intr_src = NULL, /* Share same byte with PORT9 */
+ .intr_msk = NULL, /* Share same byte with PORT9 */
+ .modsel = NULL, /* Share same byte with PORT9 */
+ .lpmode = NULL, /* Share same byte with PORT9 */
+ .reset = NULL, /* Share same byte with PORT9 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 21,
+ },
+ {
+ .port_num = 13,
+ .present = NULL, /* Share same byte with PORT9 */
+ .intr_src = NULL, /* Share same byte with PORT9 */
+ .intr_msk = NULL, /* Share same byte with PORT9 */
+ .modsel = NULL, /* Share same byte with PORT9 */
+ .lpmode = NULL, /* Share same byte with PORT9 */
+ .reset = NULL, /* Share same byte with PORT9 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 22,
+ },
+ {
+ .port_num = 14,
+ .present = NULL, /* Share same byte with PORT9 */
+ .intr_src = NULL, /* Share same byte with PORT9 */
+ .intr_msk = NULL, /* Share same byte with PORT9 */
+ .modsel = NULL, /* Share same byte with PORT9 */
+ .lpmode = NULL, /* Share same byte with PORT9 */
+ .reset = NULL, /* Share same byte with PORT9 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 23,
+ },
+ {
+ .port_num = 15,
+ .present = NULL, /* Share same byte with PORT9 */
+ .intr_src = NULL, /* Share same byte with PORT9 */
+ .intr_msk = NULL, /* Share same byte with PORT9 */
+ .modsel = NULL, /* Share same byte with PORT9 */
+ .lpmode = NULL, /* Share same byte with PORT9 */
+ .reset = NULL, /* Share same byte with PORT9 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 24,
+ },
+ {
+ .port_num = 16,
+ .present = NULL, /* Share same byte with PORT9 */
+ .intr_src = NULL, /* Share same byte with PORT9 */
+ .intr_msk = NULL, /* Share same byte with PORT9 */
+ .modsel = NULL, /* Share same byte with PORT9 */
+ .lpmode = NULL, /* Share same byte with PORT9 */
+ .reset = NULL, /* Share same byte with PORT9 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */
+ .smbus_num= 25,
+ },
+ {
+ .port_num = 17,
+ .present = "/sys/bus/i2c/devices/1-0033/port_17_24_present",
+ .intr_src = "/sys/bus/i2c/devices/1-0033/port_17_24_irq_status",
+ .intr_msk = "/sys/bus/i2c/devices/1-0033/port_17_24_irq_msk",
+ .modsel = "/sys/bus/i2c/devices/1-0033/port_17_24_modsel",
+ .lpmode = "/sys/bus/i2c/devices/1-0033/port_17_24_lpmode",
+ .reset = "/sys/bus/i2c/devices/1-0033/port_17_24_rst",
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = bms_xcvr_isrd,
+ .smbus_num= 26,
+ },
+ {
+ .port_num = 18,
+ .present = NULL, /* Share same byte with PORT17 */
+ .intr_src = NULL, /* Share same byte with PORT17 */
+ .intr_msk = NULL, /* Share same byte with PORT17 */
+ .modsel = NULL, /* Share same byte with PORT17 */
+ .lpmode = NULL, /* Share same byte with PORT17 */
+ .reset = NULL, /* Share same byte with PORT17 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 27,
+ },
+ {
+ .port_num = 19,
+ .present = NULL, /* Share same byte with PORT17 */
+ .intr_src = NULL, /* Share same byte with PORT17 */
+ .intr_msk = NULL, /* Share same byte with PORT17 */
+ .modsel = NULL, /* Share same byte with PORT17 */
+ .lpmode = NULL, /* Share same byte with PORT17 */
+ .reset = NULL, /* Share same byte with PORT17 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 28,
+ },
+ {
+ .port_num = 20,
+ .present = NULL, /* Share same byte with PORT17 */
+ .intr_src = NULL, /* Share same byte with PORT17 */
+ .intr_msk = NULL, /* Share same byte with PORT17 */
+ .modsel = NULL, /* Share same byte with PORT17 */
+ .lpmode = NULL, /* Share same byte with PORT17 */
+ .reset = NULL, /* Share same byte with PORT17 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 29,
+ },
+ {
+ .port_num = 21,
+ .present = NULL, /* Share same byte with PORT17 */
+ .intr_src = NULL, /* Share same byte with PORT17 */
+ .intr_msk = NULL, /* Share same byte with PORT17 */
+ .modsel = NULL, /* Share same byte with PORT17 */
+ .lpmode = NULL, /* Share same byte with PORT17 */
+ .reset = NULL, /* Share same byte with PORT17 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 30,
+ },
+ {
+ .port_num = 22,
+ .present = NULL, /* Share same byte with PORT17 */
+ .intr_src = NULL, /* Share same byte with PORT17 */
+ .intr_msk = NULL, /* Share same byte with PORT17 */
+ .modsel = NULL, /* Share same byte with PORT17 */
+ .lpmode = NULL, /* Share same byte with PORT17 */
+ .reset = NULL, /* Share same byte with PORT17 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 31,
+ },
+ {
+ .port_num = 23,
+ .present = NULL, /* Share same byte with PORT17 */
+ .intr_src = NULL, /* Share same byte with PORT17 */
+ .intr_msk = NULL, /* Share same byte with PORT17 */
+ .modsel = NULL, /* Share same byte with PORT17 */
+ .lpmode = NULL, /* Share same byte with PORT17 */
+ .reset = NULL, /* Share same byte with PORT17 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 32,
+ },
+ {
+ .port_num = 24,
+ .present = NULL, /* Share same byte with PORT17 */
+ .intr_src = NULL, /* Share same byte with PORT17 */
+ .intr_msk = NULL, /* Share same byte with PORT17 */
+ .modsel = NULL, /* Share same byte with PORT17 */
+ .lpmode = NULL, /* Share same byte with PORT17 */
+ .reset = NULL, /* Share same byte with PORT17 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 33,
+ },
+ {
+ .port_num = 25,
+ .present = "/sys/bus/i2c/devices/1-0033/port_25_32_present",
+ .intr_src = "/sys/bus/i2c/devices/1-0033/port_25_32_irq_status",
+ .intr_msk = "/sys/bus/i2c/devices/1-0033/port_25_32_irq_msk",
+ .modsel = "/sys/bus/i2c/devices/1-0033/port_25_32_modsel",
+ .lpmode = "/sys/bus/i2c/devices/1-0033/port_25_32_lpmode",
+ .reset = "/sys/bus/i2c/devices/1-0033/port_25_32_rst",
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 34,
+ },
+ {
+ .port_num = 26,
+ .present = NULL, /* Share same byte with PORT25 */
+ .intr_src = NULL, /* Share same byte with PORT25 */
+ .intr_msk = NULL, /* Share same byte with PORT25 */
+ .modsel = NULL, /* Share same byte with PORT25 */
+ .lpmode = NULL, /* Share same byte with PORT25 */
+ .reset = NULL, /* Share same byte with PORT25 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 35,
+ },
+ {
+ .port_num = 27,
+ .present = NULL, /* Share same byte with PORT25 */
+ .intr_src = NULL, /* Share same byte with PORT25 */
+ .intr_msk = NULL, /* Share same byte with PORT25 */
+ .modsel = NULL, /* Share same byte with PORT25 */
+ .lpmode = NULL, /* Share same byte with PORT25 */
+ .reset = NULL, /* Share same byte with PORT25 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 36,
+ },
+ {
+ .port_num = 28,
+ .present = NULL, /* Share same byte with PORT25 */
+ .intr_src = NULL, /* Share same byte with PORT25 */
+ .intr_msk = NULL, /* Share same byte with PORT25 */
+ .modsel = NULL, /* Share same byte with PORT25 */
+ .lpmode = NULL, /* Share same byte with PORT25 */
+ .reset = NULL, /* Share same byte with PORT25 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 37,
+ },
+ {
+ .port_num = 29,
+ .present = NULL, /* Share same byte with PORT25 */
+ .intr_src = NULL, /* Share same byte with PORT25 */
+ .intr_msk = NULL, /* Share same byte with PORT25 */
+ .modsel = NULL, /* Share same byte with PORT25 */
+ .lpmode = NULL, /* Share same byte with PORT25 */
+ .reset = NULL, /* Share same byte with PORT25 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 38,
+ },
+ {
+ .port_num = 30,
+ .present = NULL, /* Share same byte with PORT25 */
+ .intr_src = NULL, /* Share same byte with PORT25 */
+ .intr_msk = NULL, /* Share same byte with PORT25 */
+ .modsel = NULL, /* Share same byte with PORT25 */
+ .lpmode = NULL, /* Share same byte with PORT25 */
+ .reset = NULL, /* Share same byte with PORT25 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 39,
+ },
+ {
+ .port_num = 31,
+ .present = NULL, /* Share same byte with PORT25 */
+ .intr_src = NULL, /* Share same byte with PORT25 */
+ .intr_msk = NULL, /* Share same byte with PORT25 */
+ .modsel = NULL, /* Share same byte with PORT25 */
+ .lpmode = NULL, /* Share same byte with PORT25 */
+ .reset = NULL, /* Share same byte with PORT25 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 40,
+ },
+ {
+ .port_num = 32,
+ .present = NULL, /* Share same byte with PORT25 */
+ .intr_src = NULL, /* Share same byte with PORT25 */
+ .intr_msk = NULL, /* Share same byte with PORT25 */
+ .modsel = NULL, /* Share same byte with PORT25 */
+ .lpmode = NULL, /* Share same byte with PORT25 */
+ .reset = NULL, /* Share same byte with PORT25 */
+ .mq_name = NULL, /* Share same message queue with PORT1 */
+ .mq_desc = (mqd_t)-1,
+ .isr = bms_xcvr_isr,
+ .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */
+ .smbus_num= 41,
+ },
+};
+int xcvrirq_data_num = sizeof(xcvrirq_data) / sizeof(xcvrirq_data[0]);
+
+/*
+ * FEATURE:
+ * bms_xcvr_create_msq
+ * PURPOSE:
+ * Create POSIX message queue
+ * PARAMETERS:
+ * qname (IN) I2C bus to be looking for
+ * mqd (OUT) pointer of message queue description
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+bms_xcvr_create_msq(char *qname,
+ mqd_t *mqd)
+{
+ int flags = (O_CREAT | O_EXCL | O_RDONLY), ret_code = 0;
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+ struct mq_attr attr = {
+ .mq_maxmsg = 64,
+ .mq_msgsize = sizeof(bms_xcvr_serv_mq_data_t),
+ };
+
+ /* destroy message queue if it presents */
+ if ((mq_unlink(qname) < 0) && (errno != ENOENT)) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to destroy message queue %s (%s)\n", qname, strerror(ret_code));
+ }
+
+ /* create POSIX message queue */
+ if ((*mqd = mq_open(qname, flags, mode, &attr)) == (mqd_t)-1) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to create message queue %s (%s)\n", qname, strerror(ret_code));
+ return -ret_code;
+ }
+
+ syslog(LOG_DEBUG|LOG_USER,"Create message queue %s\n", qname);
+
+ return -ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_terminator
+ * PURPOSE:
+ * restore xcvr pin status based on CPLD spec when system reboot/halt
+ * PARAMETERS:
+ * sig (IN) system signature
+ * RETURNS:
+ * no.
+ */
+void
+bms_xcvr_terminator(int sig)
+{
+ char *mq_name = xcvrirq_data[0].mq_name;
+ if (sig) {;}
+
+ /* disable interrupt function */
+ bms_xcvr_pin_bmap_write(XCVR_INTR_MSK, INTR_MASK_EN);
+
+ /* disable module select function */
+ bms_xcvr_pin_bmap_write(XCVR_MODSEL, ~MODSEL_EN);
+
+ /* assert reset function */
+ bms_xcvr_pin_bmap_write(XCVR_RESET, RST_EN);
+
+ /* assert lpmode function */
+ bms_xcvr_pin_bmap_write(XCVR_LPMODE, ~LPMODE_DIS);
+
+ /* destroy message queue */
+ mq_unlink(mq_name);
+
+ /* destroy mutex lock */
+ pthread_mutex_destroy(&bms_xcvr_data_lock);
+
+ syslog(LOG_DEBUG|LOG_USER,"Terminate %s\n", __FILE__);
+
+ exit(0);
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_bmap_modify
+ * PURPOSE:
+ * modify the status of pin bmap
+ * PARAMETERS:
+ * changed_bmap (OUT) pointer of pin bmap
+ * check_bmap (IN) modified when the bit is 1.
+ * switch_status (IN) status that it will switch
+ * RETURNS:
+ * no.
+ */
+void
+bms_xcvr_bmap_modify(unsigned int *changed_bmap,
+ unsigned int check_bmap,
+ unsigned int switch_status)
+{
+ if ( switch_status ) {
+ *changed_bmap |= check_bmap;
+ } else {
+ *changed_bmap &= ~check_bmap;
+ }
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_bmap_to_num
+ * PURPOSE:
+ * translate to number from bit-map
+ * PARAMETERS:
+ * bmap (IN) bit-map.
+ * RETURNS:
+ * no.
+ */
+void bms_xcvr_bmap_to_num(unsigned int bmap)
+{
+ char temp[4] = { 0 };
+ int i, first = 1;
+ memset(bms_xcvr_bmap_to_num_str, 0, sizeof(bms_xcvr_bmap_to_num_str));
+ for (i = 0; i < xcvrirq_data_num; i++) {
+ if (bmap & (((unsigned int)1) << i)) {
+ if (first) {
+ snprintf(temp, sizeof(temp), "%d", i + 1);
+ first = 0;
+ } else {
+ snprintf(temp, sizeof(temp), ",%d", i + 1);
+ }
+ strncat(bms_xcvr_bmap_to_num_str, temp, 4);
+ }
+ }
+}
+
+/*
+* FEATURE:
+* bms_xcvr_mutex_init
+* PURPOSE:
+* initial mutex
+* PARAMETERS:
+*
+* RETURNS:
+* init success, this function shall return zero.
+* otherwise, an error number shall be returned to indicate the error.
+*/
+static int
+bms_xcvr_mutex_init(void)
+{
+ int ret_code;
+
+ if((ret_code = pthread_mutex_init(&bms_xcvr_data_lock, NULL)) != 0){
+ return -ret_code;
+ }
+
+ return ret_code;
+}
+
+/*
+ * FEATURE:
+ * bms_xcvr_reset
+ * PURPOSE:
+ * reset transceiver
+ * PARAMETERS:
+ * bmap (IN) port bmap for reset
+ * RETURNS:
+ * no.
+ */
+static int
+bms_xcvr_reset(unsigned int bmap)
+{
+ int ret_code = 0;
+ unsigned int reset_cache_bmap, modsel_cache_bmap, reset_bmap, modsel_bmap;
+
+ if (bmap) {
+ /* Read reset,modsel status of all port from database*/
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ bms_xcvr_data_read(XCVR_RESET, &reset_cache_bmap);
+ bms_xcvr_data_read(XCVR_MODSEL, &modsel_cache_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ /* 1. Assert ResetL of the transceiver. */
+ reset_bmap = reset_cache_bmap;
+ bms_xcvr_bmap_modify( &reset_bmap, bmap, RST_EN);
+ /* 2. De-assert ModSelL of the transceiver. */
+ modsel_bmap = modsel_cache_bmap;
+ bms_xcvr_bmap_modify( &modsel_bmap, bmap, ~MODSEL_EN);
+
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_RESET, reset_bmap, reset_cache_bmap)) < 0)
+ return -1;
+ if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_MODSEL, modsel_bmap, modsel_cache_bmap)) < 0)
+ return -1;
+ bms_xcvr_data_write(XCVR_RESET, reset_bmap);
+ bms_xcvr_data_write(XCVR_MODSEL, modsel_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ /* 3. Wait 2 micro second (t_reset_init from SFF-8679). */
+ usleep(2);
+
+ /* Read reset,modsel status of all port from database*/
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ bms_xcvr_data_read(XCVR_RESET, &reset_cache_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ /* 4. De-assert ResetL of the transceiver */
+ reset_bmap = reset_cache_bmap;
+ bms_xcvr_bmap_modify( &reset_bmap, bmap, ~RST_EN);
+
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_RESET, reset_bmap, reset_cache_bmap)) < 0)
+ return -1;
+ bms_xcvr_data_write(XCVR_RESET, reset_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ bms_xcvr_bmap_to_num(bmap);
+ syslog(LOG_WARNING|LOG_USER,"Transceiver is reset, port %s .\n", bms_xcvr_bmap_to_num_str);
+ }
+ return 0;
+}
+
+/*
+ * FEATURE:
+ * main
+ * PURPOSE:
+ * initial xcvr service and handle the message queue
+ * PARAMETERS:
+ * no
+ * RETURNS:
+ * open success, this function returns .
+ * for other cases, negative errno is returned.
+ */
+int
+main(void)
+{
+ int i, ret_code = 0, unused;
+ struct sched_param sched_param = {.sched_priority = PROC_PRIORITY};
+ pthread_attr_t attr;
+ char *mq_name = xcvrirq_data[0].mq_name;
+ bms_xcvr_serv_mq_data_t msg;
+ unsigned char xcvr_bus, xcvr_read_byte, xcvr_power_class;
+ unsigned int modsel_cache_bmap, intr_msk_cache_bmap;
+ unsigned int modsel_bmap, intr_msk_bmap;
+ unsigned int xcvr_init_intr_bmap, xcvr_intr_bmap;
+ unsigned int irq_trigger_bmap, init_fail_bmap, insert_port, xcvr_init_done_bmap;
+ unsigned int xcvr_init_pass_bmap;
+ unsigned int reset_port_bmap,intr_port;
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ unsigned int lpmode_bmap, lpmode_cache_bmap;
+#endif
+
+ /* Initial of bms_irq_xcvrd */
+ /* 0. initial Mutexes */
+ if ((ret_code = bms_xcvr_mutex_init() < 0)) {
+ return ret_code;
+ }
+
+ /* 1. Set priority and parameter of this process */
+ nice(-1);
+ sched_setscheduler(0, SCHED_FIFO, &sched_param);
+
+ /* 2. Daemonize, make the process be a background daemon */
+ daemon(0 /* change working directory to root */,
+ 0 /* redirect stdin, stdout, and stderr to /dev/null */);
+
+ /* 3. Register handler for termination */
+ signal(SIGTERM, bms_xcvr_terminator);
+
+ /* 4. set default for xcvr pin status */
+ if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_RESET, RST_EN)) < 0)
+ goto quit;
+ if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_MODSEL, ~MODSEL_EN)) < 0)
+ goto quit;
+ if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_INTR_MSK, ~INTR_MASK_EN)) < 0)
+ goto quit;
+ if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_LPMODE, ~LPMODE_DIS)) < 0)
+ goto quit;
+
+ /* set default for xcvr pin cache */
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ bms_xcvr_data_write(XCVR_PRESENT, ~PRESENT_EN);
+ bms_xcvr_data_write(XCVR_RESET, RST_EN);
+ bms_xcvr_data_write(XCVR_MODSEL, ~MODSEL_EN);
+ bms_xcvr_data_write(XCVR_INTR_MSK, ~INTR_MASK_EN);
+ bms_xcvr_data_write(XCVR_INIT_DONE, INIT_DONE_DIS);
+ bms_xcvr_data_write(XCVR_LPMODE, ~LPMODE_DIS);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ /* 5. Create message queue for each interrupt service routine (ISR) */
+ for (i = 0; i < xcvrirq_data_num; i++) {
+ if (xcvrirq_data[i].mq_name) {
+ if ((ret_code = bms_xcvr_create_msq(xcvrirq_data[i].mq_name, &xcvrirq_data[i].mq_desc)) < 0) {
+ goto quit;
+ }
+ }
+ }
+
+ /* 6. Spawn interrupt service routine (ISR) daemon */
+ for (i = 0; i < xcvrirq_data_num; i++) {
+ if (xcvrirq_data[i].isrd) {
+ pthread_attr_init(&attr);
+ pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+ pthread_attr_setschedparam(&attr, &sched_param);
+ if (pthread_create(&xcvrirq_data[i].isrd_tid, &attr, xcvrirq_data[i].isrd, (void*)&xcvrirq_data[i].port_num) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to create pthread to headle transceiver interrupt (%s)\n", strerror(ret_code));
+ goto quit;
+ }
+ }
+ }
+
+ /* 6. Spawn polling daemon */
+ pthread_attr_init(&attr);
+ pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+ pthread_attr_setschedparam(&attr, &sched_param);
+ if (pthread_create(&polld_tid, &attr, bms_xcvr_polld, (void*)&unused) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to create pthread for polling transceiver present (%s)\n", strerror(ret_code));
+ goto quit;
+ }
+
+ while (1) {
+
+ /* Wait for message queue */
+ if (mq_receive(xcvrirq_data[0].mq_desc, (char*)&msg, sizeof(msg), 0) < 0) {
+ ret_code = errno;
+ syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code));
+ goto quit;
+ }
+
+ /* Handle irq_trigger_bmap */
+ irq_trigger_bmap = msg.port_bmap;
+
+ /* Read modsel,init_done status of all port from database*/
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ bms_xcvr_data_read(XCVR_MODSEL, &modsel_cache_bmap);
+ bms_xcvr_data_read(XCVR_INIT_DONE, &xcvr_init_done_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ modsel_bmap = modsel_cache_bmap;
+
+ /* Filter to xcvr_init_intr and xcvr_intr bmap by xcvr_init_done_bmap from irq_trigger_bmap */
+ xcvr_intr_bmap = xcvr_init_done_bmap & irq_trigger_bmap;
+ xcvr_init_intr_bmap = xcvr_intr_bmap ^ irq_trigger_bmap;
+
+ if ( xcvr_init_intr_bmap ) {
+
+ /* Enable modsel for xcvr init intr port*/
+ modsel_cache_bmap = modsel_bmap;
+ bms_xcvr_bmap_modify( &modsel_bmap, xcvr_init_intr_bmap, MODSEL_EN);
+
+ /* Write modsel status to xcvr pin and database */
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_MODSEL, modsel_bmap, modsel_cache_bmap)) < 0)
+ goto quit;
+ bms_xcvr_data_write(XCVR_MODSEL, modsel_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ /* Some QSFP cables have a quirk that asserts the IntN line as a side
+ * effect of power up on plug-in. We ignore this false positive
+ * interrupt until the module has finished powering up by waiting for
+ * a minimum timeout of the module inrush initialization time of
+ * 500 ms (SFF 8679 Table 5-6) to ensure the voltage rails in the
+ * module have stabilized.
+ */
+ usleep(500000);
+
+ for (i = 0, init_fail_bmap = 0, xcvr_init_pass_bmap = 0; i < xcvrirq_data_num; i++) {
+
+ insert_port = xcvr_init_intr_bmap & (((unsigned int)1) << i);
+ if (insert_port) {
+ xcvr_bus = xcvrirq_data[i].smbus_num;
+ /* read DataNotReady */
+ ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_DATA_NOT_READY, &xcvr_read_byte);
+ /* Init xcvr */
+ if (xcvr_read_byte == XCVR_READY) {
+ if (ret_code >= 0) {
+ /* 1. Read "Initialization commplete flag" bit (SFF-8636 page 0 byte 6) and the bit is introduced after SFF rev2.5 (SFF-8636 page 0 byte 221) */
+ ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_INITIALIZATION_COMPLETE_FLAG, &xcvr_read_byte);
+ }
+ if (ret_code >= 0) {
+ /* 2. Mask interrupts of the transceiver for init process */
+ ret_code = bms_xcvr_intr_mask(xcvr_bus, bms_xcvr_addr);
+ }
+ if (ret_code >= 0) {
+ /* 3. Read power class (SFF-8636 page 0 byte 129) of the transceiver */
+ ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_HIGH_POWER_CLASS, &xcvr_read_byte);
+ bms_xcvr_check_power_class(xcvr_read_byte, &xcvr_power_class);
+ if (ret_code >= 0) {
+ /* 3.1 If the transceiver's allowed max power class is 1, set 1 to "High_Power_Class_enable" bit, set 1 to "Power_override" bit, set 1 to "Power_set" bit (SFF-8636 page 0 byte 93, SFF-8679 table 5-5) */
+ if (xcvr_power_class == 1) {
+ ret_code = bms_xcvr_min_power_class(xcvr_bus, bms_xcvr_addr);
+ } else if (xcvr_power_class < 5) {
+ /* 3.2 If the transceiver's allowed max power class is 2-4, set 0 to "High_Power_Class_enable" bit, set 1 to "Power_override" bit, set 0 to "Power_set" bit (SFF-8636 page 0 byte 93, SFF-8679 table 5-5) */
+ ret_code = bms_xcvr_max_power_class(xcvr_bus, bms_xcvr_addr, XCVR_LEGACY_POWER);
+ } else {
+ /* 3.3 If the transceiver's allowed max power class is 5-7, set 1 to "High_Power_Class_enable" bit, set 1 to "Power_override" bit, set 0 to "Power_set" bit (SFF-8636 page 0 byte 93, SFF-8679 table 5-5). */
+ ret_code = bms_xcvr_max_power_class(xcvr_bus, bms_xcvr_addr, !XCVR_LEGACY_POWER);
+ }
+ }
+ }
+ /* 4. If xcvr access fail, go to (INIT FAIL) */
+ if (ret_code < 0) {
+ init_fail_bmap |= insert_port;
+ syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is ready by DataNotReady bit, but setup fail\n", i+1);
+ } else {
+ /* 5. mark xcvr_init_done_bmap for init success port */
+ xcvr_init_done_bmap |= insert_port;
+ xcvr_init_pass_bmap |= insert_port;
+ syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is ready by DataNotReady bit and setup pass\n", i+1);
+ }
+ } else {
+ init_fail_bmap |= insert_port;
+ syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is not ready and re-init\n", i+1);
+ }
+ }
+ }
+
+ /* Reset xcvr - (INIT FAIL) When "Data_Not_Ready" bit (SFF-8636 page 0 byte 2) is not ready */
+ if (bms_xcvr_reset(init_fail_bmap) < 0)
+ goto quit;
+ }
+
+ if ( xcvr_intr_bmap ) {
+
+ for (i = 0, reset_port_bmap = 0; i < xcvrirq_data_num; i++) {
+
+ intr_port = xcvr_intr_bmap & (((unsigned int)1) << i);
+ if (intr_port) {
+ xcvr_bus = xcvrirq_data[i].smbus_num;
+ ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_POWER_MODE_CONTROL, &xcvr_read_byte);
+ if (ret_code >= 0) {
+ if (!(xcvr_read_byte & XCVR_POWER_INIT_MASK)) {
+ reset_port_bmap |= intr_port;
+ /* Read "Initialization commplete flag" bit (SFF-8636 page 0 byte 6) and the bit is introduced after SFF rev2.5 (SFF-8636 page 0 byte 221) */
+ bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_INITIALIZATION_COMPLETE_FLAG, &xcvr_read_byte);
+ syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is reset by re-insert\n", i+1);
+ }
+ } else {
+ reset_port_bmap |= intr_port;
+ }
+ }
+ }
+
+ bms_xcvr_bmap_modify( &xcvr_init_done_bmap, reset_port_bmap, INIT_DONE_DIS);
+
+ if (bms_xcvr_reset(reset_port_bmap) < 0)
+ goto quit;
+
+ /* TODO : handle transceiver interrupt */
+
+ bms_xcvr_bmap_to_num(xcvr_intr_bmap);
+ syslog(LOG_DEBUG|LOG_USER,"Transceiver interrupt has handled, port %s\n", bms_xcvr_bmap_to_num_str);
+ }
+
+ /* Read intr_msk status of all port from database*/
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ bms_xcvr_data_read(XCVR_INTR_MSK, &intr_msk_cache_bmap);
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ bms_xcvr_data_read(XCVR_LPMODE, &lpmode_cache_bmap);
+#endif
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+
+ /* Disable the source that triggers the interrupt */
+ intr_msk_bmap = intr_msk_cache_bmap;
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ lpmode_bmap = lpmode_cache_bmap;
+ bms_xcvr_bmap_modify( &lpmode_bmap, xcvr_init_pass_bmap, LPMODE_DIS);
+#endif
+ bms_xcvr_bmap_modify( &intr_msk_bmap, irq_trigger_bmap, ~INTR_MASK_EN);
+
+ pthread_mutex_lock(&bms_xcvr_data_lock);
+ if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_INTR_MSK, intr_msk_bmap, intr_msk_cache_bmap)) < 0)
+ goto quit;
+#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */
+ if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_LPMODE, lpmode_bmap, lpmode_cache_bmap)) < 0)
+ goto quit;
+ bms_xcvr_data_write(XCVR_LPMODE, lpmode_bmap);
+#endif
+ bms_xcvr_data_write(XCVR_INTR_MSK, intr_msk_bmap);
+ bms_xcvr_data_write(XCVR_INIT_DONE, xcvr_init_done_bmap);
+ pthread_mutex_unlock(&bms_xcvr_data_lock);
+ }
+
+quit:
+ pthread_mutex_destroy(&bms_xcvr_data_lock);
+ syslog(LOG_DEBUG|LOG_USER,"Quit daemon %s for monitor xcvr status\n", __FILE__);
+ exit(-ret_code);
+}
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.h
new file mode 100644
index 000000000000..71985fc65bee
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.h
@@ -0,0 +1,61 @@
+#ifndef __BMS_IRQ_XCVRD_H__
+#define __BMS_IRQ_XCVRD_H__
+
+/* these defines need to be 0*/
+#define INTR_MASK_EN 0
+#define INTR_STATUS_EN 0
+#define MODSEL_EN 0
+#define RST_EN 0
+#define PRESENT_EN 0
+#define INIT_DONE_DIS 0
+#define LPMODE_DIS 0
+
+typedef int (*isr_t)(unsigned int, char*, mqd_t);
+typedef void* (*isrd_t)(void*);
+
+typedef struct {
+ unsigned int port_num;
+ char *present;
+ char *intr_src;
+ char *intr_msk;
+ char *modsel;
+ char *reset;
+ char *lpmode;
+ char *mq_name;
+ mqd_t mq_desc;
+ isr_t isr;
+ pthread_t isrd_tid;
+ isrd_t isrd;
+ unsigned char smbus_num;
+} bms_xcvr_serv_data_t;
+
+typedef struct {
+ unsigned char intr_type;
+#define INTR_TYPE_RX_INTR 1 /* Receving an interrupt */
+ unsigned int port_bmap;
+} bms_xcvr_serv_mq_data_t;
+
+enum {
+ XCVR_PRESENT = 0,
+ XCVR_MODSEL,
+ XCVR_RESET,
+ XCVR_INTR_MSK,
+ XCVR_INTR_SRC,
+ XCVR_INIT_DONE,
+ XCVR_LPMODE,
+};
+
+extern bms_xcvr_serv_data_t xcvrirq_data[];
+extern int xcvrirq_data_num;
+extern pthread_mutex_t bms_xcvr_data_lock;
+extern char bms_xcvr_bmap_to_num_str[];
+
+extern int bms_xcvr_pin_read(char *filename, unsigned int *value);
+extern void bms_xcvr_data_read(int pin_name, unsigned int *value);
+extern void bms_xcvr_data_write(int pin_name, unsigned int value);
+extern int bms_xcvr_pin_bmap_write(int pin_name, unsigned int value);
+extern int bms_xcvr_pin_bmap_modify(int pin_num, unsigned int value, unsigned int old_value);
+extern void bms_xcvr_bmap_modify(unsigned int *changed_bmap, unsigned int check_bmap, unsigned int enable_disable);
+extern void bms_xcvr_bmap_to_num(unsigned int bmap);
+
+#endif /* __BMS_IRQ_XCVRD_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd
deleted file mode 100755
index c882ff8e335a..000000000000
Binary files a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd and /dev/null differ
diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/service/ly1200-32x-platform-init.service b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/service/ly1200-32x-platform-init.service
new file mode 100644
index 000000000000..20e38495a7d5
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/service/ly1200-32x-platform-init.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Mitac ly1200_32x platform initialization service
+Before=pmon.service
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+ExecStart=/etc/init.d/sonic-platform-mitac-ly1200-32x start
+ExecStop=/etc/init.d/sonic-platform-mitac-ly1200-32x stop
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/sonic-slave-stretch/Dockerfile b/sonic-slave-stretch/Dockerfile
index d34cfda71c06..25b99b8231ff 100644
--- a/sonic-slave-stretch/Dockerfile
+++ b/sonic-slave-stretch/Dockerfile
@@ -77,6 +77,7 @@ RUN apt-get update && apt-get install -y \
stgit \
# For platform-modules build
module-assistant \
+ libi2c-dev \
# For thrift build\
gem2deb \
libboost-all-dev \